Skip to content

Fun with Function Tags

We've seen different ways to call YS functions in YAML.

Say we have this file.yaml:

people:
- Alice
- Bob
- Charlie

What if we wanted to reverse the list?

Tag Function Calls🔗

We could use the reverse function:

!YS-v0:
people::
  reverse::
  - Alice
  - Bob
  - Charlie

We get:

$ ys -Y file.yaml
people:
- Charlie
- Bob
- Alice

That works but it's too much work for a simple function call. We had to indent the people list, add the reverse function, and the switch to code mode with :: and back to data mode with another ::.

This is where function tag calls really shine.

!YS-v0:
people: !:reverse
- Alice
- Bob
- Charlie

We get the same result:

$ ys -Y file.yaml
people:
- Charlie
- Bob
- Alice

But all we did is add a tag. No indenting and no mode switching.

On the other hand, tag function calls are less flexible. They only take a single argument; the node that has been tagged.

Fortunately there are all sorts of ways to do whatever it is you want to do with these tag calls.

Let's explore some of them.

Chained Tags🔗

What if we wanted to sort the list in reverse?

In code mode we can chain tags like this:

!YS-v0
fruit-list =::
- Date
- Banana
- Apple
- Cherry

=>::
  fruit:: fruit-list:sort:reverse

Gives us:

$ ys -Y file.yaml
fruit-list:
- Date
- Cherry
- Banana
- Apple

It turns out we can also do this with tags, in data mode:

!YS-v0:

fruit: !:sort:reverse
- Date
- Banana
- Apple
- Cherry

We get the same result.

Could combine sort() and take(3) to get the first 3 items in sorted order?

!YS-v0:

fruit: !:sort.take(3)
- Date
- Banana
- Apple
- Cherry

Let's see what we get:

$ ys -Y file.yaml
Compile error: Invalid tag for data mode node: !:sort.take(3)

Nope.

We need a different approach.

Combining Functions🔗

Remember that in YS we can always define our own functions.

If we did that here, then no problem:

$ ys -md -Y -e '
::
  defn sort-take-3(list):
    take 3:
      sort: list

fruit: !:sort-take-3
- Date
- Banana
- Apple
- Cherry
'
fruit:
- Apple
- Banana
- Cherry

A couple things here:

Remember the -e expressions are assumed to be in code mode. Here we wanted to start in data mode, so we used -md (short for --mode=data).

In data mode we can use a :: block to inject some code.

This worked but it's too much work for such a simple task.

Luckily there's more than one way to define a YS function.

$ ys -md -Y -e '
sort-take-3 =: \(_:sort.take(3))
fruit: !:sort-take-3
- Date
- Banana
- Apple
- Cherry
'
fruit:
- Apple
- Banana
- Cherry

This is way better.

We assigned an anonymous function using our preferred chaining syntax to the sort-take-3 variable.

When you need a complex function to use as a tag, you can just define it first.

I should point out that you don't need to define the functions at the beginning of your file. You can defined them anywhere, as long as they are defined before you use them.

There's more to show you about YS function composition.

Stay tuned to the Summer of YS!

Comments