A particular idiom kept appearing in Egel since I started using `|>` to form chains of transformations, I kept introducing an abstraction to set the chain up with an unknown initial argument.
I pondered on it for a while and introduced `do` syntactic sugar into Egel. The semantics of `(do f |> g |> h) x` is `x |> f |> g |> h` for example. That allows one to abstract from superfluous variables.
It works. Below, an example taken from Advent of Code '22.
# Advent of Code (AoC) - day 5, task 2
import "prelude.eg"
import "os.ego"
import "regex.ego"
using System
using OS
using List
def input =
let L = read_line stdin in if eof stdin then {} else {L | input}
val digits = Regex::compile "[0-9]+"
def parse_crates =
do map (do unpack |> chunks 4 |> map (nth 1))
|> transpose |> map (filter ((/=) ' '))
def parse_moves =
map (do Regex::matches digits |> map to_int
|> [{M,F,T} -> (M, F, T)])
def move =
[(CC,MM) -> foldl
[CC (N,F,T) ->
CC |> insert (T - 1)
(take N (nth (F - 1) CC) ++ nth (T - 1) CC)
|> insert (F - 1)
(drop N (nth (F - 1) CC))]
CC MM ]
def main =
input |> break ((==) "")
|> [(CC,MM) -> (parse_crates (init CC), parse_moves (tail MM))]
|> move |> map head |> pack
I am not sold on the donation, the abstraction also works as a strong visual reminder that a function is being expressed. But maybe it takes some getting used to. Also, it's a nice pun on Haskell monads and a reference to an old thought of mine that all you should need is function composition to chain actions, and that later became applicatives.