May 13, 2008
Yigal Chripun Wrote:

> Dee Girl wrote:
> <snip>
> > 1. Is the code inside sort!() as powerful as delegate?
> >
> >2. Is the call inside sort direct or indirect? Thank you, Dee Girl
> 
> well, you've been answered by an expert (Thanks Sean!)

Definitely Sean is a excellent expert. But my understanding of his answer is a bit different. I see he did not know the answer to the first question. So I gave the answer to him, and he said it is something he did not know before. Then he missed the second question.

> I didn't know that Walter is working on making inlining delegates possible, that this is indeed great news. :)

I think this is great but it is much easy said than done. Inlining an indirect call means the callee must be inlined too. Or at least duplicated. There is complicated analysis that shows which indirect calls can be inlined that way. Not all can.

> to answer your questions:
> as I understand it, a delegate is internally a struct with two pointers:
> a context pointer and a function pointer. the context pointer has the
> address of the outer function for nested functions, or the this pointer
> for methods. so, when passing a delegate you pass this struct.
> based on that, I think that the answer to your second question is that
> the call is indirect.

This answer is incorrect. The call is direct. I clarify: this is not matter of optimization or tricks. It is matter of principle. It is coming from the very clever way Walter instantiates templates with alias arguments. He specializes the template at the call site. I wish I had his idea for my project but not it is too late ^_^

I think this is very important feature of the D programming language.

> this is true for both cases, otherwise that trick
> of using a sort!() instance inside a mySort function wouldn't work. all
> you pass to the template version is just a D symbol, in our case the
> name of the delegate. in both cases you need to call that delegate.

In the example I wrote it is not the name of the delegate. It is the name of nested function. It is anonymous but still has internal name.

> you can pass regular function pointers to the template too (they are written either with the function reserved word, or with the C syntax) and those are simpler to inline. you can overload a non-templated sort function to receive those as well.

If a pointer to function is passed then template function is instantiated with that pointer type. Discussion on when that can be inlined takes to another subject.

> I hope, some day function pointers would be implicitly castable to
> delegates (just make the context pointer contain null) and this will
> remove the need for providing two identical functions (one for delegates
> and one for function pointers)
> btw, another way of changing the delegate for a specific sort!()
> instance is simply to assign it; no need for a wrapper function.
> delegate bool(int a, int b) dg;
> dg = aDelegate;
> sort!(dg)(array);
> dg = otherDelegate;
> sort!(dg)(array); // the same instance should be used.

That is correct. The same instance will be used. Thank you, Dee Girl

May 13, 2008
Janice Caron Wrote:

> 2008/5/13 Dee Girl <deegirl@noreply.com>:
> >  int array[] = [1, 2, 3];
> >  int x = 5;
> >  sort!((int a, int b) { return a + x < b + x; })(array);
> >
> >  Two questions not one ^_^
> >
> >  1. Is the code inside sort!() as powerful as delegate?
> 
> The code inside sort!() /is/ a delegate. It's an anonymous delegate, but its implementation is exactly the same as a delegate with a name. It's equivalent to
> 
>     int foo (int a, int b) { return a + x < b + x; };
>     sort!(foo)(array);

Yes, excellent point. The codes are equivalent. But foo is not a delegate. It is a nested function. Like in Pascal. I am not sure how it can become delegate. Maybe Walter can answer because I see he writes here. Maybe when somebody takes address of foo. Dee Girl
May 13, 2008
Janice Caron Wrote:

> 2008/5/13 Sean Kelly <sean@invisibleduck.org>:
> >  It depends what you mean by "powerful."  Passing a comparator as a template parameter,
> >  as with sort!(), means that the choice of comparator must be made at compile-time rather
> >  than run-time.  This may be problematic in some instances.
> 
> I think you meant to say, the choice of comparator /may/ be made at compile-time. Not must.
> 
>     sort!(compare)(array); // compile time
>     sort(compare, array); // run time

Even more simple.

sort!(compare)(array);
sort!(compare)(array);

Decision depends on what compare is. Dee Girl
May 13, 2008
Janice Caron wrote:
> 2008/5/13 Yigal Chripun <yigal100@gmail.com>:
>>  I want the following API:
>>  (I don't care now for the internal implementation and the wrapper
>>  functions/aliases should be provided by the standard library)
>>
>>  array.sort; //same as array.sort(ASC);
> 
>     That one already works.
> 
>>  array.sort(DESC);
> 
>     alias std.algorithm.sort!("b<a") sort_reverse;
>     array.sort_reverse;
> 
> Is that close enough?

