Unsolved Constant expression gets changed twice
-
Hello All,
I noticed a strange behavior with a constant expression. Here's an example:import QtQuick 2.8 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 property var a: [] onAChanged: console.log("a:", a) Item { property var b: a } }
When you run this code it outputs the following:
qml: a: [] qml: a: []
Can someone explain, why "a" gets changed twice?
If I remove the expression :
property var b: a
"a" gets only changed once as expected.
-
It get's even worse:
import QtQuick 2.8 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 property var a: [] property var b: a property var c: b onAChanged: console.log("a:", a) onBChanged: console.log("b:", b) onCChanged: console.log("c:", c) Item { property var d: c } }
Now the output is:
qml: a: [] qml: b: [] qml: c: [] qml: a: [] qml: b: [] qml: c: [] qml: b: [] qml: c: [] qml: c: []
"c" gets updated 4 times! Why?
-
No one? :-(
-
@DuBu Probably it's just how QML properties work. It's not recommended to have deep binding dependency chains anyways, and simple values (like integers or strings, not arrays or objects) seem to work more logically. If you have a real problem you have to do something about it, otherwise I think it's best to just let it be :)
-
@Eeli-K Thanks for your reply. Do you have any reference with some background informations about avoiding deep binding dependency chains?
-
@DuBu Something like that was just mentioned in the Qt docs. I think there's nothing special in it. If you have chains like a: 'x'; b: a; c: b; d: c etc. it makes the program hard to understand, error prone and difficult to debug, and as you demonstrated, possibly slower. I think usually such deep chains aren't needed. If you really need them, use them. It's about common sense.
-
@Eeli-K said in Constant expression gets changed twice:
@DuBu Something like that was just mentioned in the Qt docs. I think there's nothing special in it. If you have chains like a: 'x'; b: a; c: b; d: c etc. it makes the program hard to understand, error prone and difficult to debug, and as you demonstrated, possibly slower.
I agree. But my example is just a simplification. Here's a perhaps more practical snippet:
property var a: [] onAChanged: console.log("a:", a) Item { property var b: a onBChanged: console.log("b:", b) Item { property var c: parent.b onCChanged: console.log("c:", c) Item { property var d: parent.c onDChanged: console.log("d:", d) } } }
Think of the 3 items as standalone components.
The output is:qml: a: [] qml: b: [] qml: c: [] qml: d: [] qml: c: [] qml: d: [] qml: b: [] qml: c: [] qml: d: [] qml: a: [] qml: b: [] qml: c: [] qml: d: []
I think usually such deep chains aren't needed. If you really need them, use them. It's about common sense.
For me it's not common sense that after a correct initialization (first 4 output lines) the properties are updated up to 3 times more.
In my understanding that's what bindings are for, to know what and when to update. -
@DuBu You have to ask for example in the Qt Interest mailing list if you want to know why this actually happens, I don't know. I can just say that QML is declarative; it's meant to free you from thinking what happens inside. Therefore the inner workings are not necessarily intuitive. The problem comes from the fact that purely declarative programming isn't practical for our purposes and in QML/javascript declarative and imperative are mixed. Therefore you can accidentally bump into intricacies of declarative engine when you use something imperative. In practice what your snippet does may be like debugging a Prolog program by accident. In my opinion QML and this QML/javascript mix is far from perfect and will be superceded some day (within years or decades) but right now we have to live with strange things like this.