Previous: Paths

Structured Builtins

So far we've seen some basic transforms, and Paths, which let us select from other places. But we haven't been able to do anything like regular programming. That changes now.

sUTL has some basic, built in operations called "builtins". They let you do all kinds of primitive things; add numbers, manipulate dictionaries, reduce over lists. They're called builtins because they are built in to the interpreter; they are implemented directly in the host language.

This section discusses structured builtins, which work in a fairly simple way. The next section will talk about the Unstructured Builtin Evaluation Transform, which is more generic and powerful, and the builtins available to it.

Say you'd like to add a list of numbers. For this, you need the "+" builtin. eg: [ "&+", 1, 2, 3, 4 ]

The transform you are seeing above is the List Builtin Evaluation Transform. There are actually a string, list and dictionary forms.

Dictionary Form

The Dictionary Builtin Evaluation Transform is the most general builtin evaluation transform, and works like this:

{
    "&": <builtin>,
    "head": <boolean>, // evaluate to the head only? defaults to false
    "args": <list> // arguments to the builtin. defaults to []
}

evaluate applied to a dictionary builtin transform first processes it as a general dictionary transform (ie: evaluates all the values <note: there is currently a bug that this evaluation isn't happening>), then takes the args (uses an empty list if no args present) and passes them to the named builtin. It gets a result from the builtin, and either returns that result, or returns the head of the result if the result is a list, and head is set to true. 

We can multiply a list of numbers with the "x" builtin. 

List Form

The List Builtin Evaluation Transform looks like this

[
    "<op><builtin>",
    item1,
    item2,
    ...
    itemN
]

where:

  • <op> is either "^" or "&". These correspond to setting head to true or false respectively in the dictionary form.
  • <builtin> is the name of the builtin, exactly as in the dictionary form.
  • item1, item2, ..., itemN: These, in a list, are the "args" as in dictionary form.

So 

[ "&+", 1, 2, 3, 4 ]

equals

{
    "&": "+",
    "head": false,
    "args": [1, 2, 3, 4]
}

which of course evaluates to 10 in both cases.

String Form

The string form gives you an even simpler shorthand, and looks like:

"<op><builtin>" + ".<index>" (repeated zero or more times)

eg: the addition above can be written as 

"&+.1.2.3.4"

This works, but it's problematic. The interpreter has to guess at the type, and you can't express floating point numbers.

The string form is really meant for paths, which are just a form of builtin.

Required Builtins

All sUTL interpreters will include these builtins:

+ (sum or concatenate)

This builtin either operates on numbers or strings (using the first argument to decide the type). If on numbers, it adds them. If on strings, it concatenates them. It returns this result, or null if it is passed any other type.

-, x, / (other mathematical operators)

These builtins do subtraction, multiplication, and division. They are like putting the infix operator between each operand (eg: [ "&-", 5, 2, 1] is 5 - 2 - 1 = 2).

Returns null if arguments aren't all numeric.

(equality operator)

Evaluates to true iff:

  • There are two arguments exactly
  • They are the same type
  • They are equal

Otherwise it evaluates to false

!= (inequality operator)

["&!=", ...] is exactly the same as  ["&!", ["&=", ...]]

<, >, <=, >= (comparison operators)

Evaluates to true iff:

  • There are two arguments exactly
  • They are numeric
  • The first is (less than, greater than, less than or equal to, greater than or equal to) the second (respectively).

Otherwise evaluates to false.

&&, ||, ! (logical operators)

These are and, or and not operators. They operate on truthiness.

A value is considered truthy if it is not falsey. The following values are falsey:

  • false
  • null
  • 0
  • "" (the empty string)
  • [] (the empty list
  • {} (the empty dictionary)

All other values are truthy.

"&&" and "||" can have 2 or more arguments. "&&" evaluates to true if all its arguments are truthy. "||" evaluates to true if any of its arguments are truthy. 

"!" is unary (only looks at the first argument) and evaluates to true if the argument is falsey, otherwise evaluates to false.

$, @, ~, *: Path operators

See paths for detail on these.

%: The raw pathing operator

This operator wasn't mentioned in the paths page. It's used to select from a provided data structure, rather than one of the standard ones.

% is used when you've been constructing a particular object and want to select from it. It is used like the other path operators, except that the first argument isn't an index, but rather the object that you want to select from.

eg: 

transform = [
  "^%",
  {
    "person": {
      "name": "Fred"
    }
  },
  "person",
  "name"
]

evaluates to "Fred". Try it:

The string form doesn't really work for raw paths (you can't specify a complex structure inside the string). But the list and dictionary forms work well.

Next: Unstructured Builtins