Suppose you want to recursively remove everything with a particular name from a binding. (Perhaps you copied a directory structure into Vesta that has a bunch of subdirectories containing files used by another program that you want to keep but not be present during tool invocations or in the result.)
Simple Recursion
Here's a recursive function which does this:
1 // Recursively remove any elements from a binding and all
2 // sub-bindings with a particular name.
3 /**nocache**/
4 remove_by_name(b:binding, remove:text)
5 {
6 // Remove the specified name from b
7 b = b - [$remove=1];
8 // The variable is used to accumulate the result of this function
9 result = [];
10 // Loop over the elements of binding b
11 foreach [n=v] in b do
12 {
13 // If v is a sub-binding, call ourselves recursively to remove
14 // the specified name in sub-bindings. Otherwise,
15 v = (if _is_binding(v)
16 then remove_by_name(v, remove)
17 else v);
18 // Put the modified value into the result.
19 result = _append(result, [$n=v]);
20 };
21 return result;
22 };
Here's an example of how you might call remove_by_name:
1 a = [ CVS = [],
2 file.c = "...",
3 sub = [
4 file.h = "...",
5 CVS = []
6 ]
7 ];
8
9 b = remove_by_name(a, "CVS");
After that, the value of the variable b will be:
Using _map
Here's another way you could do this:
1 /**nocache**/
2 remove_by_name2(b:binding, remove:text)
3 {
4 /**nocache**/
5 inner(n:text, v:any)
6 {
7 return (if (n == remove)
8 then []
9 else (if _is_binding(v)
10 then [$n=_map(inner, v)]
11 else [$n=v]));
12 };
13 return _map(inner, b);
14 };
15
16 b2 = remove_by_name2(a, "CVS");
The value of the variable b2 will be the same as the value of b above.
This version will perform a little better than the first one. In many cases _map will perform a little better than foreach because each binding (or list) element is processed in an independent context, which makes for less dependency book-keeping.