May 13, 2008
Yigal Chripun Wrote:

> 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.

But this is the interesting thing. Walter is a genius compiler writer and he made it happen already. Now. Your compiler has it already. And it has it in very elegant form. The point I tried many times to clarify is that Walter has done the great work already. But it is not in the documents. Maybe only Walter knows it now. And Andrei because he wrote std.algorithm exactly to use the feature.

> >> 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.

I am using standard terminology. But maybe my sentences are wrong.

> 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.

It is important because of this. Direct call is trivially inlined. Indirect call is maybe 1000 times harder to inline and sometimes impossible. By direct call I mean you know the address of the function at compilation. By indirect call I mean you have a pointer with the address of the function.

> I'm saying here that both options (the template instance and the regular
>  function) do the same regarding inlining the delegate.

This sentence is incorrect. The template instance works very different from the regular function.

> >> 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.

They are not the same thing. I have explained in other post. Thank you, Dee Girl
May 13, 2008
Dee Girl wrote:

>> 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.

exactly what I've said.
> 
> 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
> 
sure. Call it what you like, the point is that you can pass foo to a
function the same way you can pass a class method. so it's a nested
function that is automagically becomes a delegate by the compiler.
the functionality is the same.
for simplicity sake let me call it a delegate. now that we put the
terminology differences aside, we both agree about the behavior of this
D feature.
From what I know many languages behave exactly like this (turning nested
functions into delegates).

side note: I heard Walter doesn't like anything that looks or smells like pascal.

May 13, 2008
Janice Caron wrote:
> 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).

I don't like it either.
> 
> 
> 
>>  D needs to make it possible
>>  to overload built-in properties.
> 
> You can't overload something that isn't a class. Overloading requires inheritance.

either D should provide special treatment for this or it shoud use one
of the other options like removing the built-in sort.
Besides we are discussing changes to D, aren't we?

although I'm still not sure that parameterizing sort with an alias for
the delegate makes less instances than parameterizing sort with array
element type. could you explain and compare the two options in this
regard? (this of course doesn't take into account the string mixin
instances)
of course, this is secondary to the syntax issue for me.


May 13, 2008
Janice Caron wrote:
> 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.

agreed :)
May 13, 2008
Yigal Chripun Wrote:

> Dee Girl wrote:
> 
> >> 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.
> 
> exactly what I've said.
> > 
> > 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
> > 
> sure. Call it what you like, the point is that you can pass foo to a
> function the same way you can pass a class method. so it's a nested
> function that is automagically becomes a delegate by the compiler.
> the functionality is the same.
> for simplicity sake let me call it a delegate. now that we put the
> terminology differences aside, we both agree about the behavior of this
> D feature.
> From what I know many languages behave exactly like this (turning nested
> functions into delegates).

But no language I know can pass the nested function by alias. Pass by alias is fundamental different from pass by delegate. I have tried to explain it all this time. Do we agree on this now?

> side note: I heard Walter doesn't like anything that looks or smells like pascal.

Then I am sure he wish Pascal did not have nested functions ^_^ PS I installed spell check for English on emacs now, at least fewer typos! Thank you, Dee Girl

May 13, 2008
Dee Girl wrote:
 > It is important because of this. Direct call is trivially inlined.
> Indirect call is maybe 1000 times harder to inline and sometimes impossible. By direct call I mean you know the address of the function at compilation. By indirect call I mean you have a pointer with the address of the function.

again, I'll leave this to Walter to figure out. the decision to inline is and should be the compiler's.

> 
>> I'm saying here that both options (the template instance and the regular function) do the same regarding inlining the delegate.
> 
> This sentence is incorrect. The template instance works very different from the regular function.

you say that sort!(delegate) inlines the call to delegate?
in that case:
dg = dg1;
sort!(dg)(..);
dg = dg2;
sort!(dg)(..);
whould the above produce two different instances?
with classes:
class A { bool method(); }
auto a = new A;
auto b = new B;
dg = &a.method;
sort!(dg)(..);
dg = &b.method;
sort!(dg)(..);
will this produce two instances?

I understood till now that the sort!(delegate)(..) /may/ inline the
delegate but it's not a must.
on the other hand:
sort(delegate,..) currently doesn't inline but /may/ do so in the
future. in the end, both will /maybe/ provide inline capability.
if this is true I don't see any difference.


May 13, 2008
Dee Girl wrote:
> 
> But no language I know can pass the nested function by alias. Pass by alias is fundamental different from pass by delegate. I have tried to explain it all this time. Do we agree on this now?

the main thing for me is the syntax:
look at Nemerle, for example.
Here's a snippet:

class MoreFunctions {
   static run_twice (f : int -> int, v : int) : int
   {
     f (f (v))
   }

   static run_adder (x : int) : void
   {
     def f (y : int) : int { x + y }; // <==== this is a nested function
     System.Console.WriteLine ("{0}", run_twice (f, 1))
   }

   public static Run () : void
   {
     run_adder (1);
     run_adder (2);
   }
 }

look at: http://nemerle.org/Grok_Functionals for a better explanation.

> 
>> side note: I heard Walter doesn't like anything that looks or smells like pascal.
> 
> Then I am sure he wish Pascal did not have nested functions ^_^ PS I installed spell check for English on emacs now, at least fewer typos! Thank you, Dee Girl
> 
May 13, 2008
2008/5/13 Yigal Chripun <yigal100@gmail.com>:
> <snip> Lots of stuff about inlining

Please don't confuse inlining with instantiation. This does not help the discussion.

Whether or not a compiler inlines a function or not is a decision made at the call site, however the function body must still exist elsewhere in the object file, in case other functions in other modules need to call it non-inlined.

If nothing calls it non-inlined, the linker should remove it when building the executable.

This has nothing whatsoever to do with template instantiation. Inlining may or may not happen with either functions or delegates, but it has no bearing whatsoever on the "to template or not" discussion.
May 13, 2008
2008/5/13 Yigal Chripun <yigal100@gmail.com>:
>  the main thing for me is the syntax:
>  look at Nemerle, for example.
>  Here's a snippet:
>
>  class MoreFunctions {
>    static run_twice (f : int -> int, v : int) : int
>    {
>      f (f (v))
>    }
>
>    static run_adder (x : int) : void
>    {
>      def f (y : int) : int { x + y }; // <==== this is a nested function
>      System.Console.WriteLine ("{0}", run_twice (f, 1))
>    }
>
>    public static Run () : void
>    {
>      run_adder (1);
>      run_adder (2);
>    }
>   }

And the same thing in D:

    class MoreFunctions
    {
        static run_twice!(alias f)(int v)
        {
            f(f(v))
        }

        static run_adder (x : int) : void
        {
            int f(int y) { return x + y; };
            writefln("{0}", run_twice!(f)(1))
        }

        void main()
        {
            run_adder(1);
            run_adder(2);
        }
    }

What's your point?
May 13, 2008
2008/5/13 Janice Caron <caron800@googlemail.com>:
>         static run_adder (x : int) : void

Darn copy/paste errors. I meant of course

    static void run_adder(int x)