www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How Nested Functions Work, part 1

reply Walter Bright <newshound1 digitalmars.com> writes:
http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/
Aug 30 2009
next sibling parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Walter Bright Wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

I really like the way nested functions and closures are done in D. Especially because they are the same thing as delegate and closures. But speaking of closures, I did notice something that could be optimized: void foo { int a; void foo2() { a++;} bar(&foo2); } void bar(in void delegate() dg) { dg(); } Here foo() is using _d_allocmemory to get storage for the stack frame. I understand it is for cases where the closure is executed long after the owner method has returned, but if the delegate has a scope storage class it could use the thread's stack instead. Using nested functions alone does use the stack for storage, unless you need to use a local delegate to fix forward references within nested functions resulting in _d_allocmemory allocating the stack frame, as in the following example: void myFoo() { int a; scope void delegate() bar = void; void foo() { bar(); } void foo2() { a++; if(a != 10) foo(); } bar = &foo2; foo(); } Closures in D is an amazing feature and I really miss it when I need to use another language (I can't find an employer who wants D code, but I keep my fingers crossed!), but here is yet another feature I try to avoid in time critical code right now because of the expensive call into the memory manager when I can write longer code that executes on stack storage. Anywho, thanks for the link Walter, I'm not really familiar with C# and it's nice to know D beats its syntax, I would hate to have to assign delegates for every nested function!
Aug 30 2009
next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sun, Aug 30, 2009 at 9:00 PM, Jeremie Pelletier<jeremiep gmail.com> wrot=
e:
 Walter Bright Wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_=


 I really like the way nested functions and closures are done in D. Especi=

 But speaking of closures, I did notice something that could be optimized:

 void foo {
 =A0 =A0int a;
 =A0 =A0void foo2() { a++;}
 =A0 =A0bar(&foo2);
 }
 void bar(in void delegate() dg) { dg(); }

 Here foo() is using _d_allocmemory to get storage for the stack frame. I =

er method has returned, but if the delegate has a scope storage class it co= uld use the thread's stack instead. It already is optimized if you use "void bar(scope void delegate() dg)". If it doesn't optimize it when you use 'in', it's probably a bug. :)
Aug 30 2009
parent Jeremie Pelletier <jeremiep gmail.com> writes:
Jarrett Billingsley Wrote:

 On Sun, Aug 30, 2009 at 9:00 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:
 Walter Bright Wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

I really like the way nested functions and closures are done in D. Especially because they are the same thing as delegate and closures. But speaking of closures, I did notice something that could be optimized: void foo {    int a;    void foo2() { a++;}    bar(&foo2); } void bar(in void delegate() dg) { dg(); } Here foo() is using _d_allocmemory to get storage for the stack frame. I understand it is for cases where the closure is executed long after the owner method has returned, but if the delegate has a scope storage class it could use the thread's stack instead.

It already is optimized if you use "void bar(scope void delegate() dg)". If it doesn't optimize it when you use 'in', it's probably a bug. :)

I need to try that out, its most likely a bug since 'in' means 'const scope' now. Check my second code bit, the delegate is declared as scope and it doesn't optimize, maybe the compiler only checks if the closure is being dereferenced and if so switches to memory storage instead of stack storage without checking the storage class of the closure's delegate. And even without 'scope' in this case the compiler could detect that the delegate doesn't leave the function scope and optimize away. Better yet, allow forward references for nested functions. The need to assign closures to delegates to get a nested function is so C# ;)
Aug 30 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
That's very nice, could you post that on reddit?
Aug 30 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Walter Bright Wrote:

 That's very nice, could you post that on reddit?

Just did, I even changed "D" to "the D programming language" because I know you like it for search engine referencing :) http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/c0cm3bk
Aug 31 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Thanks!
Aug 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. Andrei
Aug 31 2009
next sibling parent Jeremie Pelletier <jeremiep gmail.com> writes:
Andrei Alexandrescu Wrote:

 Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. Andrei

Am I the only one here using web-news?
Aug 31 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Some of us read the NG via email, not a newsreader.

Thunderbird email has an option to view emails in a threaded form.
Aug 31 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 I don't think gmail can do that.
 Anyway, pretty much Walter is the only one here who regularly writes
 replies with absolutely no context, so it's not a huge problem.

I try to counterbalance the person(s) who quote a 90 line message and add a single sentence at the end!
Aug 31 2009
parent "Manfred_Nowak" <svv1999 hotmail.com> writes:
Walter Bright wrote:

 I try to 

rofl :-) -manfred
Sep 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sun, Aug 30, 2009 at 10:54 PM, Jeremie Pelletier<jeremiep gmail.com> wro=
te:
 I need to try that out, its most likely a bug since 'in' means 'const sco=

 Check my second code bit, the delegate is declared as scope and it doesn'=

