Quotations

Being concatenative - and maybe a bit like Lisp - Xlerb code lends itself well to ‘homiconicitiy’; the idea that code can be represented in the same way it represents data.

Elixir supports this too - its AST is implemented in the same data structures you use on the day-to-day:

iex(1)> quote do
...(1)>   def square(x), do: x * x
...(1)> end
{:def, [context: Elixir, imports: [{1, Kernel}, {2, Kernel}]],
 [
   {:square, [context: Elixir], [{:x, [], Elixir}]},
   [
     do: {:*, [context: Elixir, imports: [{2, Kernel}]],
      [{:x, [], Elixir}, {:x, [], Elixir}]}
   ]
 ]}

Tuples, atoms and lists the whole way down!

This lets us do neat things like write Elixir code that manipulates Elixir code, which gives rise to its excellent macro system, and indeed the core constructs of the language itself. This is usually called ‘meta programming’ since we’re programming the code. In non-homiconic languages, you usually end up with a limited, more text-based preprocesser that’s not really aware of the code (like C for example).

Xlerb is somewhat homiconic (maybe it’s fully homiconic but I don’t really know the strict definition) - and takes inspo from both Elixir and Joy

What?

Anyway, on to some more definitions. Quotations are trains of words delimited by [ ... ] :

xlerb[0]> 200 [dup *] .s
[dup *]
200

We can invoke a quotation (run its contents) with i. Since the quotation [dup *] is on the stack, i essentially unwinds to us calling dup then *:

xlerb[2]> i .
40000
xlerb[0]>

You can think of them as little programs, which we can move around and manipulate - like sending them in messages for other processes to run, or executing them in a strange way.

Or we can do some freaky things like manipulate them directly:

xlerb[0]> [2 + 3] .s
[2 + 3]
xlerb[1]> rev .s
[3 + 2]

The word do is quite cool; it lets us run a quotation using the previous quotation as the stack:

xlerb[1]> [ swap ] .s
[swap]
[3 + 2]
xlerb[2]> do .s rev .s i .
[+ 3 2]
[2 3 +]
5
xlerb[0]>

There is a ton of different combinators we can pull out of this, like say, “rev-map” where we reverse the list, map over it, then re-reverse it:

: _ _ rev-map swap rev swap map rev ;

Quotations and manipulating code are just the tip of what we can do here. We’ll come back to quotations more when we get into talking about spawning processes, as well as case, and receive expressions.