Functionally Equivalent Language Translation →
(foreach (array-name element) ...body...) ; enumerate keys in array (foreach (array-name key value) ...body...) ; enumerate keys with values in array (foreach (array-name key (value :ref) ...body...) ; enumerate keys with mutable values
This instruction is for iterating arrays and objects. The first form enumerates the array and binds each successive element to element
. The second form provides bindings to the key and the value. The third form provides a binding to the key and a mutable binding to the value if the back-end coder supports it.
The first form of the FOREACH
instruction is used for simple enumeration of an array or object when you only want the 'values' to work with. Here's a simple example that shows how to iterate the values in an ALIST
, an associative array:
(defvar things {:name "eric" :age 46 :occupation "not sure yet"}) (foreach (things v) (emit "property: " v "\n"))
The above translates to PHP as:
$things = array('name' => "eric", 'age' => 46, 'occupation' => "not sure yet"); foreach($things as $v) { {echo $v;}}
and when piped through the PHP run-time we get the following output:
$ felt docex.felt -cw | php property: eric property: 46 property: not sure yet
and JavaScript (Node.js) as:
felt docex.felt -as nodejscoder var things = {'name' : "eric", 'age' : 46, 'occupation' : "not sure yet"}; for(var v in things) {console.log("property: "+ v+ "\n");}
And this time the output from running through a Node.js session is:
$ felt docex.felt -as nodejscoder | node property: name property: age property: occupation
Let's improve on the previous example by not only displaying the value but the name of the property (key) as well. In PHP this is easily supported using the usual "$k => $v" syntax but that's not possible in JavaScript... is it? That's one of the nice things about FELT... it does these things for you! Let's see how it works...
This is the same code as above but this time we are printing out the value of the key as well, so here is the modified FELT source code:
(defvar things {:name "eric" :age 46 :occupation "not sure yet"}) (foreach (things k v) (emit "key: " k ", property: " v "\n"))
And here is the new PHP output code:
$things = array('name' => "eric", 'age' => 46, 'occupation' => "not sure yet"); foreach($things as $k => $v) { echo "key: ", $k, ", property: ", $v, "\n"; }
And the output we get from running it.
$ felt docex.felt -cw | php key: name, property: eric key: age, property: 46 key: occupation, property: not sure yet
So let's render it as JavaScript now and see what happens, after all there is no such way of doing this as a single instruction in JavaScript, what will FELT do?
var things = {'name' : "eric", 'age' : 46, 'occupation' : "not sure yet"}; for(var k in things) { var v = things[k]; console.log("key: "+ k+ ", property: "+ v+ "\n"); }
So... the back-end coder has kindly provided some 'free code' for us, a local variable binding inside the for loop that takes the current property being iterated over and binds the key into the variable that was named in the source.
Running the above code gets us this output:
$ felt docex.felt -as nodejscoder | node key: name, property: eric key: age, property: 46 key: occupation, property: not sure yet
So you can see that we still have a functionally equivalent program, which is what FELT is all about after all.
This form is almost the same as the last but this time the 'value' binding is expressed in the same way as a function 'reference' parameter is defined, (v :ref)
... for those languages that support this feature, such as PHP, it will instruct the back-end coder that the loop will be altering the actual value within the scope of the loop. This is of course dangerous at the best of times but FELT gives you that freedom.
The sample code so far but modified to use a reference looks like this:
(defvar things {:name "eric" :age 46 :occupation "not sure yet"}) (foreach (things (v :ref)) (emit "property: " v "\n"))
The output for PHP:
$things = array('name' => "eric", 'age' => 46, 'occupation' => "not sure yet"); foreach($things as $k => &$v) { echo "key: ", $k, ", property: ", $v, "\n"; }
The output for JavaScript:
var things = {'name' : "eric", 'age' : 46, 'occupation' : "not sure yet"}; for(var k in things) { var v = things[k]; console.log("key: "+ k+ ", property: "+ v+ "\n"); }
This time FELT cannot do something that JavaScript is not capable of and so the same loop as before is generated.