nced and if so switches to memory storage instead of stack storage without = checking the storage class of the closure's delegate. And even without 'sco= pe' in this case the compiler could detect that the delegate doesn't leave = the function scope and optimize away. The compiler currently doesn't do anything with local delegates declared with 'scope'. It only seems to do anything special if 'scope' is used as a parameter storage class.
 Better yet, allow forward references for nested functions. The need to as=

Oh indeed ;)
Aug 30 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Aug 31, 2009 at 1:14 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Aug 31, 2009 at 1:11 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is.

Some of us read the NG via email, not a newsreader. --bb
Aug 31 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Aug 31, 2009 at 01:57:41PM -0700, Bill Baxter wrote:
 Some of us read the NG via email, not a newsreader.

My email client (mutt) can do threading on it too. You might want to check the settings on your mail reader and see if you have a threading option - the necessary headers are in the messages. (That said, I agree that quoting the relevant part of messages is preferable, since I don't often use the threading mode and just read the messages as they come in.)
 
 --bb

-- Adam D. Ruppe http://arsdnet.net
Aug 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Aug 31, 2009 at 2:05 PM, Adam D. Ruppe<destructionator gmail.com> wrote:
 On Mon, Aug 31, 2009 at 01:57:41PM -0700, Bill Baxter wrote:
 Some of us read the NG via email, not a newsreader.

My email client (mutt) can do threading on it too. You might want to check the settings on your mail reader and see if you have a threading option - the necessary headers are in the messages.

I don't think gmail can do that. Anyway, pretty much Walter is the only one here who regularly writes replies with absolutely no context, so it's not a huge problem. --bb
Aug 31 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Aug 31, 2009 at 4:11 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is.

I said I'm using the mailing lists ;)
Aug 31 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Aug 31, 2009 at 6:30 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:
 Andrei Alexandrescu Wrote:

 Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. Andrei

Am I the only one here using web-news?

Probably. It's full of fail.
Aug 31 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Aug 31, 2009 at 3:30 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:
 Andrei Alexandrescu Wrote:

 Jarrett Billingsley wrote:
 On Mon, Aug 31, 2009 at 1:14 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Thanks!

I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.

Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. Andrei

Am I the only one here using web-news?

Most people give up on the web-news interface after a week or two, if they intend to stick around for a while, at least. --bb
Aug 31 2009
prev sibling next sibling parent Tim M <tim.matthews7 gmail.com> writes:
Walter Bright Wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

Have had a quick look through. You could have explained that D supports closures and how the implementation supports it. Also looked in to C# before complaining about it not semantically supporting of nested functions but why C# doesn't allow the same syntax too? Who knows?
Aug 31 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 30 Aug 2009 17:34:36 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

Am I missing something or did you repeat the "Let's rewrite abc and def in C to illustrate the semantics" part at the end? Is there something different I'm supposed to be reading? -Steve
Aug 31 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 Am I missing something or did you repeat the "Let's rewrite abc and def 
 in C to illustrate the semantics" part at the end?  Is there something 
 different I'm supposed to be reading?

Eh, you're right.
Aug 31 2009
prev sibling next sibling parent reply language_fan <foo bar.com.invalid> writes:
Sun, 30 Aug 2009 14:34:36 -0700, Walter Bright thusly wrote:

 http://www.reddit.com/r/programming/comments/9fk6g/

This seems more like an advertisement of D than practical new information for compiler construction. Nesting functions is the basic feature of functional languages. Moreover even procedural Algol based languages such as Pascal have always supported them, too. This information is also taught in basic university level compiler courses. Now that I checked what wikipedia had to say to the matter, it also seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature <foo>' always equals 'innovation'.
Aug 31 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
language_fan wrote:
 This seems more like an advertisement of D than practical new information 
 for compiler construction. Nesting functions is the basic feature of 
 functional languages. Moreover even procedural Algol based languages such 
 as Pascal have always supported them, too.

But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.
 This information is also 
 taught in basic university level compiler courses.

I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.
 Now that I checked what wikipedia had to say to the matter, it also 
 seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature 
 <foo>' always equals 'innovation'.

Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order. In part 2, I'll cover innovative things D does with nested functions.
Aug 31 2009
next sibling parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Walter Bright Wrote:

 language_fan wrote:
 This seems more like an advertisement of D than practical new information 
 for compiler construction. Nesting functions is the basic feature of 
 functional languages. Moreover even procedural Algol based languages such 
 as Pascal have always supported them, too.

But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.
 This information is also 
 taught in basic university level compiler courses.

I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.
 Now that I checked what wikipedia had to say to the matter, it also 
 seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature 
 <foo>' always equals 'innovation'.

Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order. In part 2, I'll cover innovative things D does with nested functions.

I agree with Walter here. While D is not the first place I see closures and nested functions, it is the first language I come across that blends delegates, closures and nested functions in a simple, elegant and intuitive manner. PHP for one does not support closures at all, and delegates are done using the ugly array(object => 'method') syntax. JavaScript works like C#; you have to assign a closure to a delegate value to get a nested function. C/C++ also don't support closures, and delegates must be manually handled (function ptr + void* param) with very little support from many existing APIs (win32 is especially bad for that as it only uses static callbacks). Its no surprise that I was literally drooling when I first read about how D does it, I had just spent a few weeks doing jQuery in JavaScript for a client back then and fell in love with closures, D had it all with better syntax :) In D you can even send a function pointer to a delegate value!
Aug 31 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Nick Sabalausky:
 Quick! For each of these, valid or invalid?:

I may like this one: import std.stdio: writeln; import d.templates: IsCallable; void repeat(TyCall)(int n, TyCall callme) if (IsCallable!TyCall) { foreach (i; 0 .. n) callme(i); } void main() { repeat(5, (int i){ writeln("hi"); }); } It works if callme is a delegate, function pointer or callable object, and gives good error messages otherwise. The bad thing is that currently the LDC compiler has not enough semantics to inline that delegate. If you need more performance you can use the template trick(s) used by std.algorithm of Phobos2. Bye, bearophile
Sep 02 2009
parent bearophile <bearophileHUGS lycos.com> writes:
If the loop index "i" isn't necessary, you can use simpler code:

import std.stdio: writeln;

void repeat(TF)(int n, lazy TF callme) {
    foreach (i; 0 .. n)
        callme();
}

void main() {
    repeat(5, writeln("hi"));
}

Bye,
bearophile
Sep 02 2009
prev sibling next sibling parent Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= <jmjmak utu.fi.invalid> writes:
Nick Sabalausky wrote:

 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message
 news:h7h5i1$5mp$1 digitalmars.com...
 While D is not the first place I see closures and nested functions, it is
 the first language I come across that blends delegates, closures and
 nested functions in a simple, elegant and intuitive manner.

I almost agree. But not quite. D certainly handles much of it better than a lot of languages, and the syntax of the *actual* nested functions is nice. But there are still issues that bug the hell out of me.

 Quick! For each of these, valid or invalid?:
 
 // A ////////////////////////
 void repeat(int n, delegate void(int i) dg)
 {
     foreach(int i; 0..n)
         dg(i);
 }
 repeat(5, delegate void(int i) { writefln("hi"); });
 
 // B ////////////////////////
 void repeat(int n, void delegate(int i) dg)
 {
     foreach(int i; 0..n)
         dg(i);
 }
 repeat(5, void delegate(int i) { writefln("hi"); });
 
 // C ////////////////////////
 void repeat(int n, delegate void(int i) dg)
 {
     foreach(int i; 0..n)
         dg(i);
 }
 repeat(5, void delegate(int i) { writefln("hi"); });
 
 // D ////////////////////////
 void repeat(int n, void delegate(int i) dg)
 {
     foreach(int i; 0..n)
         dg(i);
 }
 repeat(5, delegate void(int i) { writefln("hi"); });
 

Also keep in mind that to increase confusion, D still supports the old style C syntax for functions. It's true that when you make a distinction between delegates, functions, nested functions and lambdas, all kinds of inconsistencies may crop up. For example the above example is much simpler in Scala (but of course scalac doesn't produce efficient native code): def foo(i: Int) = println("hi") class c { def bar(i: Int) = println("hi") } object obj extends c def scope = { def lambda = { i: Int => println("hi") } def repeat(n: Int, dg: Int => Unit) = 0.to(n-1).foreach { dg (_) } repeat(5, foo) repeat(5, obj.bar) repeat(5, (new c).bar) repeat(5, lambda) repeat(5, { i: Int => println("hi") }) } As you can see, whatever you try to do, the type system cleanly stays out of the way.
Sep 02 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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? Andrei
Sep 02 2009
parent reply Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
Jarrett Billingsley wrote:
 On Wed, Sep 2, 2009 at 9:45 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail 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.


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.
Sep 02 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Edward Diener wrote:
 Jarrett Billingsley wrote:
 On Wed, Sep 2, 2009 at 9:45 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail 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.


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. Andrei
Sep 03 2009
parent reply Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
Andrei Alexandrescu wrote:
 Edward Diener wrote:
 Jarrett Billingsley wrote:
 On Wed, Sep 2, 2009 at 9:45 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail 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.


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> !
Sep 03 2009
next sibling parent grauzone <none example.net> writes:
Jarrett Billingsley wrote:
 On Thu, Sep 3, 2009 at 6:48 PM, Edward
 Diener<eddielee_no_spam_here tropicsoft.com> wrote:
 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> !

