YS Summer Break
When I started the Summer of YS blog series on June 1st, I committed to writing a blog post every day until September 1st (92 days in a row).
Today it's Friday, August 1st, 2025 and today's post is number 62.
It's also the last one!
When I started the Summer of YS blog series on June 1st, I committed to writing a blog post every day until September 1st (92 days in a row).
Today it's Friday, August 1st, 2025 and today's post is number 62.
It's also the last one!
The looping function that offers the most control in YS is called loop.
It's also the most verbose.
There are lots of alternatives that are more specific and require less code, but they don't let you do everything, like decide when to stop.
We'll talk about both today.
YS (being Clojure) is a functional language with immutable data structures and lazy evaluation.
Laziness is cool because you can do complicated operations on large (even infinite) sequences without having to load everything into memory.
But laziness can be very confusing when you're not used to it or you don't expect it.
YAML is a superset of JSON.
This is a basic truth about YAML.
I assume that in 2025, most people who use YAML and JSON regularly already know this.
Today I'll say a bit more about this and how it came to be.
Last Friday we got a YS program running on Go using Glojure.
Today we'll show how to run it on 3 other Clojure platforms:
ys -c compile commandLet's do a Fun FridaYS post on Sunday.
I wrote the YS one liner to open 40 random Rosetta Code tasks written in Clojure.
$ cd RosettaCodeData
$ vim $(ys -e 'sh-out("find Lang/Clojure"):lines:shuffle
.mapv(fn([d] sh-out("ls $d"):lines
.mapv(fn([f] say("$d/$f")))))' |
grep -v '\-[0-9]' |
head -40)
Pretty cool, right?
The term "YAML Schema" is a bit of unfortunate history.
It's not the YAML version of a JSON Schema.
In my opinion it needs to be renamed because it's not a schema in the typical sense of the word. The term has been part of the YAML spec since the beginning.
Let's use the term "YAML-Schema" instead of "YAML Schema" to be clear that this is not a typical schema applied to a YAML file.
Typically a schema is a set of rules that are used to validate data.
A YAML-Schema is a set of rules about how untagged nodes are implicitly tagged during the loading process.
Allow me to explain.
Yesterday I hinted at the idea of YS hosted on Go.
This doesn't mean that YS would be rewritten in Go or that it wouldn't compile to Clojure. The Lisp is still essential to YS.
Where I was going was the possibility of creating a Clojure hosted on Go, which I've been thinking about for a while.
Go is the backbone of technologies like Kubernetes, where YS wants to provide a more powerful YAML experience.
As I was getting ready for bed, the word "Glojure" popped into my head.
What a perfect name for a Go hosted Clojure!
So YS compiles to Clojure.
It also has a Clojure runtime and access to the Clojure ecosystem.
It's also written in Clojure. (It didn't have to be. The compiler could have been written in any language.)
Why Clojure?
I'll explore that topic today.
We've seen before that YS can work with YAML files that contain multiple documents. "Document" is the YAML term for a single top level node (object).
YS returns the last document in the file by default.
YS can also load all the documents in the file.
This is called streaming mode, and we'll learn more about it today.
Today I met Mike Farah, the creator of yq!
I help maintain the go-yaml YAML framework for Go, and am working with Mike to help it fix certain issues in yq.
It looks like a promising future for both go-yaml and yq.
It turns out that YS has a lot of crossovers with yq.
Let's take a closer look at how they compare.
Wouldn't it be handy to get data from shell commands in YAML?
Well you can, and it's really easy.
YS has a bunch of functions in its Standard Library for calling shell commands, and passing data to and from them.
Let's take a look...
YAML has a Core Development Team of five people that I am a member of.
In May 2024, 4 of us met in Berlin. One of the things we did was to write a list of best practices for YAML. We came up with a list of 40 or so things that we all agreed on.
Today I'll share some of those with you.
Did you know that in YAML you can write:
? foo
: bar
instead of:
foo: bar
The ? is called an explicit key indicator.
But why would you want to use it?
It's not often useful in YAML config files, but it is actually useful in YS code.
On Friday June 27th we found a task on Rosetta Code and converted the Clojure solution to YS.
Let's do that again today.
What is the syntax for comments in YS?
Well that's simple.
YS code is YAML, so the comment syntax is the same as YAML.
Well, there's a little bit more to it than that.
I'll say it again. All YS syntax is 100% YAML. The YS compiler uses a third party YAML parser so there is no way that YS code cannot be YAML.
YS code also uses a lot of Clojure syntax. This makes sense since the code gets compiled to Clojure in the end.
Some Clojure code looks a lot like YAML but with subtle differences.
Today we'll talk about the little gotchas that can trip you up when you're writing YS code, and how to work around them.
In functional programming, currying is a technique where a function that takes multiple arguments is called with fewer arguments than it takes and returns a function that takes the remaining arguments.
In Clojure and YS, the partial function is used to create a curried function.
Here's an example:
$ ys -e '
multiply-by-6 =: partial(mul 6)
multiply-by-7 =: mul.partial(7)
say: multiply-by-6(7)
say: multiply-by-7(6)
'
42
42
That's neat but how is it useful in YAML configs?
I've said it before, but YS code is 100% valid YAML.
Here's a YS program:
!ys-0
say: 'You say Goodbye'
say: 'I say Hello'
YAML says that mapping keys must be unique.
That program seems to be a YAML mapping with two keys that are the same.
How can this be valid YAML?
Yesterday we talked about writing tests in YS.
We also introduced the ys::taptest library, but we didn't really cover how it
works.
Let's take a closer look...
YS is a great language for writing tests in.
Why?
Well tests are mostly data. Inputs and outputs for some code you want to test. Code is usually in functions, and functions usually have names and names are just strings and strings are just data.
YAML is a great format for data. YS is YAML with code (expressed as YAML data).
So it seems like YS should be a great language for writing tests in. And it is.
YS is a YAML loader module. On one hand it does have super powers, but on the other hand it's just a plain YAML loader.
A YAML loader is a utility that can turn YAML into a data structure. Every modern language has a YAML loader. Most have many.
YS is the first YAML loader that was made for every programming language.
Well that's the goal anyway.
For the past year it's only had loaders for 11 languages: Clojure, Crystal, Go, Java, Julia, NodeJS, Perl, Python, Raku, Ruby, and Rust.
Until this week, that is...
Try running these commands on Linux or Mac:
git clone https://github.com/yaml/yamlscript
cd yamlscript
make install
Chances are that everything will just work.
You'll have new builds of ~/.local/ys and ~/.local/lib/libys.so (.dylib on
a Mac).
YS actually has a lot of heavy dependencies like Clojure, Java, Maven, GraalVM, etc.
So how does it just work?
Today I'll tell you!
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?
The current version of YS as of today is 0.2.1.
I'm sure you've noticed the -0 part of the !ys-0 tag by now.
YS intends to be a "versioned programming language", where v2 can behave
very differently from v1 while still being able to use v1 libraries and
such.
Today I'll tell you a bit more about the versioning and how things are expected to work.
Remember, we are still officially at v0 so even the rules of how versioning
works are not yet set in stone!