I was playing with syntax today, specifically terse lambdas. After a brief dalliance with Smalltalk-like blocks with a Haskell-like `->`

separator, I dumped the square brackets and was left with an infix operator for lambda:

```
successor = (a → a + 1)
fib = memoize (n → if (n < 2) n (fib (n - 1) + fib (n - 2)))
apropos term = filter id
(map (f → if (find-substring term (docstring f))
(name f))
*module*)
```

I like it because it's terse without requiring any special parentheses, and it minimizes the difference between an expression and a function abstracting that expression. Like most infix operators, it gets harder to read as the expression gets bigger, but for small expressions it's great - it approaches the brevity of combinators without requiring gymnastics to convert an existing expression to a function. It's also a perfect example of the value of infix: the operator itself serves to delimit the argument list, saving a pair of parentheses.

I vaguely remember having heard of an infix lambda operator before, but casual googling does not reveal it - the results for both "infix lambda" and "lambda infix" are dominated by accidental juxtapositions. Do any of my fearsomely knowledgeable readers know whether and where this has been done before?

I haven't bothered to implement it - I know what it *does*; I'm trying to figure out what it's like to *read*. So far I've only found one significant problem: in a language which also has infix `define`

, I'm tempted to read the first argument as the name of the function. Which is just fine, but I tend to confuse the `λ`

and `named-λ`

versions.

Consider `(→ body)`

. It's obviously a nice short way to write a thunk: `(λ () body)`

. But `(f g → body)`

could be either `(λ (f g) body)`

or `(named-λ f (g) body)`

. Neither `λ`

nor `named-λ`

is more *right* than the other, but there's no reason to choose one - they are both frequently useful, so it's fine to have both. How about `→`

for `λ`

and `⇒`

for `named-λ`

, since the double arrow resembles `=`

?

There's also the `define`

/`defun`

question: for `(named-λ f (a b) body)`

, do you write `(f a b ⇒ body)`

or `(f (a b) ⇒ body)`

? In prefix syntax, I prefer a separate λ-list: I find `(defun f (x) ...)`

easier to read than `(define (f x) ...)`

, because the function name is not mixed in with the semantically different argument names. But in infix I would rather dispose of the parentheses and write the Haskell-like `f x = ...`

. This pattern holds for non-defining forms too: I like `named-λ`

to separate the name from the λ-list, but this just looks silly in infix.

The `define`

style also has the advantage that it generalizes nicely to recursive bindings of non-functions:

`endless x = (l ⇒ (lcons x l))`

Now, does that look familiar? It's the infix version of SRFI-31's `rec`

!

Update 7 Sep: It turns out C# 3.0 has infix lambda, and calls it `=>`

.

## No comments:

## Post a Comment

It's OK to comment on old posts.