yamlscript 2024-04-18

Last week @pez asked me if YS could be used to refactor his Calva CircleCI config.yml https://github.com/BetterThanTomorrow/calva/blob/published/.circleci/config.yml I just finished a PR for that with 30 iterative commits resulting in: https://github.com/ingydotnet/calva/blob/dev/.circleci/config.ys which evaluates to an equivalent config.yml file with:

$ make build
ys --load --yaml --ordered config.ys >> _config.yml
mv _config.yml config.yml
The README.md explains it pretty well: https://github.com/ingydotnet/calva/blob/dev/.circleci/README.md

👍 1
💯 2

Starting a thread to link elsewhere.

That's awesome

This Calva was released with YamlScript. 💪 🚀

💪 1
🎉 1

Three weeks ago, homoiconicity was just a gentlefolks' conceit. Now it is rising, reptilian, out of the drains.

💯 1

I'm late to this party, but I agree wholeheartedly with @phill. Though I wonder... Do you think "code-as-data" might be a preferable expression to "homoiconic"? To my mind "code-as-data" is the important concept and would likely result in less debates.

@phill what are you alluding to exactly? Don't want to make assumptions.

I am impressed & thrilled but most of all honored to be present at this time in history.

Because there is some serious pedantry (and I mean that in the most positive sense) about homoiconicity.

I feel the same sense of being there when something really important is happening!

But there is nothing elitist about YAML.

And while (on one hand) Lisp macros owe a lot to homoiconicity, (on the other hand) the Everyman in programming and IT does not know why they should care about macros.

But now with YamlScript, basically a self-transforming data instance, the homoiconicity shoe is completely on the other foot.

The Everyman in IT will dabble happily in YamlScript, because it is homoiconic!

1

It was a bit poetic to describe it as "homoiconicity rising up, reptilian, out of the drains"; but my powers of expression were inadequate to convey the revolution that we're on the cusp of: the abstruse concept having been plucked from the ivory towers, and offered to the IT masses: who will shortly topple all ramparts to bring it to all corners of dull-and-boring configuration. A bottom-up crash introduction of functional expression from the very people the ivory tower considered least likely!

💯 1
🔥 1

This is quite interesting I was thinking that you were saying clojure is homoiconic and the yamlscript is not. I thought about this topic quite a bit and I'm unsure whether YS is truly homoiconic and also whether a clojure is. Some differing opinions out there.

The opinions doesn’t matter so much, me thinks. 😃

This is a compilation, where =: forms transform into defs or lets. I'm not sure if this breaks homoiconicity.

$ ys -ce '
x =: 123
defn foo(y):
  z =: 321
  =>: z / y
'
(def x 123)
(+++ (defn foo [y] (let [z 321] (/ z y))))

I guess you could think of it as an elaborate macro expansion.

This is the same compilation with each of the 7 stages exposed.

$ ys -ce '
x =: 123
defn foo(y):
  z =: 321
  =>: z / y
' -d
*** parse output ***
({:+ "+MAP", :! "yamlscript/v0/code"}
 {:+ "=VAL", := "x ="}
 {:+ "=VAL", := "123"}
 {:+ "=VAL", := "defn foo(y)"}
 {:+ "+MAP"}
 {:+ "=VAL", := "z ="}
 {:+ "=VAL", := "321"}
 {:+ "=VAL", := "=>"}
 {:+ "=VAL", := "z / y"}
 {:+ "-MAP"}
 {:+ "-MAP"}
 {:+ "-DOC"})

*** compose output ***
{:! "yamlscript/v0/code",
 :%
 [{:= "x ="}
  {:= "123"}
  {:= "defn foo(y)"}
  {:% [{:= "z ="} {:= "321"} {:= "=>"} {:= "z / y"}]}]}

*** resolve output ***
{:pairs
 [{:def "x ="}
  {:exp "123"}
  {:defn "defn foo(y)"}
  {:pairs [{:def "z ="} {:exp "321"} {:exp "=>"} {:exp "z / y"}]}]}

*** build output ***
{:pairs
 [[{:Sym def} {:Sym x}]
  {:Int 123}
  [{:Sym defn} {:Sym foo} nil {:Vec [{:Sym y}]}]
  {:pairs
   [[{:Sym def} {:Sym z}]
    {:Int 321}
    {:Sym =>}
    {:Lst [{:Sym /} {:Sym z} {:Sym y}]}]}]}

*** transform output ***
{:pairs
 [[{:Sym def} {:Sym x}]
  {:Int 123}
  [{:Sym defn} {:Sym foo} nil {:Vec [{:Sym y}]}]
  {:pairs
   [[{:Sym def} {:Sym z}]
    {:Int 321}
    {:Sym =>}
    {:Lst [{:Sym /} {:Sym z} {:Sym y}]}]}]}

*** construct output ***
{:Top
 [{:Lst [{:Sym def} {:Sym x} {:Int 123}]}
  {:Lst
   [{:Sym +++}
    {:Lst
     [{:Sym defn}
      {:Sym foo}
      nil
      {:Vec [{:Sym y}]}
      {:Lst
       [{:Sym let}
        {:Vec [{:Sym z} {:Int 321}]}
        {:Lst [{:Sym /} {:Sym z} {:Sym y}]}]}]}]}]}

*** print output ***
"(def x 123)(+++ (defn foo  [y] (let [z 321] (/ z y))))"

(def x 123)
(+++ (defn foo [y] (let [z 321] (/ z y))))

It's certainly all data transformations.

👍 1

I'd like to have a solid story for yamlscript homoiconicity...

Am much too exuberant to split hairs. If YS is YAML & its data literals are YAML, then that just about does it for me, and if YS can generate data that also happens to be valid YS then that's 110%.

👍 1

I think it's a topic that will be raised in the future. Glad to have your insights 🙂

YS is and must be valid YAML. I didn't even write the first stage (parser). That's the java yaml parser snakeyaml-engine. Writing a parser is a LOT of work 🙂

snakeyaml (or maybe snakeyaml-engine) backs clj-yaml

snakeyaml -> yaml 1.1 snakeyaml-engine -> 1.2

I will likely swap out that parser later as it has edge cases spec failures. but more than good enough for now.