You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `foreach` statement loops over a set of attributes as given by
12
-
`<attribute-reference>`. The loop can be exited early by using the
11
+
The `foreach` statement loops over values given in `<reference>`.
12
+
Each value is assigned to the given loop variable. If the loop is
13
+
done over attributes, it is also possible to get a reference to the
14
+
current attribute, either as a string reference, or an integer index.
15
+
16
+
The loop can be exited early by using the
13
17
xref:unlang/break.adoc[break] keyword.
14
18
15
19
There is no limit to how many `foreach` statements can be nested.
16
20
17
21
<key-type>::
18
22
19
-
In conjunction with `<key-name>`, an optional data type for the key or index variable. The data type should be numeric (e.g. `uint32`) for a `<reference>` which is a dynamic expansion. The data type should be `string` for a `<reference>` which is an attribute reference.
23
+
The `<key-type>` and `<key-name>` fields are optional. But if used,
24
+
both must be specified.
25
+
26
+
The `<key-type>` is the data type for the key or index variable. The data type can be numeric (e.g. `uint32`) for a `<reference>` which is a dynamic expansion or attribute reference. The data type can be `string` for an attribute reference.
20
27
21
28
<key-name>::
22
29
23
-
The name of the local variable which is used as the name of key when iterating over the attributes.
30
+
The local variable where the key refereence is placed.
24
31
25
-
For numerical data types, the key value starts off at zero (0), and increases by one every round through the loop. For `string` data types the key value is the full path to the current attribute.
32
+
For numerical data types, the key value starts off at zero (0), and
33
+
increases by one every round through the loop. For `string` data
34
+
types the key value is the full path to the current attribute.
26
35
27
36
The `<key-type>` and `<key-name>` are optional, and can be omitted.
28
37
38
+
A `<key-name>` must not be an `unlang` keyword, a module name, or
39
+
the name of an existing attribute.
40
+
29
41
<value-type>::
30
42
31
-
An optional data type for the `<value-name>` local variable. When looping over attributes, the data type can be omitted. The data type of the local variable is then taken from the attribute reference.
43
+
An optional data type for the `<value-name>` local variable. It must be a 'leaf' data type like `uint32`, or `string`, or `ipv4addr`. Structural data types like `group` or `tlv` are not allowed.
44
+
45
+
When looping over attributes, the `<value-type>` can be omitted. The
46
+
data type of the local variable is then taken automatically from the
47
+
attribute reference.
48
+
49
+
When looping over data returned from a dynamic expansion, the
50
+
`<value-type>` can sometimes be determined from the expansion.
51
+
e.g. `%range(...)` returns a `uint32`. However, if the `<value-type>`
52
+
cannot be automatically determined, then an error will be produced.
53
+
54
+
If the `<value-type>` is specified, it has to be compatible with the
55
+
data type produced by the `<reference>`. That is, the data types can
56
+
be different, but it must be possible to cast one data type to another.
32
57
33
58
<value-name>::
34
59
35
-
The name of the local variable which is used as the name of value when iterating over the attributes.
60
+
The name of the local variable which is used to store the current value when iterating over the attributes.
36
61
37
-
The local variable is created automatically when the `foreach` loop is entered, and is deleted automatically when the `foreach` loop exits.
62
+
The local variable is created automatically when the `foreach` loop is
63
+
entered, and is deleted automatically when the `foreach` loop exits.
38
64
39
-
The `<value-name>` can be modified during the course of the `foreach` loop. Modifications to the variable are copied back to the referenced attribute when the loop is done. See below for an example.
65
+
The `<value-name>` can be modified during the course of the `foreach`
66
+
loop. Modifications to the variable do not result in immediate
67
+
changes being made to any attribute being looped over. Instead, the
68
+
value is copied back to the attribute at the end of each loop
69
+
iteration.
40
70
41
-
The only limitation on the `<value-name>` is that it must be unique.
71
+
A `<value-name>` must not be an `unlang` keyword, a module name, or
72
+
the name of an existing attribute. A `<value-name>` can be reused in
73
+
different sections.
42
74
43
75
<reference>::
44
76
45
77
An xref:unlang/attr.adoc[attribute reference] which will will be looped
46
78
over. The reference can be to one attribute, to an array, a child, or
47
79
be a subset of attributes.
48
80
49
-
Alternatively, the `<reference>` can be a xref:reference:xlat/index.adoc[dynamic expansion function],
50
-
such as `%sql("SELECT ...")`. When the reference is a dynamic
51
-
expansion function, a `<value-type>` must be specified.
81
+
Alternatively, the `<reference>` can be a
82
+
xref:reference:xlat/index.adoc[dynamic expansion function], such as
83
+
`%sql("SELECT ...")`. When the reference is a dynamic expansion
84
+
function, a `<value-type>` usually needs to be specified.
52
85
53
-
== Modifying Loop variables
86
+
There is currently no way to assign _sets_ of results to a value.
87
+
That is, an SQL query can return a list of strings or IP addresses,
88
+
but it cannot return a series of rows, each of which contains a number
89
+
of columns.
54
90
55
-
When the `<reference>` is an attribute, the attribute being looped
56
-
over can sometimes be modified. When the `<reference>` is a dynamic
57
-
expansion, the results cannot be modified, and are discarded when the
58
-
`foreach` loop is finished. If it is necessary to save the results,
59
-
they should be placed into another attribute.
91
+
== Attributes Being Looped over
60
92
61
-
An attribute which is a "leaf" data type (e.g. `uint32`, and not
62
-
`tlv`) will be automatically copied back to the original attribute at
63
-
the end of each iteration of the `foreach` loop. That is, the
64
-
original attribute will still exist, and will be unmodified, during
65
-
the execution of the loop.
93
+
While it is technically possible to modify the attributes being looped
94
+
over, any modifications are over-written at the end of each loop.
95
+
96
+
Instead, any modifications should be done to the loop variable.
97
+
98
+
It is not possible to delete the attributes being looped over.
66
99
67
100
.Example of modifying values
68
101
[source,unlang]
@@ -74,7 +107,8 @@ foreach self (Tmp-Integer-0) {
74
107
}
75
108
----
76
109
77
-
Once the loop has finished , the `Tmp-Integer-0` attribute will have the following set of values.
110
+
Once the loop has finished , the `Tmp-Integer-0` attribute will have
copy attribute[i] to the key variable, or cast the attribute to the destination type
121
+
copy / cast attribute[i] to <value-name>
88
122
89
123
run loop body
90
124
91
-
if data type of attribute matches the data type of the key
92
-
copy the key variable back to attribute[i]
125
+
copy / cast <value-name> back to attribute[i]
93
126
----
94
127
95
128
=== Keys
96
129
97
-
Using a key variable allows the loop to determine exactly which attribute is being modified. Or for dynamic expansions, which of `0..n` values are being examined.
130
+
Using a key variable allows the loop to determine exactly which
131
+
attribute is being modified. Or else, which of `0..n` values are
132
+
being examined.
133
+
134
+
For attributes, the `<key-type>` must be `string` or `uint32`. When
135
+
the `string` data type is used, a reference to the attribute is placed
136
+
into the string value. e.g. `reply.Reply-Message[3]` When the
137
+
`uint32` data type is used, the index to the current loop iteration is
138
+
placed into the value, e.g. `3`.
98
139
99
-
For attributes, the `<key-type>` must be `string` or `uint32`. For dynamic expansions, it must be a numerical type such as `uint32`.
140
+
For dynamic expansions, The `<key-type> must be a numerical type such
141
+
as `uint32`. The index to the current loop iteration is placed into
142
+
the value at the beginning of each loop iteration.
A dynamic expansion can use a keyed index. If the `SELECT` statement below returns a list of `"a", "b", "c", "d"`. then we have the following example:
176
+
A dynamic expansion can use a keyed index. If the `SELECT` statement
177
+
below returns a list of `"a", "b", "c", "d"`. then we have the
178
+
following example:
134
179
135
180
.Key variable with expansion
136
181
[source,unlang]
@@ -153,9 +198,14 @@ When the loop is finished, the `total` variable will have the following value:
153
198
154
199
=== Structural Data Types
155
200
156
-
It is possible to loop over the children of a structural data type, as given in the example below. Since the loop is over the child (i.e. leaf) attributes, the values are copied back.
201
+
It is possible to loop over the children of a structural data type, as
202
+
given in the example below. Since the loop is over the child
203
+
(i.e. leaf) attributes, the values are copied back as described above.
157
204
158
-
In this example, we have to explicitly give a data type `string`. The data type is needed because there may be multiple children of the `TLV-Thing` attribute, and the children may not all have the same data type.
205
+
In this example, we have to explicitly give a data type of `string`. The
206
+
data type is needed because there may be multiple children of the
207
+
`TLV-Thing` attribute, and the children may not all have the same data
208
+
type.
159
209
160
210
.Example of Looping over children of a structural type.
0 commit comments