greek-letter-lambda-clip-artIn our previous tutorial, we started dissecting the different types of iterators that exists in pf.lambda. In this tutorial, we will continue that exercise, and take a look at some of the other, more specialized iterators.

Siblings iterators

Some of the more useful iterators that exists in pf.lambda, are the “siblings iterators”. These guys comes in two flavors, and allows you to either retrieve an “older sibling” or a “younger sibling” from your current position. Consider this code;

_data
  foo1:error
  foo2:success
pf.console.write-line:@/../*/_data/0/+?value

The above piece of pf.lambda code, will first access the “zeroth child” of the [_data] node, for then to retrieve its “older sibling node”, due to our “+” sign at the end of our expression.

If you wish to retrieve its “older sibling’s older sibling”, you can append the integer number of “2” after the “+” sign. Any integer written out after the + sign, will define how many times older siblings it’ll retrieve. You could also write “+1” to retrieve its older sibling. However, when you wish only to retrieve its directly older sibling, the integer number is optional.

In addition, there’s a “younger sibling” iterator, which you can see an example of below;

_data
  foo1:success
  foo2:error
  foo3:error
pf.console.write-line:@/../*/_data/2/-2?value

The above code, simply retrieves the “two times younger sibling” from the second child of the [_data] node. Effectively leading to the “success” node.

Ranged iterators

Every now and then, you wish to retrieve a sub-set of your previous result, such as the second node, third node, but not the fourth node, and so on from a previous result. This is where the “ranged iterator” comes into the picture. Consider this piece of code;

_data
  foo1:error
  foo2:success
  foo3:success
  foo4:error
for-each:@/../*/_data/*/[1,3]?value
  pf.console.write-line:@/./*/__dp?value

The above piece of code, will access [foo2] and [foo3], but neither [foo1] nor [foo4]. That’s because the ranged iterator, defined through our square-brackets, will extract nodes, starting from its first integer value, and to, but not including, our last integer, where our start and end are separated by a comma.

Both the start and end integers are optional, and if omitted, will retrieve either from start of range and/or until end of range. If they both are omitted however, the iterator will have no effect of course.

Modulo iterator

Every now and then, it might be useful to access “every second node” or “every third node”, and so on, from a previous result. This is where the “modulo iterator” comes into the picture. For instance, if you wish to retrieve all the “error nodes” from a list of nodes, you could do so using this piece of code;

_data
  foo1:error
  foo2:success
  foo3:error
  foo4:success
for-each:@/../*/_data/*/%2?value
  pf.console.write-line:@/./*/__dp?value

The above code will access all “even children nodes” from the [_data] node’s children. Resulting in accessing all node’s who’s values are “error”.

The Left-Shift/Right-Shift iterators

To understand what the right-shift and left-shift iterators actually does, you must realize that pf.lambda can be both perceived as a relational tree structure, in addition to a sequential list of nodes. This makes it useful sometimes to access the “next node” instead of the “next sibling node”. Consider this code;

_data
  foo1:error
    foo2:success
  foo2:error
  foo3:success
for-each:@/../*/_data/*/[,2]/>?value
  pf.console.write-line:@/./*/__dp?value

The “right-shift iterator” in the above expression, can be found at the end of the [for-each] statement, and is defined using an “>” sign. And it basically means; “give me the ‘next node’ in the sequential list of nodes from my previous results.”

To understand the difference between the left- and right-shift iterators, and the siblings iterators, try to exchange the “>” sign above with a “+” sign, and run it through your pf.lambda executor, to see the difference in result. The concept is further explained in the video found below.

The reference iterator

Every now and then, you need to access a node “by reference”, meaning a node who can be found in the value of another node. This is especially useful when you’re using the [for-each] statement to iterate nodes, instead of values or names. Consider this code;

_data
  foo1:Hello
  foo2:World
for-each:@/../*/_data/*?node
  pf.console.write-line:"Name; {0}, Value; {1}"
    :@/././*/__dp/#?name
    :@/././*/__dp/#?value

The above piece of code, will access the [__dp] node’s value, cast it to a node, and access that node’s name and value, in the two expressions, at the bottom of the code piece above.

Every time you have a node, that’s a value of another node, and you wish to access the referenced node, as a node, you’ll need to use the “reference iterator”.

And that’s it for now, the video below though goes slightly deeper into the concepts, and hopefully clarifies any misunderstandings.