Of pipes and blocks

Das is not a write-only code. The idea is we read more than we write.
There is “write as you speak”, but there is also “read as you listen”.

Picture this

verify_if_even(map(each(range(50)), @(x:int) => x+x ))

And this

(       range(50)
    |>  each()
    |>  map( @(x : int) => x + x )
    |>  verify_if_even()
)

I can read both. First one is hard. I need to flip it in my head first. Second one happens in the order its written.
Welcome to pipes.

Lets lay some more pipes

add_element(some_collection, 12)
some_collection |> add_element(12)

I can read both. First one is ever so familiar. Second one makes sense a lot more.

Even more pipes

field.init |> move_new <| clone(expr.init)

It’s a verb. Its a bit obscure, but at least I don’t have to guess what we are moving to where.

Left pipe stacks. Plus we can always skip empty bracers

take_3_elements <| 1 <| 2 <| 3

We can get silly too

1 |> take_3_elements <| 2 <| 3

Speaking of left pipe. Its mainly there for blocks.
Ruby blocks were an initial inspiration, but this days its more common than not.
So lets pipe some blocks

get_component(renderSettings) <| $(var shadow : ShadowSettings)
    shadow.powWeight = 0.6

Or better yet

renderSettings |> get_component <| $(var shadow : ShadowSettings)
    shadow.powWeight = 0.6

Lets read it. We take renderSettings. We get it’s component, which is shadow of type ShadowSettings, and then we change powWeight.

Almost good. Almost. Every time there is a right pipe and then block - we know what comes next the moment we see that pipe.
Its a block. Its always a block. Actually, sometimes it’s lambda, or local function. But you got the gist.
So lets make it even better

renderSettings |> get_component $(var shadow : ShadowSettings)
    shadow.powWeight = 0.6

Notice, no left pipe. This is new. Perhaps old syntax will go away entirely at some point. Old initialization sure will.

We can pass types

some_type_function(type<int>) $ ...
type<int> |> some_type_function() $ ...

But we can make it a type-function

[type_function]
def some_type_function ( t : auto(TT); ...

some_type_function<int> $ ...

Its the same thing. Only not really. Because ‘some_type_function’ becomes keyword, and can no longer be specialized. But it sure looks cool.
It can take multiple types

some_other_type_function_which_takes<int;float>(and,the,rest,of,the,arguments) <| of \
    <| which <| some <| are <| piped

Just like you say it.