grauzone wrote:
Consider you have this code:
> map!("a*3")(a)
Now you see that you forgot something! For some reason, you actually
need to return absolute values! Uh-oh, let's fix that:
> map!("fabs(a*3)")(a)
Oops, this doesn't work. fabs() isn't available, because the code is
compiled inside the standard library, and not the module, where the code
was written. This is confusing and non-intuitive. Even more, you don't
have _any_ way to access fabs() in this code (except if std.algorithm
imports std.math). You'll have to rewrite this line of code somehow.
Maybe turn it into a delegate. But then you lose the performance benefit
you had before. What to do now? Looks like this simple issue caused more
work than you thought! And all this even though the predicate is simple
and trivial!
Lest a misunderstanding arises, the code:
auto r = map!((float a) { return fabs(a); })(a);
does *not* involve a delegate; it's still a direct call. This code
doesn't currently compile because of a bug in the compiler, but this
equivalent code does:
float fun(float a) { return fabs(a); }
auto r = map!(fun)(a);
and again it does not involve a delegate.
I don't see how this is simple and elegant. Looks more like a hack. It
reminds me a bit of C++, where things first look simple, but actually...
they really aren't.
But I get Don's and Andrei's points. End of discussion, I guess.
Whereas I reckon in the beginning you weren't fully aware of the
flexibility offered by pass-by-alias, you brought some good points. The
functionality afforded by strings can be improved by importing more
modules inside std.functional. I just added std.math and std.contracts.
At the end of the day std.functional could include the entire Phobos
(you'd be surprised how fast that compiles). I agree that that's not
elegant, but let's not forget that strings are just that - an
*additional* convenience to the many conveniences that pass-by-alias
imparts.
Andrei