I want this alias in the library. I'd prefer a sort that received some enum (also incorporating the stable vs non-stable enum constants) but I can settle for this, _if_ it were present in the library. Those are the small things that make a difference. after all D does provide a string alias too.

> 
> 
>>  array.sort(someStaticComperator);
>>  array.sort(aDelegateComperator);
>>  array.someOtherfunction(params);
> 
> That will never be possible either with or without templates.
> 
> Guess why?
> 
> Well, to save you guessing, I'll tell you. It's because "sort" is a built-in property of D's dynamic arrays. (Like length and ptr are built in). In general, we can define a function foo upon arrays which can be called as either
> 
>     foo(array,otherParams);
>     array.foo(otherParams);
> 
> But unfortunately, you can't do that if the function happens to be named "sort". (Likewise "length", "ptr", "init", and so on). As I said, this is /not/ a limitation of templates.
> 
> If Walter were to remove the built-in sort property of arrays, then all of a sudden you would have:
> 
>     array.sort(someStaticComperator);
>     array.sort(aDelegateComperator);

than, either the buit-in sort needs to be removed, or enhanced (thus removing the need for the library sort), or D needs to make it possible to overload built-in properties.

> 
> which I /think/ would work, because of type-deduction. (The compiler will match it with sort!(delegate)). If it doesn't, then you could file a bugzilla report that type deduction fails, and eventually it will be fixed. In short, the solution to your problem is to REMOVE the built-in property "sort" from arrays, so that libary versions can take over.

OK, that is all I really wanted in the first place. my issue was with the syntax. if it is implemented with templates but I get to use the above syntax than I'm a 100% satisfied customer. :)

also, I didn't mention it above but this also needs to support anonymous
delegates too:
array.sort((C a, C b) {return a.val < b.val;});
I assume this works too. correct me if this is wrong.
May 13, 2008
Janice Caron wrote:
> 2008/5/13 Yigal Chripun <yigal100@gmail.com>:
>>  Good Points! I thought about the IDE issue, but I wasn't sure how the
>>  IDE handles this.
> 
> I don't have an IDE, but in my text editor,
> 
>     "a < b"
> 
> is colored like a string, but
> 
>     q{ a < b }
> 
> is colored like D code throughout. So I can choose my quoting method depending on how I want my code colored. This works, not because my IDE is smart, but precisely because it isn't! It doesn't realise that q{...} is a string, so it gets colored like code.
OK, but the point Ary made was that an IDE is smart and provides auto-complete and similar features which cannot be provided for strings.
May 13, 2008
Dee Girl wrote:
> Janice Caron Wrote:
> 
>> 2008/5/13 Dee Girl <deegirl@noreply.com>:
>>>  int array[] = [1, 2, 3];
>>>  int x = 5;
>>>  sort!((int a, int b) { return a + x < b + x; })(array);
>>>
>>>  Two questions not one ^_^
>>>
>>>  1. Is the code inside sort!() as powerful as delegate?
>> The code inside sort!() /is/ a delegate. It's an anonymous delegate, but its implementation is exactly the same as a delegate with a name. It's equivalent to
>>
>>     int foo (int a, int b) { return a + x < b + x; };
>>     sort!(foo)(array);
> 
> Yes, excellent point. The codes are equivalent. But foo is not a delegate. It is a nested function. Like in Pascal. I am not sure how it can become delegate. Maybe Walter can answer because I see he writes here. Maybe when somebody takes address of foo. Dee Girl

foo _is_ a delegate.
there is no difference: As I explained in a different post, a delegate
is simply two pointers where the context pointer either points to the
surrounding function for nested functions or to the this pointer for
methods.
May 13, 2008
2008/5/13 Yigal Chripun <yigal100@gmail.com>:
>  >     alias std.algorithm.sort!("b<a") sort_reverse;
>  >     array.sort_reverse;
>  >
>  > Is that close enough?
>
>  I want this alias in the library.

It can't be in the library, because if it were in the library it would cause the template to instantiate. We don't want it to instantiate if it's not needed.

(Currently, an alias causes instantiation, even if the alias is not subsequently used. I don't like that behaviour, but that's how it is right now).



>  D needs to make it possible
>  to overload built-in properties.

You can't overload something that isn't a class. Overloading requires inheritance.
May 13, 2008
2008/5/13 Janice Caron <caron800@googlemail.com>:
>  >  D needs to make it possible
>  >  to overload built-in properties.
>
>  You can't overload something that isn't a class. Overloading requires
>  inheritance.

My apologies - I think we both meant "override", not "overload". :-)

