Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Evaluation Context

The most important concept in NADI is the evaluation context. This determines how your expressions are evaluated, and how everything is understood.

Variable Type

We have learned about attributes before, depending on what attribute you are setting or getting, you need to use the varible type for that.

For example, by default you set or get a local variable

x = 90
x

Results:

90

if you want to set an env variable, or network variable you need to specify. Those variable are saved as env or network attributes, and are only accessible by specifying them as variable type.

env.x = 90
env.x
net.x = 9
net.x
x

Results:

90


9

<None>

There are more varible types when you have access to a network, for example the nodes, leaves and roots are always accessible and refers to the attributes from all nodes, leaf nodes and root nodes.

network load_str("a -> b")
nodes.NAME
leaves.NAME
roots.NAME

Results:

["b", "a"]

["a"]

["b"]

And their map counterparts are also available

network load_str("a -> b")
nodesmap.NAME
leavesmap.NAME
rootsmap.NAME

Results:

{
  b = "b",
  a = "a"
}

{
  a = "a"
}

{
  b = "b"
}

You can shorten nodesmap to nm, leavesmap to lm and rootsmap to rm.

Next are the variables available only in a node context

network load_str("a -> b")
node[b].NAME
node[b] input.NAME
node[a] output.NAME
node[b] inputs.NAME
node[a] outputs.NAME

Results:

"b"

"a"

"b"

["a"]

["b"]

the inputs and outputs also have map counterparts. The singular variable type input and output error out if there are more than one, or no inputs or outputs in a node.

Context Expression

Context expression are expressions that are evaluated given a context. You can have any variable type as a context for an expression. In a way a variable is a context expression with a variable name.

Context expressions have two syntax format:

  • <context> <space> <expression>: here the expression is simple expression, and the context is only separated by a space. We have used this variation in the codes above already
  • <context> { <expression> }: here the expression can be more complex or nested with other contexts as well

For example the following three ways to set/get env expressions exist. First one directly sets and evals the environmental variable, while the bottom two do it through context expressions

env.x = 10
env.x
# or you can do
env {x = 100}
env {x}
# or you can do
env x = 200
env x

Results:

10


100


200

Be careful that, the default evaluation context is local context. The variables are local variables, and if variable type is not given, it will first try to resolve using local variables before looking at the current context.

Here, for example, we set a variable, but it can only be accessed as a local variable.

network.load_str("a -> b")
x = 12
env.x
nodes.x
network.x
x
loc.x

Results:

<None>

[<None>, <None>]

<None>

12

12

but if we are trying to evaluate in terms of some context, then the local variable will be used.

network.load_str("a -> b")
x = 12
env.x = 100
network.x = 100
env x
nodes x
network x
x
loc x

Results:

12

[12, 12]

12

12

12

Setting variables

Now that we know what context expressions are, it is important to know that while setting an attribute, we are evaluating the expression with a context.

For example, setting an environment variable means we will evaluate the right side with environment context. While setting nodes variable means we are evaluating the right side with each node as a context for all the nodes, and setting them individually.

Here, each time NAME is evaluated in the context of the current node being set, resulting in different answers set to x.

network.load_str("a -> b");
nodes.x = NAME
nodes.x

Results:

["b", "a"]

Return Value from Context Expression

By default, the context expressions return value same as the one from variable type (array and map variant).

but you can use the do keyword to tell nadi to just execute the statement and not return a value. This avoids nadi reporting None values for statements that do not return values.

network.load_str("a -> b")
nodes {
   node.x = [NAME, ORDER]
}
"no output"
nodes do {
   node.x = [NAME, ORDER]
}

Results:

[<None>, <None>]

"no output"

Multiple Context Expressions

The context expressions can have multiple statements inside of it, and you can make the expression as complex as you want.

For example, if you want sum of input nodes’s some value for all nodes:

network.load_str("a -> b");
nodes.x = 1;
nodes.y = sum(inputs.x)
nodes.y

Results:

[1, 0]

Can also be done like below, but here you need to run input nodes before the output node as you want to set the x of input nodes before you calculate y of the output node. This ordering feature from nadi allows you do simplify your calculation logic.

network.load_str("a -> b");
nodes<inp> do {
	node.x = 1;
	node.y = sum(inputs.x)
}
nodes.y

Results:

[1, 0]

Nested Context Expressions

Now that you understand context expressions, you can use them in a nested format as well if you need.

Here we do the same thing as before, but in unnecessarily complex and nested way.

network.load_str("a -> b");
nodes<inp> do {
	node.y = sum(inputs {
		node.x = 1;
		x
	})
}
nodes.y

Results:

[1, 0]