How Nested Functions Work, part 1

Edward Diener eddielee_no_spam_here at tropicsoft.com
Fri Sep 4 10:33:57 PDT 2009


Andrei Alexandrescu wrote:
> Edward Diener wrote:
>> Andrei Alexandrescu wrote:
>>> Edward Diener wrote:
>>>> Andrei Alexandrescu wrote:
>>>>> Edward Diener wrote:
>>>>>> Jarrett Billingsley wrote:
>>>>>>> On Wed, Sep 2, 2009 at 9:45 AM, Andrei
>>>>>>> Alexandrescu<SeeWebsiteForEmail at erdani.org> wrote:
>>>>>>>> Jarrett Billingsley wrote:
>>>>>>>>> Well repeat should probably always take a delegate since most 
>>>>>>>>> likely,
>>>>>>>>> you're going to be passing it a lambda. However I agree that it 
>>>>>>>>> would
>>>>>>>>> be very, very nice to be able to make APIs take just delegates and
>>>>>>>>> allow functions to be implicitly cast to them. You can already 
>>>>>>>>> make
>>>>>>>>> your own thunks, but they're not going to be as efficient as 
>>>>>>>>> something
>>>>>>>>> that actually works on an ABI level.
>>>>>>>> Did someone file a bug report on this?
>>>>>>>
>>>>>>> Surprisingly, it doesn't seem like it. Walter himself, in the spec,
>>>>>>> said that "Function pointers and delegates may merge into a common
>>>>>>> syntax and be interchangeable with each other," so I just assume 
>>>>>>> that
>>>>>>> no one has found it necessary to make a report. Maybe there 
>>>>>>> should be.
>>>>>>
>>>>>> I suggested this a long time back on this NG, and I am sure many 
>>>>>> others have also. A function pointer should essentially be a 
>>>>>> delegate whose object is null. That is essentially the way 
>>>>>> delegates are in .Net. In C++, boost::Function can encompass any 
>>>>>> C++ callable type so there is little theoretical reason why D 
>>>>>> should not encompass all callable types into a delegate. Having to 
>>>>>> program for any callable type, in a functional callable or 
>>>>>> signal/slots library, by dealing with the two signature variations 
>>>>>> of a function pointer and a delegate rather than a single common 
>>>>>> signature is a real PITA in an advanced programming language.
>>>>>
>>>>> IMHO it's ok if there are two types, as long as function is 
>>>>> implicitly convertible to delegate. Function pointers have the 
>>>>> advantage that they are only one word in size, can be assigned to 
>>>>> atomically, and help interfacing with C callback APIs.
>>>>
>>>> Good point ! That would be fine also. The basic issue is to allow a 
>>>> single syntactical construct to encompass all callables in order to 
>>>> simplify code design.
>>>>
>>>> But I am still theoretically in favor of the single type, purely 
>>>> from KISS principles. The single delegate type subsumes the function 
>>>> pointer type. As far as the size savings, of course some small 
>>>> amount of memory can be saved. As far as the assigned speed, if the 
>>>> delegate type in D is as I suppose a language, and not a library, 
>>>> implementation, the language ( compiler ) can be smart enough to 
>>>> know that the programmer is assigning a function pointer to the 
>>>> delegate and make the speedier atomic assignment.
>>>>
>>>> What I imagine will happen in D is that when an updated delegate 
>>>> type allows itself to be initialized with a function pointer, the 
>>>> vast majority of D programmers will use delegate for all callables 
>>>> and the function pointer will remain simply an artefact of the 
>>>> language. Then D can eventually get rid of it <g> !
>>>>
>>>> This is analogous to the transition that will happen in C++ from 
>>>> function pointers/member function pointers to std::function in 
>>>> C++0x. Of course I never expect C++ to get rid of anything because 
>>>> some person in 3009, going back to code 100 years old and still 
>>>> supported by C++30x, still uses function pointers/member function 
>>>> pointers and the C++ standard committee deems it impermissible to 
>>>> break that code <g><g> !
>>>
>>> Actually it could be said that C++'s exercise with pointers to member 
>>> functions, which unifies a variety of functions (virtual, nonvirtual, 
>>> in a host of multiple inheritance scenario), although KISS-motivated 
>>> for the user, was at the same time a departure from C++'s usual 
>>> approach, and a disastrous one.
>>
>> Why do you think pointer to member function was a "departure from 
>> C++'s usual approach" ?
> 
> Don't pay for what you don't use, low-key approach to under-the-wraps 
> magic. The pointer to member type is the most elaborate of all C++ 
> built-in types.

If I don't use it, I don't see how I am paying for it.

> 
>> Bjarne mentioned in one of his books of having considered the C++ 
>> version of a delegate as a language construct ( taking the address of 
>> an object's member function ) sometime in the design of C++ and having 
>> rejected it. I can not remember the reason but it was evidently 
>> considered.
> 
> I'm not saying it was a decision made in ignorance. IMHO it was, 
> however, a wrong decision, and experience with pointer to member 
> functions (i.e., few even know how to write one down) supports that 
> hypothesis.

Hooking an object to a C++ pointer to member functions is not really 
rocket science syntax <g>. That they are inflexible in reusable cases, 
and need the scaffolding that at least boost::function/boost::bind 
provides to be really reuable is a given.

It is easy in retrospect to say that C++ should have gone with the 
delegate concept, as C# and D have done, but remember that C++'s origins 
  were many years ago in a Bell lab far away.

> 
>> I don't think pointer to member function is a disaster, just sometimes 
>> difficult to use, and of course very limiting. I agree I would have 
>> still liked a delegate to be part of the C++ language instead of 
>> pointer to member function, since the former is much more flexible. 
>> But std::function/std::bind ( boost::function/boost::bind or 
>> boost::lambda ) solves that problem nicely at the expense of a little 
>> more syntax but with great flexibility in binding.
> 
> "Nice" doesn't come to my mind when thinking of the above, but the 
> significant runtime cost does :o).

"Nice" in the sense of:

1) Fairly easy to understand and use.
2) A lot better than what came before <g>.

But that's another language and now D should unite all callables under 
the same delegate roof.



More information about the Digitalmars-d mailing list