There's no real reason to get rid of function pointers. What type would the .funcptr property of a delegate be, if function pointers

Probably the same type as .ptr? And by the way, I find it really strange, that .funcptr results into an incorrectly typed function pointer, that basically has the wrong calling convention for the destination code, which usually is a method. It'd be different if signature of the .funcptr included an explicit argument for the hidden pointers. So that you could write: dg.funcptr(dg.ptr, arguments);
 didn't exist? You also need them for C compatibility.

And that's about the only reason to keep them. But wouldn't it be possible for the compiler to allow assignment of a function pointer to a delegate? All the compiler had to do is to generate a hidden dispatch method to "translate" the different calling conventions. The delegate's .funcptr points to that dispatch function, and the dispatch function call the actual function. If the assigned function pointer is not a statically known function (but from a variable), the function address could be stored in the delegate's .ptr. Would this work?
Sep 03 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Edward Diener wrote:
 Andrei Alexandrescu wrote:
 Edward Diener wrote:
 Jarrett Billingsley wrote:
 On Wed, Sep 2, 2009 at 9:45 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail 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.


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. Andrei
Sep 03 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Edward Diener wrote:
 Andrei Alexandrescu wrote:
 Edward Diener wrote:
 Jarrett Billingsley wrote:
 On Wed, Sep 2, 2009 at 9:45 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail 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.


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. Andrei
Sep 03 2009
parent reply Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
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 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.


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" ? 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 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.
Sep 03 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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 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.


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.
 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.
 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). Andrei
