function literals cannot be class members

Steven Schveighoffer schveiguy at yahoo.com
Wed Jul 20 07:00:27 PDT 2011


On Wed, 20 Jul 2011 03:03:26 -0400, Mehrdad <wfunction at hotmail.com> wrote:

> On 7/18/2011 6:21 AM, Steven Schveighoffer wrote:
>>> I'm actually still confused at why _functions_ should be passed as  
>>> template parameters
>>
>> The beauty of alias parameters <snip>
>
> ... the beauty?
>
> Please excuse me my tone becomes a bit rant-y, but I was asking _why_,  
> and the reason is just... beauty? IMHO, it's getting pretty darn ugly...

Sorry for the confusion, "the beauty of X is..."  is a figure of speech  
that really does not necessarily have to do with beauty.  It means  
something like "the good part of it".  You can substitute the word  
"benefit" for "beauty".

As in, templates may be ugly but the benefit of using alias is...

I assure you, I was not speaking of code beauty whatsoever, I was more  
speaking of it's utility and flexibility.

> Templates are just that: *templates*. They're meant to avoid  
> __duplication of code and/or unnecessary variation in code__, by  
> providing a common style (i.e. a common *template*). Metaprogramming,  
> conditional compilation, etc. are great uses of templates, since they  
> avoid unnecessary duplication of code.
> But using them _in lieu_ of delegates is kind of pointless -- delegates  
> *already* avoid duplication of code, and aliases don't solve any  
> problems here. (I'm guessing you disagree, in which case: Can you  
> provide an example of a problem that they actually solve, aside from  
> their "beauty"?)

Yes, the entire message that you erased for this reply was my explanation  
of why it's better.

> Sure, they're beautiful, but they're ugly at the same time: they don't  
> let the code describe itself. i.e. when you say
>      void Foo(alias F)() { ... }
> the reader has **no idea whatsoever** what kind of "thing" F is (string?  
> delegate? data type?), and it gets cryptic fast. Sure, you can document  
> it, but isn't the whole point to let the code document itself? Not only  
> that, it becomes absolutely /painful/ to write completely correct  
> conditions for a template like this, when you can have multiple kinds of  
> parameters.

The problem is that the "type" of alias is described in the template  
constraints later.  It's hard to mentally associate that with the  
parameter, but it's all we have at this point.  It's almost like some  
horrible function specification syntax:

f(a, b, c) ... a: int, b: int, c:string

I.e. the requirements for the parameter are specified at a completely  
different location.  It's not something I love, but it's all we have.

> If you want to be able to pass multiple parameter types, then why not  
> just either use overloading or, if you're really concerned about  
> duplication, let the argument type be specified as a template? That  
> would remove the duplication issue.

There are other gains as well.  First, a template can optimize calls to  
that specific function, for example, a simple a < b can be inlined.   
Delegates cannot.  This is why std.algorithm.sort is (well, it should be,  
enforce is another problem) faster than the builtin array sort.  Second,  
if the delegate is pure, you'd need to overload on purity as well, so that  
doubles the overloads.  Third, even when it cannot be inlined, the code is  
specifically generated to call that function, so the call will be less  
instructions, plus the type does not have to store the delegate.

> If you're worried about simple things like "a < b", then it's because we  
> shouldn't be using a string in the first place! It's painful to write
>      foo(delegate(a, b) { return a < b; })

That also works, the string is just a nicety that makes it easy to write  
delegate literals without having to specify too much punctuation.

> but that's an easily solvable solution: Just support C#'s syntax of  
> lambdas and you instead get:
>      foo((a, b)  =>  a < b);
> which is cleaner and easy to type, and which avoids using strings for  
> code. Or you can just predefine it somewhere as a lessThan template, and  
> pass it as an argument. Either way, no strings.

I think the string solution is a means to avoid augmenting the syntax to  
support something like this.  I'm not really convinced by this argument  
that we "shouldn't be using a string".  Why not?  You have brought up no  
negatives about it except that you don't like it.  Do you have any  
substantial argument against them?

> In any case, this shouldn't be an excuse for using templates -- if  
> typing something is hard, simplifying the syntax is the answer (I'm all  
> for C# lambdas...), not using the template hammer to solve everything.

It's not an excuse, there are plenty of very good reasons to use an alias  
template parameter for a functor besides having a string functor.  I think  
if we put our heads together, we can probably come up with a good solution  
to pair this with a version that uses a stored delegate as well, for those  
cases where this doesn't work (as in the OP's example).  Such a pattern  
would be a good addition to phobos/dcollections.

-Steve


More information about the Digitalmars-d mailing list