You can't overLOAD unless you are the author of the struct/class in question.
May 13, 2008
Dee Girl wrote:

>> I didn't know that Walter is working on making inlining delegates possible, that this is indeed great news. :)
> 
> I think this is great but it is much easy said than done. Inlining an indirect call means the callee must be inlined too. Or at least duplicated. There is complicated analysis that shows which indirect calls can be inlined that way. Not all can.
> 
OK. so what?
either way, It's the compiler/linker job to make optimizations. it sure
is more capable and has more info than I am.
I'm not implementing the D compiler, I'm using it. my POV is that of the
user. I believe Walter is a genius compiler writer and that if it's
possible he'll make it happen.

>> to answer your questions: as I understand it, a delegate is internally a struct with two pointers: a context pointer and a function pointer. the context pointer has the address of the outer function for nested functions, or the this pointer for methods. so, when passing a delegate you pass this struct. based on that, I think that the answer to your second question is that the call is indirect.
> 
> This answer is incorrect. The call is direct. I clarify: this is not matter of optimization or tricks. It is matter of principle. It is coming from the very clever way Walter instantiates templates with alias arguments. He specializes the template at the call site. I wish I had his idea for my project but not it is too late ^_^
> 
> I think this is very important feature of the D programming language.
I'm confused by your terminology. anyway, this is not really that
important to me, again I trust Walter to make the compiler produce the
best possible code.
I meant that the sort instance calls the delegate anyway and does not
inline it. I'm not sure what you mean in direct vs. indirect and why
this is important. I thought that the important thing for performance
was whether the call gets inlined or not.
I'm saying here that both options (the template instance and the regular
 function) do the same regarding inlining the delegate.
> 
> 
>> this is true for both cases, otherwise that trick of using a sort!() instance inside a mySort function wouldn't work. all you pass to the template version is just a D symbol, in our case the name of the delegate. in both cases you need to call that delegate.
>> 
> 
> In the example I wrote it is not the name of the delegate. It is the name of nested function. It is anonymous but still has internal name.
> 

see Janice's reply. effectively this is the same thing.

> 
>> you can pass regular function pointers to the template too (they are written either with the function reserved word, or with the C syntax) and those are simpler to inline. you can overload a non-templated sort function to receive those as well.
> 
> If a pointer to function is passed then template function is instantiated with that pointer type. Discussion on when that can be inlined takes to another subject.
> 
>> I hope, some day function pointers would be implicitly castable to
>> delegates (just make the context pointer contain null) and this
>> will remove the need for providing two identical functions (one for
>> delegates and one for function pointers) btw, another way of
>> changing the delegate for a specific sort!() instance is simply to
>> assign it; no need for a wrapper function. delegate bool(int a, int
>> b) dg; dg = aDelegate; sort!(dg)(array); dg = otherDelegate;
>> sort!(dg)(array); // the same instance should be used.
> 
> That is correct. The same instance will be used. Thank you, Dee Girl
> 
May 13, 2008
Yigal Chripun Wrote:

> Dee Girl wrote:
> > Janice Caron Wrote:
> > 
> >> 2008/5/13 Dee Girl <deegirl@noreply.com>:
> >>>  int array[] = [1, 2, 3];
> >>>  int x = 5;
> >>>  sort!((int a, int b) { return a + x < b + x; })(array);
> >>>
> >>>  Two questions not one ^_^
> >>>
> >>>  1. Is the code inside sort!() as powerful as delegate?
> >> The code inside sort!() /is/ a delegate. It's an anonymous delegate, but its implementation is exactly the same as a delegate with a name. It's equivalent to
> >>
> >>     int foo (int a, int b) { return a + x < b + x; };
> >>     sort!(foo)(array);
> > 
> > Yes, excellent point. The codes are equivalent. But foo is not a delegate. It is a nested function. Like in Pascal. I am not sure how it can become delegate. Maybe Walter can answer because I see he writes here. Maybe when somebody takes address of foo. Dee Girl
> 
> foo _is_ a delegate.
> there is no difference: As I explained in a different post, a delegate
> is simply two pointers where the context pointer either points to the
> surrounding function for nested functions or to the this pointer for
> methods.

It is clear what is a delegate. It is pointer to a function and pointer to environment. Like in Lisp.

But foo is not delegate. It is nested function. Like in Pascal. If you call foo from the same scope there is regular function call. Not delegate call! If you take address &foo it becomes delegate. (I just checked). D has very interesting scheme. I hope Walter writes here and confirms. But your explanation is wrong. I hope you are not offended. I am sorry, Dee Girl