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:

   1 [ file.c="...",
   2   sub=
   3   [ file.h="..." ] ]

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.