Skip to content

Load and Compose your YAML Files

Probably the biggest problem people have with YAML is that everything has to be in one file. Things start off nice and clean, but as requirements grow, so do your files!

What if you could compose your YAML documents like you compose your code? Lots of small, single-purpose, possibly reusable files that you can load and compose together into the thing you need?

That's what YS is all about. As you know, YS is a functional language, and it has quite a few ways to load data (and code too, since Code is Data™!) from external sources.

Today we'll be looking at how to load things from disk files, including:

  • Other YS files
  • YAML files (YAML is YS)
  • JSON files (JSON is YAML)

You can also load things from CSV/TSV files, shell commands, databases, APIs, environment variables, and the web, but those are topics for another day.

Loading YAML Files🔗

YS has a standard library function called load that can load YS files.

Since YAML is YS, you can load YAML files with load. And since JSON is YAML, you can also load JSON files with load.

Let's try on some new shoes!

We'll put each shoe in its own file.

# shoe1.yaml
name: sneaker
color: red
# shoe2.json
{
  "name": "boot",
  "color": "black"
}
# shoe3.ys
!YS-v0:
name: sandal
size:: 2 * 2 * 2

I got a little cheeky on that third shoe. I used a YS expression to calculate the size! That's just to show that YS expressions evaluate on load.

Let's load them all together.

# shoes.yaml
!YS-v0:
- ! load('shoe1.yaml')
- ! load('shoe2.json')
- ! load('shoe3.ys')

Notice the ! there? Remember the :: mode switcher?

Well :: is just a nice shorthand for !. It works great with mapping pairs, but for sequence entries, there's no way to use it, so we need to use ! instead.

$ ys -Y shoes.yaml
- name: sneaker
  color: red
- name: boot
  color: black
- name: sandal
  size: 8

It works, but we don't have the defaults in there.

We'll make a defaults file like this:

# defaults.yaml
size: 10
color: blue

Now we could use the merge key (<<) to add it to the YAML and YS files, but that would never work in a JSON file.

Fortunately, YS is a functional language with 100s of functions. Surely it has a merge function!

# shoes.yaml
!YS-v0:
- ! merge(load('defaults.yaml'), load('shoe1.yaml'))
- ! merge(load('defaults.yaml'), load('shoe2.json'))
- ! merge(load('defaults.yaml'), load('shoe3.ys'))

And then:

$ ys -Y shoes.yaml 
- size: 10
  color: red
  name: sneaker
- size: 10
  color: black
  name: boot
- size: 8
  color: blue
  name: sandal

There we go!

There's More Than One Way To Do It🔗

I was raised by Perl wolves! (well, Monks in wolf's clothing)

As we progress through the Summer of YS, you'll notice Perlisms showing up here and there. For all its warts, Perl is has a lot of gems. Maybe that's what Matz was thinking when he created Ruby and based so much of it on Perl? I've stolen many of those shiniest gems for YS.

Anyway, in YS… TMTOWTDI!


Let's rearrange our new shoes a bit:

--- !YS-v0
defaults =:
  load: 'defaults.yaml'

--- !YS-v0:
- ! defaults.merge(load('shoe1.yaml'))
- !
  merge defaults:
    load: 'shoe2.json'
- !:merge*
  - ! defaults
  - ! load('shoe3.ys')

And we get:

$ ys -Y shoes.yaml 
- size: 10
  color: red
  name: sneaker
- size: 10
  color: black
  name: boot
- size: 8
  color: blue
  name: sandal

That's a lot of new YS syntax to unpack, but the surf's up! 🏄

See you again tomorrow!

Comments