Sep 03 2009
next sibling parent Don <nospam nospam.com> writes:
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 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.


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.

No kidding. When writing my "Member function pointers" CodeProject article [1], it seemed that nobody had truly documented the extent of their grotesqueness before. And during the course of writing that article, I noticed that the compiler vendor with the sanest implementation also had an alternative language called D... [1] http://www.codeproject.com/KB/cpp/FastDelegate.aspx BTW: I've just discovered that my article is referenced from the C++ FQA, with a prominent note: "WARNING: this stuff can be used to scare little children." <g>
Sep 04 2009
prev sibling parent Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
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 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.


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.
Sep 04 2009
prev sibling next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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.

The problem is that function pointers and delegates have different calling conventions. You *might* be able to rig up an asm stub that compensated for the difference... not sure. As it stands, you can just use a function to create the delegate stub for you; doesn't even require a heap allocation! http://gist.github.com/140507
Sep 02 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Jarrett Billingsley wrote:
 ...
 
 void foob(T: Ret function(Args), Ret, Args...)(T func)
 {
 	pragma(msg, ParameterTupleOf!(T).stringof);
 	static void wtf(ParameterTupleOf!(T) args) {}
 	pragma(msg, ParameterTupleOf!(T).stringof);
 }
 
 void blah(int, ref float) {}
 
 void aojkjas()
 {
 	foob(&blah);
 }
 
 Okay, look at foob's body. Both pragmas should print out the same thing, no?
 
 They don't.
 
 They print:
 
 (int, ref float)
 (int _param_0, float _param_1)
 
 WHAT. For one, where did the 'ref' go? For two, where did the names
 come from? Also, if you look at typeof(&wtf), it's also missing the
 ref.

Yeah, I've noticed this, too. Parameter tuples are just outright screwed.
 I'd really, really like to replace your entire module with this:
 
 Ret delegate(Args) toDg(T: Ret function(Args), Ret, Args...)(T func)
 {
 	struct Wrap
 	{
 		T mFunc;
 
 		Ret call(Args args)
 		{
 			return (cast(T)this)(args);
 		}
 	}
 
 	Ret delegate(Args) dg;
 	Wrap wrap;
 	dg.ptr = func;
 	dg.funcptr = &wrap.call;
 	return dg;
 }

You and me both. That said, this code is ported from an experimental library for binding D to lua; it used something similar to detect ref and out and change the function signature (outs became multiple returns, for example).
Sep 02 2009
prev sibling parent Jeremie Pelletier <jeremiep gmail.com> writes:
Nick Sabalausky Wrote:

 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h7h5i1$5mp$1 digitalmars.com...
 While D is not the first place I see closures and nested functions, it is 
 the first language I come across that blends delegates, closures and 
 nested functions in a simple, elegant and intuitive manner.

I almost agree. But not quite. D certainly handles much of it better than a lot of languages, and the syntax of the *actual* nested functions is nice. But there are still issues that bug the hell out of me. For instance, it's fairly common for me, in D, to write a function that takes a delegate and then call it with a delegate literal (anon func). But out of all the times I've done that, I don't think there's been a single time I haven't had to go look up the syntax. And here's why: bool delegate(int a) delegate bool(int a) Umm, yea. If you don't already know what I'm getting at with that, then... Quick! For each of these, valid or invalid?: // D //////////////////////// void repeat(int n, void delegate(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, delegate void(int i) { writefln("hi"); }); ////////////////////////// And now the secondary question: Which, if any, of those instances of "delegate" should be changed to "function"? (I know it's not a real serious problem, but the thing is, 99.9% of the time, I don't care, and more importantly, I don't *want* to care whether or not there's a scope being passed around with the...whatever it is.) So...If you could correctly, and confidently, identify the correct answers without hesitation, especially on the first part, well...then you've got a far better mind than I do.

