I've been using infix lambda in pseudocode for a couple of years, with mixed results. I find it very easy to write, because it's so terse, and I tend to use it for any one-argument function I can't get by partial application and simple combinators. But I find it surprisingly hard to read.
The symptom is that I mistake the parameter list for an expression. For example, in a definition like this...
gravitate bodies = map (b → accelerate b (field b bodies)) bodies
...I sometimes read the first b
as a free variable, and spend a confused moment trying to figure out where it's bound, before I notice the →
operator and realize that I'm looking at the binding occurrence. This mistake is especially easy to make in larger definitions, where it's not obvious the b
doesn't refer to some local variable I've forgotten about — and where it takes longer to see that no such variable exists.
I think the underlying problem is that the parameter list is the left argument of →
, so when I read an expression left-to-right, I encounter it before the operator. Since I haven't yet seen any hint that it's not an expression, I try to read it as one, and fail. Ordinary lambda
, in constrast, announces its specialness first, so I'm not surprised by the parameter list.
If this really is the problem, then it should also affect other operators whose left arguments aren't expressions. But there aren't many. The only one I can think of is the ubiquitous (in my pseudocode, at least) infix define
, =
, which may be less confusing because it's used in distinctive contexts (at top level or in a progn
). There are a few common operators whose right arguments are special (e.g. .
for field access), but it seems few infix operators have left arguments that aren't expressions.
What do C♯ users (at least those few who use lambda much) think? Do you have trouble reading =>
?