Here's something I write all the time in Elixir:
a =
some_list_of_tuples()
|> Enum.map(&elem(&1, 1))
|> # more pipeline here
The alternative, without De Brujin indices, is:
a =
some_list_of_tuples()
|> Enum.map(fn x -> elem(x, 1) end)
|> # more pipeline here
Are you going to tell me that the second example is
more readable? Personally, I find that the tiny little elem/2 expression gets lost in the line noise of the closure syntax. Reducing that syntax using an "anonymous closure" like in the first example makes it
clearer to me what's going on.
And, as well, in such closures, there really is no "name" for the thing that I'm processing. It's an intermediate in a destructuring expression that I'm only holding onto in order to further rip it apart. (The output has a name, say, `foo`; but if the input is just, say, `{:ok, foo}`... then what is the name of said tuple? `result`? `maybe_foo`?) Whatever name you make up there, it would only distract a future reader by making them think that it might be something important to the domain.
Oh, and also, at least in Elixir, De Brujin anonymous closures "flow well" with function handles:
&List.first/1 # function handle
&List.first(&1) # equivalent anonymous closure
---
But to put a finer point on it, in practice, 99% of the use I get out of (De Brujin) anonymous closures is just using them as "function handles but with the parameters reordered"—i.e. as a way of wrapping a closure in a combinator, without having to remember the names of combinators.
Instead, with De Brujin indices, such "combinator" effects are self-evident descriptions. Elixir code:
&(x.(&2, &1))
What is that? An expression that returns a version of the closure x (of arity 2) where the two input parameters are swapped. In other words, that's the C (cardinal) combinator, or the Haskell function `flip`. Except you don't need a special name for it; you just describe the effect you want then and there. Anyone who reads it can see what it does. Is the non-De-Brujin equivalent any clearer?
fn a, b -> x.(b, a) end
&1 and &2 are metasyntactic variables.
a and
b here are
also metasyntactic variables. There might be a better name for what they are, but frequently there isn't, if this code is e.g. sitting in a library that does something generic with a data structure or algorithm, rather than something specific with business logic.
Personally, if I'm going to be using metasyntactic variables anyway, I prefer to use ones that look different in a way that highlights them as metasyntactic variables. Just like I prefer languages that require some sigil on class-instance variables in a method to differentiate them from lexical variables. It allows both regular syntax highlighting, and the "syntax highlighter in my brain", to work more efficiently.