The only valid syntax is up there, and you could use a simple closure instead of a delegate literal. As for function pointers, you can send a function pointer to a delegate value, the context only gets set to null and the method calls with a null "this", but calls nonetheless. I almost only use delegates in D, since it allows functions pointers, delegates, closures and nested functions to be passed. Function pointers only allow function pointers, but are useful for C compatibility. I almost never use delegate literals since closures can be used instead, even with a return value (works like 'auto' return values). void foo(bool delegate() dg) { dg(); } foo({return true;});
Sep 02 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
language_fan wrote:
 For what it's worth, they also seem somewhat buggy in D. Hopefully 
 writing the articles motivates fixing those issues :) For example one 
 can't call symbols before their declaration on non-global scope.

That's actually not a bug. In function scopes, you can't reference a variable before use, either.
Aug 31 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Walter Bright Wrote:

 language_fan wrote:
 For what it's worth, they also seem somewhat buggy in D. Hopefully 
 writing the articles motivates fixing those issues :) For example one 
 can't call symbols before their declaration on non-global scope.

That's actually not a bug. In function scopes, you can't reference a variable before use, either.

You have to agree however that this is counter-intuitive, since functions in D can be used before they are declared, yet nested functions cant. While it follows the convention used by local variables, this isnt the same, local variables need storage, the nested functions merely need a pointer to the stack frame. Also, using delegates to dereference a nested function so it can be used as a prototype (which to me feels more like a hack than a feature) forces the entire stack frame to be allocated in _d_allocmemory. Nested functions should be parsed in the same pass as their parent method, fixing the need to use delegates which also needlessly use 8bytes in the stack frame.
Aug 31 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
I agree it would be better to allow forward references for nested 
functions, I just wished to point out that the current behavior is not a 
bug, it was built that way.
Aug 31 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
language_fan wrote:

 I agree it would be better to allow forward references for nested
 functions, I just wished to point out that the current behavior is not a
 bug, it was built that way.

That's great news actually. It might even mean that this might change some day.

I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc. -- Michiel Helvensteijn
Sep 02 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Michiel Helvensteijn wrote:
 I still find it silly that it was built that way. Seems to me you should be
 able to forward-reference *any* symbol that has a value that can't change
 over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.

That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; } -- Rainer Deyke - rainerd eldwood.com
Sep 02 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Rainer Deyke wrote:

 I still find it silly that it was built that way. Seems to me you should
 be able to forward-reference *any* symbol that has a value that can't
 change over its lifetime. Functions, const/immutable vars, typedefs,
 classes, etc.

That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; }

You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-) -- Michiel Helvensteijn
Sep 02 2009
parent reply Don <nospam nospam.com> writes:
Michiel Helvensteijn wrote:
 Rainer Deyke wrote:
 
 I still find it silly that it was built that way. Seems to me you should
 be able to forward-reference *any* symbol that has a value that can't
 change over its lifetime. Functions, const/immutable vars, typedefs,
 classes, etc.

int i = f(); int f() { return i; }

You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-)

constructing a dependency tree of top-level symbols. Pass over the tree, evaluating everything which is a leaf of the tree. If you have a pass where you don't succeed in removing any leaf nodes, you have a circular dependency. DMD sort of does this, I think, but it only does two passes, and it's not very good at backing out when it discovers something is not a leaf. It'd be hard to make that efficient when there are potentially infinite passes.
Sep 02 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Jarrett Billingsley wrote:

 It wouldn't even be that difficult. Basically if you treat
 forward-referenced nested functions as a sort of goto, the same rules
 should apply: a call to a nested function may not skip the
 initialization of any variables it depends on. When i's initializer is
 evaluated, it has not been declared yet, so the call to f is illegal.
 It also prevents other invalid use.

That's what I meant, yes. Basically, any function that reads i may not be called before i is declared, nor in i's initialization. Of course, in reality, it depends on the control flow within the function. But that's holy grail stuff. So: conservatively. -- Michiel Helvensteijn
Sep 02 2009
parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Michiel Helvensteijn wrote:

 Basically, any function that reads i may not be called before i is
 declared, nor in i's initialization. Of course, in reality, it depends on
 the control flow within the function. But that's holy grail stuff. So:
 conservatively.

