You can still do this though:
let result = (barbalyze(c, d, $) . foobinade(a, b, $)) input
Or if you prefer left-to-right: let result = input
|> foobinade(a, b, $)
|> barbalyze(c, d, $)
Maybe what isn't clear is that this hole operator would bind to the innermost function call, not the whole statement.This is essentially how Mathematica does it: the sugar `Foo[x,#,z]&` is semantically the same as `Function[{y}, Foo[x,y,z]]`. The `&` syntax essentially controls what hole belongs where.
Wow, this convinced me. It's so obviously the right approach when you put it this way.
Even better, this method lets you pipeline into a parameter which isn't the last one: