Future of string lambda functions/string predicate functions

Jakob Ovrum jakobovrum at gmail.com
Tue Aug 6 02:05:56 PDT 2013


In Phobos pull request #1453 (Implement chunkBy.)[1], the topic 
of string lambda functions has again cropped up. I think we 
should clearly decide on some things regarding them. Questions 
such as; are they a worthwhile alternative in the present 
language? Should they be deprecated? Should they be supported in 
new additions to Phobos?

Some background: string lambda functions are a feature of 
std.functional/std.range/std.algorithm, where strings can be 
passed in lieu of functions as template alias arguments to 
various public functions in these modules. The string becomes the 
return expression of an anonymous function which implicitly has 
one or two arguments, named "a" and "b", like the string "a < 3" 
in the following example expression:

   arr.filter!"a < 3"

When this feature was developed, there were no lambda function 
literals in the language. There were anonymous functions, but 
their syntactical overhead means they fare poorly as a 
replacement for lambda functions:

   arr.filter!((a) { return a < 3; })

The effect is particularly jarring in bigger compositions:

   assert([ 1, 2, 3, 4, 5 ].filter!((a) { return a < 3; 
}).equal([1, 2]));

Since then, a first-class lambda syntax has been introduced, with 
significantly less syntactic overhead:

   arr.filter!(a => a < 3)

The issue is then: is the old string lambda syntax obsolete in 
the face of the new lambda literals?

----------

My opinion on the matter is that the *only* advantage of string 
lambdas is that they are (even) shorter than the new lambda 
syntax. However, I don't think that comes even close to making up 
for its many disadvantages; here are the ones I think are the 
biggest:

  * The number one reason string lambdas are shorter is because 
they implicitly introduce their parameters. However, this means 
that you're always stuck with the generic, uninformative 
parameter names "a" and "b".
  * To the uninitiated, they may not look like code. They 
certainly aren't highlighted as D code in your average code 
editor (the q{} literal deserves a mention, but then some of the 
succinctness advantage is lost and it's not just for D code), and 
the magically, implicitly introduced variables "a" and "b" is 
something you plain just have to know beforehand to understand.
  * Apart from "a" and "b", they can only access symbols that are 
visible in the scope of the std.functional module.

In light of the above points, I just find them excessively arcane 
- something new D programmers shouldn't have to learn and thus 
none of us should continue to use or promote. The symbols you can 
access in a string lambda are determined by the implementation 
details of std.functional and thus, may change at any time. It is 
then only reasonable to recommend that the programmer should not 
depend on any symbols except for "a" and "b", severely limiting 
the utility of string lambdas. Also, they only exist in unary and 
binary forms at present, which means new functions with different 
requirements cannot leverage them. And then comes the point about 
consistency; if the utility of string lambdas is so limited in 
the face of the general lambda literal syntax, foregoing string 
lambdas in favour of lambda literals helps code consistency.

I can also think of some relatively minor disadvantages of string 
lambdas, such as the compile-time performance cost they incur.

I think string lambdas were a valiant effort to fill a glaring 
hole in the language at the time, but are now superseded by an 
overall superior alternative. The cognitive and maintenance load 
on programmers is not worth their marginal utility. I think we 
should deprecate string lambdas altogether.

Specifically, I suggest the following deprecation path:

  * Add deprecation notes to std.functional's unaryFun and 
binaryFun so users are dissuaded from using them in new code. In 
time, we would remove their documentation.
  * Leave support for string lambdas in existing Phobos functions 
for the foreseeable future, for backwards-compatibility purposes.
  * Change all documentation so that it doesn't mention string 
lambdas, whether in prose or code. Phobos pull request #707 
(Switch std.algorithm/.range to lambda syntax)[2] attempted this 
and was approved and merged, but subsequently reverted due to 
bugs.
  * New functions would not support string lambdas.

----------

To be honest, I thought this was a foregone conclusion, but 
comments on Github indicate otherwise, hence this thread.

What does everyone think?

  [1] https://github.com/D-Programming-Language/phobos/pull/1453
  [2] https://github.com/D-Programming-Language/phobos/pull/707


More information about the Digitalmars-d mailing list