Oh, you may also not take a delegate of the function before i is declared. Same reason. -- Michiel Helvensteijn
Sep 02 2009
prev sibling next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 language_fan wrote:
 This information is also taught in basic university level compiler 
 courses.

I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.

Some universities don't even have compiler classes. Mine only covered basic parsing. Thanks for the article, Walter! :) -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Aug 31 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Tom S wrote:
 Walter Bright wrote:
 language_fan wrote:
 This information is also taught in basic university level compiler
 courses.

I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.

Some universities don't even have compiler classes. Mine only covered basic parsing. Thanks for the article, Walter! :)

Wollongong has a compiler course. They just never run it due to complete and total lack of interest in the student body. People are no fun WHATSOEVER.
Aug 31 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Sep 3, 2009 at 6:48 PM, Edward
Diener<eddielee_no_spam_here tropicsoft.com> wrote:
 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> !

There's no real reason to get rid of function pointers. What type would the .funcptr property of a delegate be, if function pointers didn't exist? You also need them for C compatibility.
Sep 03 2009
prev sibling next sibling parent reply language_fan <foo bar.com.invalid> writes:
Mon, 31 Aug 2009 10:37:29 -0700, Walter Bright thusly wrote:

 language_fan wrote:
 This seems more like an advertisement of D than practical new
 information for compiler construction. Nesting functions is the basic
 feature of functional languages. Moreover even procedural Algol based
 languages such as Pascal have always supported them, too.

But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.

Most programmers I know don't use those languages, but then again I'm part of some minority.
 
 This information is also
 taught in basic university level compiler courses.

I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.

Ok. We were taught that. We basically built a naive Pascal compiler.
 
 Now that I checked what wikipedia had to say to the matter, it also
 seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature
 <foo>' always equals 'innovation'.

Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order.

For what it's worth, they also seem somewhat buggy in D. Hopefully writing the articles motivates fixing those issues :) For example one can't call symbols before their declaration on non-global scope.
 
 In part 2, I'll cover innovative things D does with nested functions.

Ok.
Aug 31 2009
parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 2, 2009 at 3:29 PM, Don<nospam nospam.com> wrote:
 Michiel Helvensteijn wrote:
 Rainer Deyke wrote:

 I still find it silly that it was built that way. Seems to me you should
 be able to forward-reference *any* symbol that has a value that can't
 change over its lifetime. Functions, const/immutable vars, typedefs,
 classes, etc.

That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; }

You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-)

constructing a dependency tree of top-level symbols. Pass over the tree, evaluating everything which is a leaf of the tree. If you have a pass where you don't succeed in removing any leaf nodes, you have a circular dependency. DMD sort of does this, I think, but it only does two passes, and it's not very good at backing out when it discovers something is not a leaf. It'd be hard to make that efficient when there are potentially infinite passes.

It wouldn't even be that difficult. Basically if you treat forward-referenced nested functions as a sort of goto, the same rules should apply: a call to a nested function may not skip the initialization of any variables it depends on. When i's initializer is evaluated, it has not been declared yet, so the call to f is illegal. It also prevents other invalid use.
Sep 02 2009
prev sibling next sibling parent language_fan <foo bar.com.invalid> writes:
Mon, 31 Aug 2009 13:17:11 -0700, Walter Bright thusly wrote:

 I agree it would be better to allow forward references for nested
 functions, I just wished to point out that the current behavior is not a
 bug, it was built that way.

That's great news actually. It might even mean that this might change some day.
Sep 02 2009
prev sibling next sibling parent language_fan <foo bar.com.invalid> writes:
Mon, 31 Aug 2009 14:42:09 -0400, Jeremie Pelletier thusly wrote:

 I agree with Walter here. While D is not the first place I see closures
 and nested functions, it is the first language I come across that blends
 delegates, closures and nested functions in a simple, elegant and
 intuitive manner.

Well..
 Its no surprise that I was literally drooling when I first read about
 how D does it, I had just spent a few weeks doing jQuery in JavaScript
 for a client back then and fell in love with closures, D had it all with
 better syntax :)
 
 In D you can even send a function pointer to a delegate value!

I can see your point. I have previously mostly used OCaml, Mercury, Miranda, Haskell, SML, CL, Scheme, Qi, Ur, Clojure, Erlang, and Oz. It's not really that surprising to first find some flaws in the functional part of a new language.
Sep 02 2009
prev sibling next sibling parent language_fan <foo bar.com.invalid> writes:
Wed, 02 Sep 2009 13:35:05 +0200, Michiel Helvensteijn thusly wrote:

 language_fan wrote:
 
 I agree it would be better to allow forward references for nested
 functions, I just wished to point out that the current behavior is not
 a bug, it was built that way.

That's great news actually. It might even mean that this might change some day.

I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.

