Undefined variable and it/them behaviour

[it] and [them] cannot work the way it is described in The Magical It and Them Tiles, as it would be too costly and impractical to look for the last parent rule that evaluated to an object or object set, but that explanation is good enough and simplifies the way we understand how those tiles work.

This page describes how [it], [them], and more generally any output, work. It turns out that there is also a notion of undefined variable which is linked to the [it] tile, and therefore this issue is discussed in the second section of this page.

[it] and [them]
One way we could think about [it] and [them] is this: [it] and [them] are set to "nothing" at the beginning of a frame, and each time a WHEN side evaluates to an object or an object set, [them] is set to that object or object set and [it] is set to that object or the first object in the object set, for the group of lines that are indented under this WHEN. If another WHEN inside that group evaluates to a new object or object set, [it] and [them] change their value again for the inner group of lines indented under that other WHEN.

There is one pitfall, though: going to another page after a call will be considered as going outside of the lines that were under the last WHEN {object} / {object set}, and thus only the lines inside the called page count toward modifying the value of [it] and [them] inside that particular page.

Let's look at an example:

Page 1: 1 WHEN {objectA} DO [obj: test1][equals][it] 2 > WHEN [nothing] DO [obj: test2][equals][it] 3 > WHEN {objectB} DO [obj: test3][equals][it] 4 > >  WHEN DO [call page][2] 5 > WHEN DO [obj: test6][equals][it]

Page 2: 1 WHEN {objectC}[not equal to][nothing] DO [obj: test4][equals][it] 2 WHEN {objectD} DO [obj: test5][equals][it]

Color code for the value of [it] in the kode:


 * Black - not set or kode doesn't run
 * Red - objectA
 * Blue - objectB
 * Orange - objectC
 * Olive - objectD

As you can see, even though "call page" is colored in blue, the kode which runs during the call page is not colored in blue, [it] has not been set to anything. You can also point out that {objectC} [not equal to] [nothing] evaluates to a boolean, not an object, and therefore [it] is not set to objectC; this can be useful if you want to keep the previous value of [it] when testing objects or object sets, but be very careful so that you remember to write WHEN {objectC} when you want to run the kode only if {objectC} does not equal to nothing, and at the same time need the value of [it] to be changed to objectC.

For those who are interested in how it works under the hood, normally the kode should be stored as a tree, with each line of Kode being a node, and if a line B is indented under another line A, then B is the child of A, and each following child of A goes to the right of the previous child of A.

Representation of the example above using trees

The way the kode runs then is simple: it reads through the whole tree (from top to bottom, left to right) and skips a node if its WHEN condition is not satisfied; otherwise, it sets the corresponding outputs which will be valid for all descendants unless it is overwritten later because of a descendant new WHEN output.

