Announcing Ryan

tokahuke
4 min readFeb 9, 2023

--

Say hello to Ryan!

Yeah… that's Ryan, folks!

TL; DR: A solution for big, scary configuration YAMLs and confusing CLIs that is a cross between a JSON and a Python (sort of). Try Ryan Online today! And don't forget to leave us a like!

So, I was minding my own existence the other day when somebody asked me to write a web server. Nothing big, nothing great; just a couple of routes. Naturally, this entails creating some sort of interface between my program and the outside world. You know, good old configuration: which port to listen to, which files to load from where, the address of this service and that other service, etc… Of course, the values of all these files differed depending on the environment the server was supposed to run: is it production, staging or development? Naturally, configuration files started pile up and commented configuration lines started to abound. Yes, even for a simple service as that…

Since I had some spare time during my free time, I went to my favorite search engine and asked for a solution. The oracle then proceeded to show me the whimsical world of configuration languages. I discovered wonderful things as Dhall and Jsonnet and other languages yet more obscure. These were a kind of middle-of-the-road between full programming languages, like Python, and data description formats, like JSON. Yes, you get if-elses, variables and even functions, but no, you don't get a print function or an asynchronous runtime. Oh! And your program will always evaluate to data in some data description format in the end.

If this looks like an aberration to you, hear me out: I found out that my server got much simpler in the end. It could just expect an ugly-fat JSON in a configuration file instead of having to write "amenities" for humans. All the amenities were in the configuration file, that took care of all the "configury" stuff. Besides, one single file could understand exactly what environment it was in and generate the appropriate JSON. Shorter, reusable and clear. What else can you hope for?

Alas! My happiness was short-lived:

  1. I discovered that Dhall is nice, but it's just too Haskelly for me. When I discovered that comparing strings was a no go and that even my environment variables had to be in Dhall because of that… it was too much! I don't mind esoteric stuff in in my own code, but writing for a company, things are different. And this was supposed to be just a minor and harmless stunt.
  2. The I saw Jsonnet with the blessings of Our Lord Google all over it. Much more practical, superset of JSON, etc… worked great until I had to compile it for CI. Not insurmountable, but a papercut. Then, it is completely hermetic (you need to pass parameters explicitly to it). Also, not a big deal, but another papercut. So, I ditched it before complete loss of blood set in.

In the end, I had to go with the traditional .conf file and admit defeat in my little stunt. Yet, I didn't give up: why not brew my very own?

Well, it has been a time since I wanted to use pest, the elegant parser, for something serious and this proved just the right opportunity. So, some thousands of lines of code later… Ryan was born!

Ryan was made to solve all my pet peeves with the configuration languages I tried out while still maintaining the features I liked the most. Yes, Ryan is an opinionated take on configuration languages. What did you expect from an irritable programmer? As such, Ryan features

  1. A string comparison operator. Shocking, I know!
  2. (Partial) hermeticity: the default is that Ryan can read some things from the outside world (a sensible default) , but what is read can be tweaked to no end, if one pleases. Want to read things from the internet? Want no access whatsoever? Both are possible.
  3. Type guards: not a type system, but will make most strongly-typed folks content.
  4. Loads of pattern matching! If you like match from Rust, Python, Scala (and I know you do), you will feel right at home.

Aside from that Ryan looks very much like JSON (pun intended). Actually Ryan is a superset of JSON. Also, like Dhall and unlike Jsonnet, Ryan also not Turing-complete. This is achieved (in part) by forbidding recursion; it's very hard to calculate the Fibonacci sequence in Ryan. The upside is that all Ryan code finishes eventually, which puts it nearer to an actual data description format than to a programming language.

So, where can you get a taste of Ryan? Well, there is already The Book:

And you can also fiddle with Ryan in a limited capacity in your browser, thanks to the wizardry of WASM:

And, of course, there is the central pice in all the project: the Ryan repository.

About integrating Ryan into your code, it can be as easy as, e.g., in Python

import ryan

# Read from a file
ryan.from_path("my-stuff.ryan")

# Read from a string directly
ryan.from_str('let x = 1; { "value_of_x": x }')

And you are good to go! The interface for the vanilla configuration is purposefully similar to that of a JSON or YAML library. And yes, Ryan is already available to Python, Rust and JavaScript (web).

So, tell your friends and family that their configuration woes might have gotten a bit less woeful. And, why not try Ryan today? The syntax is easy enough if know JavaScript or Python (and who doesn't these days?). It might just save you some lines of code and (perhaps) a few hours of tedious, dull, boring, monotonous and utterly mind-numbing CI debugging.

--

--