While the syntax might vary a bit in functional languages, it's a common practice for the compiler to solve symbol dependencies inside the function scope. myfun:: Int -> Int -> Int myfyn a b = result b where result c = helper3 c + a helper3 = helper2 5 helper2 d c = if c == 1 then d else helper2 d (c - 1) When I first tried D, I put all my helper functions on top of all procedural code inside the function's scope, but soon noticed how badly it can fail.
Sep 02 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 2, 2009 at 6:07 AM, Nick Sabalausky<a a.a> wrote:

 Umm, yea. If you don't already know what I'm getting at with that, then..=

 Quick! For each of these, valid or invalid?:

 // D ////////////////////////
 void repeat(int n, void delegate(int i) dg)
 {
 =A0 =A0foreach(int i; 0..n)
 =A0 =A0 =A0 =A0dg(i);
 }
 repeat(5, delegate void(int i) { writefln("hi"); });

Only valid one! I've been doing this too long ;)
 And now the secondary question: Which, if any, of those instances of
 "delegate" should be changed to "function"? (I know it's not a real serio=

 problem, but the thing is, 99.9% of the time, I don't care, and more
 importantly, I don't *want* to care whether or not there's a scope being
 passed around with the...whatever it is.)

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.
Sep 02 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 2, 2009 at 9:49 AM, Daniel Keep<daniel.keep.lists gmail.com> wr=
ote:
 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.

The problem is that function pointers and delegates have different calling conventions. =A0You *might* be able to rig up an asm stub that compensated for the difference... not sure.

Which is why I suggest that the ABI be changed ;) I suppose one method of making their calling conventions compatible would be to pass the delegate's context in what would normally be a scratch register. Delegates/member funcs would store that immediately upon entry, and normal functions wouldn't care if anything were passed.
 As it stands, you can just use a function to create the delegate stub
 for you; doesn't even require a heap allocation!

 http://gist.github.com/140507

Wow. What a horrible mess of code to do something that should be straightforward. If this is what Andrei is thinking of when he says "introspection", well heh, I'll have no part of it. The comment about tuples not being allowed to contain out and ref is actually not entirely true. Internally type tuples are represented as parameter type tuples, which include the refness, and you can even get .stringofs that include the ref qualifiers. It instead seems that the compiler is buggy and _whether or not the refness of the params in a param tuple is preserved depends on the code using it_. Consider this gem: void foob(T: Ret function(Args), Ret, Args...)(T func) { pragma(msg, ParameterTupleOf!(T).stringof); static void wtf(ParameterTupleOf!(T) args) {} pragma(msg, ParameterTupleOf!(T).stringof); } void blah(int, ref float) {} void aojkjas() { foob(&blah); } Okay, look at foob's body. Both pragmas should print out the same thing, no= ? They don't. They print: (int, ref float) (int _param_0, float _param_1) WHAT. For one, where did the 'ref' go? For two, where did the names come from? Also, if you look at typeof(&wtf), it's also missing the ref. I'd really, really like to replace your entire module with this: Ret delegate(Args) toDg(T: Ret function(Args), Ret, Args...)(T func) { struct Wrap { T mFunc; Ret call(Args args) { return (cast(T)this)(args); } } Ret delegate(Args) dg; Wrap wrap; dg.ptr =3D func; dg.funcptr =3D &wrap.call; return dg; } But I can't. :C
Sep 02 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 2, 2009 at 9:45 AM, Andrei
Alexandrescu<SeeWebsiteForEmail 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.
Sep 02 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 2, 2009 at 4:53 PM, Nick Sabalausky<a a.a> wrote:
 void foo(bool delegate() dg) {
 =A0 =A0dg();
 }
 foo({return true;});

Sure, when there's no parameters (...does that work in D1, or just D2?...=

 but even then, I still always end up going though a process like this whe=

 defining foo:

No, you can do it with params too. foo((int x) { return x; });
Sep 02 2009
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-30 17:34:36 -0400, Walter Bright <newshound1 digitalmars.com> said:

 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

It's
 

C++ and Objective-C, starting with Snow Leopard, has it. Well, it has nested function litterals, called blocks. And it's really nice for performing tasks in the background. The following example is an Objective-C method that adds a task to the system's global task queue, which upon completion adds a task to the application's main thread event loop to updates the user interface. - (IBAction)analyzeDocument:(NSButton *)sender { dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSDictionary *stats = [myDoc analyze]; dispatch_async(dispatch_get_main_queue(), ^{ [myModel setDict:stats]; [myStatsView setNeedsDisplay:YES]; [stats release]; }); }); } Source: Mac OS X 10.6 Snow Leopard Review, Ars Technica -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 01 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Michel Fortin wrote:
 On 2009-08-30 17:34:36 -0400, Walter Bright <newshound1 digitalmars.com>
 said:
 
 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/

It's