But what does that mean exactly, and what is a tree anyway? It is a data structure, you may have heard about different data structures like lists and arrays already. But this time, it is not a "linear" way of storing information. Instead, it starts at a root node and then branches out into more nodes. Each node has one parent (except for the root), and can have one or several children (if it doesn't, it is called a leaf). That's why we use the terminology "parent line/rule" and "child line/rule" in Project Spark. You can get more information on trees on Wikipedia, or anywhere else on the internet as it is actually a very important and well-documented data structure.

Knowing what we have seen with the behaviour of call page above, we can understand what happens thanks to the trees now: each page has its own tree, and when the [call page] tile is executed, it jumps to a new tree. This explains why we observe that the values of outputs in the other page don't apply to the new called page.

One last comment about [it]/[them] and outputs in general: a consequence of the way they are set is that an output refers to the last parent rule setting this particular type of output, or the default value* in case there is no parent rule changing the output's value (*actually, as you are going to see afterwards, this is not exactly true). That's why the description of [it]/[them] in The Magical It and Them Tiles is what it is.

Undefined variable
So, now that you know exactly how [it] and [them] work, you should be able to tell very easily what the value of the "test" object variable is in the following kodes:

1st kode: WHEN [object] DO [obj: test][equals][it] WHEN DO [display][obj: test]

2nd kode: Page 1:

WHEN [object] DO [call page][2] WHEN DO [display][obj: test]

Page 2:

WHEN DO [obj: test][equals][it]

3rd kode: Page 1:

WHEN [object] DO [obj: test][equals][it] > WHEN DO [call page][2] WHEN DO [display][obj: test]

Page 2:

WHEN DO [obj: test][equals][it]

However, you probably got the first two right, but not the third one. Test it in Project Spark to see the result.

In that third kode, we see that "test" should be set to "it" the first time, but not the second time, because if you followed carefully the previous explanations, [it] is normally equal to [nothing], and therefore "test" should be set to nothing, which we see is not the case. And in fact, I can reveal that the second kode didn't work "as expected" either, as "[obj: test] [equals] [it]" did not work either, but since [object] was [nothing] in the first place, we did not see there was a problem.

So, what happened? The answer is: undefined variable.

You see, every custom variable you use has a value, even if it is undeclared, this is what is explained in the Variables. This might not be the right terminology, but I'll consider a custom variable is always defined, even if it is not declared, in the sense that it has a value and would not cause an "undefined variable" kind of error if Kode was a conventional programming language.

However, outputs are not always defined. I haven't looked at all of them, but it seems that most of them are defined even if they have not been set... except for [it]. What does that even mean? A custom variable which is not declared is not stored anywhere in the memory, but it is defined because Kode replaces the variable tile with the default value corresponding to its type. So when Kode tries to read the [it] tile in this case, the fact that it is undefined means that no value is returned (instead of the default [nothing]): the kode is simply ignored, and because the game cannot stop and there is no debugger, you are not warned about this. In the examples 2 and 3, the kode "DO [obj: test] [equals] [it]" in page 2 does not run at all, because [it] literally has no value.

I should point out that [them] works fine, it returns the default value "empty object set" if it has not been set. I believe only [it] has this issue among the outputs, which is why I think it is a bug. But there are some other situations involving undefined variables.

Indeed, we can consider the expression "{nothing} [variable]" is also an undefined variable. Again, if that is found in a kode, the line will not be run and you would have no way to know it was ignored. You should be very careful and keep that in mind, and to be clear, I'll give two examples:

1) WHEN DO [obj var: nearest goblin][equals][gallery picker: Goblin Bruiser][nearest object] WHEN [obj var: nearest goblin][bool var: attack mode] DO > WHEN DO ... >  WHEN [else] DO >  >  WHEN DO ... WHEN DO [display][txt: "Nearest goblin"][obj var: nearest goblin] WHEN DO [display][txt: "Nearest goblin HP:"][plus][obj var: nearest goblin][health]

If there is no Goblin Bruiser in your world, the child lines of "WHEN [obj var: nearest goblin] [bool var: attack mode]" won't run, even inside the [else] block! Moreover, the "Nearest goblin" text displays fine (but there is no goblin icon, as the object variable is [nothing]), but not "Nearest goblin HP:" as that second display is ignored since "[obj var: nearest goblin] [health]" is undefined.

2) WHEN [A][pressed][or][obj var: my pet][bool var: cast heal] DO [heal]

If your pet variable is [nothing] (e.g. it has not been invoked yet), then the kode won't run, even if you press A.

To fix it, you need to make sure the object variable is not [nothing] before looking at its local variables:

WHEN [A][pressed] DO [bool var: heal][equals][true] > WHEN [else][obj var: my pet] DO [bool var: heal][equals][obj var: my pet][bool var: cast heal] > >  WHEN [else] DO [bool var][equals][false] WHEN [bool var: heal] DO [heal]

That's it for the undefined variable. There may be some other case where a variable is undefined, but these (the output [it] when it hasn't been set and the expression {nothing} [variable]) are the only ones I know.

Source: Undefined variable and it/them behaviour.