One of the fundamental concepts I’ve been working with in the Fabulator expression engine is that a set of items should be as easy to work with as a single item. However, if we know (or think) we are working with sets of items, then we can start asking different questions as soon as that set has more than one element.

Junctions are variables that act as if they are set to multiple values at the same time. The default junction (and the only one supported for now in the engine) is ‘any()’.


Instead of saying something like ‘/a[. = 1 or . = 2 or . = 3]’, a junction allows ‘/a[. = any(1,2,3)]’, which is more readable and maintainable.

You could also do something like ‘/a/*[f:name(.) = any($list-of-names)]’, though I might like ‘/a/{any($list-of-names)}’ better.

Given two sets of values, you could do comparisons such as ‘any($list-a) > any($list-b)’ to see if there’s a value in $list-a that is larger than a value in $list-b.


Another junction is ‘all()’. It is used to ensure that every value meets any requirement in a comparison. For example, ‘all($list-a) > any($list-b)’ would mean that every value in $list-a had to exceed a value in $list-b (possible a different value in $list-b for each value in $list-a). ‘all($list-a) > all($list-b)’ would be true only if the minimum value of $list-a exceeded the maximum value in $list-b.

The construct ‘/a/{all($list-of-names)}’ wouldn’t be very useful unless $list-of-names was single-valued.


The ‘none()’ junction is a bit of the opposite of ‘all()’. Instead of requiring complete agreement from all values, it requires complete non-agreement.

The expression ‘none($list-a) > none($list-b)’ would mean that no value from $list-a could exceed a value not in $list-b. Not very useful given the number of negative numbers that are less than the minimum value that could be in $list-b. Replacing one of them with an ‘all()’ or ‘any()’ would work though. ‘none($list-a) > any($list-b)’ would be true if no value in $list-a exceeded a value in $list-b (equivalent to ‘all($list-a) <= all($list-b)’).

The path ‘/a/{none($list-of-names)}’ would select all of the children of ‘/a’ that didn’t have a name in the $list-of-names.

We’re still figuring out how these will be worked into the language. They might be limited to use within predicates and tests or any ephemeral run-time processing. This is the beginning of the thinking out loud design phase.