and Objective-C, starting with Snow Leopard, has it. Well, it has nested function litterals, called blocks. ...

Oh sod blocks; the REAL awesome in that example is Grand Central Dispatch. For those who don't know, it's a parallelism framework that lets you farm off tasks to thread pools, with a few neat additions: 1) you can express dependencies and 2) the thread pools are managed by the OS itself, so it can load-balance. No doubt Microsoft will have Windows Bismuth or something for Windows 9 that's a hard to use, missed-the-point knock off. As for the FLOSS crowd, I expect that in a year or so down the track their solution will be buggy, even HARDER to use, and involve at LEAST three different and completely incompatible libraries. Plus, they have OpenCL. I've seen about a half dozen OpenCL examples specifically for non-Mac machines, but none bother to tell you how to actually GET an OpenCL implementation, or if they're even available. *sigh* I loathe Macs, but Apple seems to have hit this particular feature out of the park.
Sep 01 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-09-01 08:15:39 -0400, Daniel Keep <daniel.keep.lists gmail.com> said:

 Oh sod blocks; the REAL awesome in that example is Grand Central
 Dispatch.  For those who don't know, it's a parallelism framework that
 lets you farm off tasks to thread pools, with a few neat additions:
 
 1) you can express dependencies and
 2) the thread pools are managed by the OS itself, so it can load-balance.

And they're dead easy to use. Want an asynchronous foreach loop on the global system task queue? Here you go: dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i) { results[i] = do_work(data, i); }); I wonder how you could do the above in D2. I mean, assuming there's a way to declare a C function taking a block argument and that you can prevent prevent the garbage collector from deallocating the heap-allocated function frame once it's given to 'dispatch_apply', "results" would need to be a shared variable (using unnecessary atomic operations?), and the heap-allocated function frame would also need to be "shared" since it's given to another thread. Can this work?
 Plus, they have OpenCL.  I've seen about a half dozen OpenCL examples
 specifically for non-Mac machines, but none bother to tell you how to
 actually GET an OpenCL implementation, or if they're even available.  *sigh*

OpenCL is Apple's baby, no wonder they're a little ahead in their implementation. Just be pacient, I'm sure others will appear soon. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 01 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Michel Fortin Wrote:
 Plus, they have OpenCL.  I've seen about a half dozen OpenCL examples
 specifically for non-Mac machines, but none bother to tell you how to
 actually GET an OpenCL implementation, or if they're even available.  *sigh*

OpenCL is Apple's baby, no wonder they're a little ahead in their implementation. Just be pacient, I'm sure others will appear soon.

The specification is overseen by the Khronos group, Apple was a major contributor, and they had the original idea. But its not their work alone :) ATI already has a beta implemention of OpenCL, nVidia has one it releases to developers but I am too lazy to fill in the long form with just "i want to toy with it" answers. Hopefully these both reach release quality at the same time D handles 'shared' correctly :)
Sep 01 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-09-01 10:07:42 -0400, Jeremie Pelletier <jeremiep gmail.com> said:

 OpenCL is Apple's baby, no wonder they're a little ahead in their
 implementation. Just be pacient, I'm sure others will appear soon.

The specification is overseen by the Khronos group, Apple was a major contributor, and they had the original idea. But its not their work alone :)

I didn't say it was their work alone. What I meant is as you said: it was there original idea. I'll leave the baby analogy out of this. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 01 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_fu
ctions_work_part_1/ 

Another thread on it! http://www.reddit.com/r/programming/comments/9ga7e/c_lambdas_vs_apples_c_blocks/
Sep 01 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Sep 3, 2009 at 7:10 PM, grauzone<none example.net> wrote:
 Probably the same type as .ptr?

void*? That's just silly. Let's just throw all static typing out the window. :P
 And by the way, I find it really strange, that .funcptr results into an
 incorrectly typed function pointer, that basically has the wrong calling
 convention for the destination code, which usually is a method. It'd be
 different if signature of the .funcptr included an explicit argument for the
 hidden pointers. So that you could write: dg.funcptr(dg.ptr, arguments);

Yeah. There probably needs to be an extern(this) or so for functions that take a context pointer, like __thiscall in VC++. The way it works now is rather unsafe.
 And that's about the only reason to keep them.

 But wouldn't it be possible for the compiler to allow assignment of a
 function pointer to a delegate? All the compiler had to do is to generate a
 hidden dispatch method to "translate" the different calling conventions. The
 delegate's .funcptr points to that dispatch function, and the dispatch
 function call the actual function. If the assigned function pointer is not a
 statically known function (but from a variable), the function address could
 be stored in the delegate's .ptr. Would this work?

Of course it'd work. And D APIs would take delegates and everyone would be happy. But it still doesn't really justify getting rid of raw function pointers.
Sep 03 2009