On Wed, 25 Feb 2009 17:19:30 +0300, Andrei Alexandrescu <[email protected]> wrote:

Jason House wrote:
Andrei Alexandrescu Wrote:
int plus(int x, int y} { return x + y; } auto plus5 =
curry!(plus)(5); assert(plus5(10) == 15);
 typeof(plus5) will be a little struct that may be cumbersome to
pass around, in which case you do want to take the toll of the
indirect call by writing:
 auto plus5 = makeDelegate(curry!(plus)(5)); assert(is(typeof(plus5)
== int delegate(int)); assert(plus5(10) == 15);
 This stuff belongs to std.functional. I plan to eliminate std.bind
and put currying and binding in std.functional. What do people
think?
 Andrei
 I've done the whole boost::bind thing before and it sucks. When
boost::lambda came out, that was way better. Anonymous delegates are
even better. Learning a separate functional syntax will always be a
sub par solution to me.

So let's see. If what you have is a function int fun(int, int) and you want to fix its first parameter to a specific value, you can write:

(int x) { return fun(42, x); }

That would be a function literal. To give it a name, you can say:

int gun(int x) { return fun(42, x); }

If you want to pass that thing around, you take &gun (or &(literal)) and transform it into a delegate. One minor issue with the above is that the syntax is rather verbose and that the relationship between the function, the parameter, and the outcome is not conceptualized. Yes, the constructs can curry any function, but you have no *notion* of currying a function. So I thought of defining such a simple notion that would allow you to write:

curry!(fun)(42)

instead of the literals above.

I don't want to offend anyone, but this syntax sucks badly.

Just compare:

auto x = (int x) { return fun(42, x); };
auto x = makeDelegate(curry!(fun)(42));

And you say that your solution is /shorter/? You must be kidding! Delegate is THE way to pass closures in D, not some functional object that has opCall(). Besides, I want my methods to be virtual and I can't afford myself a template method that accepts functional objects of any type.

bind is way *way* WAY more capable that what you propose as a replacement. It allows parameter reordering, duplication etc with a simple, uniform syntax:

auto x = bind(&fun, 42, _0);
auto y = bind(&fun, _0, 42);
auto z = bind(&fun, _1, _0);

But it's not very intuitive and easy to read:

auto q = bind(&fun, _1, bind(&fun, bind(&fun, _0, 42), _1));

Besides, it is often ambiguous:

void foo(int x, int y);
void foo(float x, int y);

auto x = makeDelegate(bind(&foo, _0, 42)); // error

With built-in D delegate syntax, there is no ambiguity and mistake:
auto x = (int x) { foo(x, 42); };

That's *the best* syntax I can think of. Just keep it and let the std.bind go. Don't waste your precious time of fixing something that isn't broken (err.. std.bind IS broken, but that's not what I was talking about :p)

In your code you are of course free to use either form as you find fit, just as you can write x * x * x or cube(x) or pow(x, 3). So I'm not sure where the sub par thing comes.

I'll go even further. If D had only what you've proposed for ranges
and std.functional but lacked opApply and anonymous delegates, I
never would have become a D user. Simple, clean syntax is that
important to me...  Please don't recreate boost and STL in D.
They're great libraries, but we can do way better than that!

This is the Usenet equivalent of a pie in the face. Wait, what? I _thought_ I'm far beyond recreating boost and STL and also that in the process I am using the full power of the language (and sometimes even more, as shown by the stream of bug reports and enhancement requests that I had to post recently). All range, functional, and algorithms do hinge on anonymous delegates (function literals in fact, which are considerably better); they don't compete with them at all, so I fail to see how one could be thought of in separation from the other. Anyhow, if you have some ideas on how we can do way better than the current trend I'm all ears. My perception, if you allow me to venture a thought, is that you are a bit confused. To paraphrase SICP, you are happy with x * x * x and are afraid that the option of writing cube(x) makes things worse.


Andrei

Reply via email to