Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
February 11, 2013 nested functions and closures | ||||
---|---|---|---|---|
| ||||
When debugging gdc I've found some at least for me interesting behavior which I'm trying to understand now: ---- auto testFunction() { int a = 41; int nestedFunc() { return ++a; } struct NestedStruct { int answer() { return nestedFunc(); } } return NestedStruct(); } writeln(testFunction().answer()); ---- This is valid D code, creates a closure. ---- class testClass { int a = 41; int nestedFunc() { return ++a; } struct NestedStruct { int answer() { return nestedFunc(); } } auto getStruct() { return NestedStruct(); } } writeln((new TestClass()).getStruct().answer); ---- This does not compile: test.d(33): Error: this for nestedFunc needs to be type testClass not type NestedStruct Is this intended? It seems to be very similar to the function closure code. Couldn't NestedStruct just get a pointer to the testClass to access its variables? Or am I missing something? Everything works fine if NestedStruct is a class and not a struct so I guess this functionality was disabled deliberately. But why? And why wasn't using a nested struct in functions in a similar way disallowed as well? |
February 11, 2013 Re: nested functions and closures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On Monday, 11 February 2013 at 18:59:37 UTC, Johannes Pfau wrote: > When debugging gdc I've found some at least for me interesting > behavior which I'm trying to understand now: > > ---- > auto testFunction() { > int a = 41; > int nestedFunc() { return ++a; } > > struct NestedStruct { > int answer() { return nestedFunc(); } > } > > return NestedStruct(); > } > > writeln(testFunction().answer()); > ---- > > This is valid D code, creates a closure. > > ---- > class testClass > { > int a = 41; > int nestedFunc() { return ++a; } > > struct NestedStruct { > int answer() { return nestedFunc(); } > } > > auto getStruct() { return NestedStruct(); } > } > > writeln((new TestClass()).getStruct().answer); > ---- > > This does not compile: > test.d(33): Error: this for nestedFunc needs to be type testClass not > type NestedStruct > > Is this intended? It seems to be very similar to the function closure > code. Couldn't NestedStruct just get a pointer to the testClass to > access its variables? Or am I missing something? > > Everything works fine if NestedStruct is a class and not a struct so I > guess this functionality was disabled deliberately. But why? And why > wasn't using a nested struct in functions in a similar way disallowed as > well? I recently wrote an article partly on this topic which may be of interest to you. Apologies if it is not. See part one: neutrons. http://forum.dlang.org/thread/ririagrqecshjljcdubd@forum.dlang.org |
February 11, 2013 Re: nested functions and closures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On Mon, 11 Feb 2013 13:59:36 -0500, Johannes Pfau <nospam@example.com> wrote:
> When debugging gdc I've found some at least for me interesting
> behavior which I'm trying to understand now:
>
> ----
> auto testFunction() {
> int a = 41;
> int nestedFunc() { return ++a; }
>
> struct NestedStruct {
> int answer() { return nestedFunc(); }
> }
>
> return NestedStruct();
> }
>
> writeln(testFunction().answer());
> ----
>
> This is valid D code, creates a closure.
>
> ----
> class testClass
> {
> int a = 41;
> int nestedFunc() { return ++a; }
>
> struct NestedStruct {
> int answer() { return nestedFunc(); }
> }
> auto getStruct() { return NestedStruct(); }
> }
>
> writeln((new TestClass()).getStruct().answer);
> ----
>
> This does not compile:
> test.d(33): Error: this for nestedFunc needs to be type testClass not
> type NestedStruct
>
> Is this intended? It seems to be very similar to the function closure
> code. Couldn't NestedStruct just get a pointer to the testClass to
> access its variables? Or am I missing something?
>
> Everything works fine if NestedStruct is a class and not a struct so I
> guess this functionality was disabled deliberately. But why? And why
> wasn't using a nested struct in functions in a similar way disallowed as
> well?
A nested class has an outer pointer to it's owner class. You cannot instantiate a nested class without it's owner class.
A nested struct does NOT have a pointer to it's owner class. It's simply typed inside the class' namespace.
FYI, nested classes were enshrined with a pointer to an outer instance for two reasons:
1. Their footprint is larger, not as big a hit to add another pointer.
2. To allow porting of Java code.
Structs are POD for the most part, and are much more "bare metal" than classes.
Nested structs could be given an instance pointer to the owner, but I think we would need a new construct for that.
For your problem at hand, you may want to consider using interfaces instead. Or you can possibly embed the owner pointer manually.
-Steve
|
February 12, 2013 Re: nested functions and closures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Am Mon, 11 Feb 2013 17:03:22 -0500 schrieb "Steven Schveighoffer" <schveiguy@yahoo.com>: > > A nested class has an outer pointer to it's owner class. You cannot instantiate a nested class without it's owner class. > > A nested struct does NOT have a pointer to it's owner class. It's simply typed inside the class' namespace. > > FYI, nested classes were enshrined with a pointer to an outer instance for two reasons: > > 1. Their footprint is larger, not as big a hit to add another pointer. 2. To allow porting of Java code. > > Structs are POD for the most part, and are much more "bare metal" than classes. > > Nested structs could be given an instance pointer to the owner, but I think we would need a new construct for that. Thanks, I thought it was something like that. The weird part is that if you return a nested struct which is nested in a _function_ the compiler generates a closure for the function and then struct is given an instance pointer to the closure. But if you return a struct nested in a class the struct doesn't get an instance pointer. > For your problem at hand, you may want to consider using interfaces instead. Or you can possibly embed the owner pointer manually. > > -Steve Fortunately there's no problem at hand, I was just curious :-) I actually use nested classes/structs and closures quite rarely. |
February 12, 2013 Re: nested functions and closures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zach the Mystic | Am Mon, 11 Feb 2013 21:41:26 +0100 schrieb "Zach the Mystic" <reachBUTMINUSTHISzach@gOOGLYmail.com>: > > I recently wrote an article partly on this topic which may be of interest to you. Apologies if it is not. See part one: neutrons. > > http://forum.dlang.org/thread/ririagrqecshjljcdubd@forum.dlang.org Yes, that's basically the same question. I'm not really interested in possible implementation details though, I'd just like to know why it wasn't allowed to access outer variables of nested structs in the first place. But Steven Schveighoffer answer already covers that. |
February 12, 2013 Re: nested functions and closures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On Tue, 12 Feb 2013 03:23:13 -0500, Johannes Pfau <nospam@example.com> wrote: > Am Mon, 11 Feb 2013 17:03:22 -0500 > schrieb "Steven Schveighoffer" <schveiguy@yahoo.com>: > >> >> A nested class has an outer pointer to it's owner class. You cannot >> instantiate a nested class without it's owner class. >> >> A nested struct does NOT have a pointer to it's owner class. It's >> simply typed inside the class' namespace. >> >> FYI, nested classes were enshrined with a pointer to an outer >> instance for two reasons: >> >> 1. Their footprint is larger, not as big a hit to add another pointer. >> 2. To allow porting of Java code. >> >> Structs are POD for the most part, and are much more "bare metal" >> than classes. >> >> Nested structs could be given an instance pointer to the owner, but >> I think we would need a new construct for that. > > Thanks, I thought it was something like that. The weird part is that if > you return a nested struct which is nested in a _function_ the compiler > generates a closure for the function and then struct is given an > instance pointer to the closure. But if you return a struct nested in a > class the struct doesn't get an instance pointer. If structs inside functions acted just like structs outside of functions, there would be very little reason to have them. Functions sort of have their own namespace, but I don't know if that justifies having function-nested structs. There are static function-nested structs, but I think the concept of using them with frequency is pretty new (voldemort types). I actually wouldn't mind an opt-in approach to including an outer reference, at least for structs nested in classes (it's too dangerous to do this for owner structs). I think it's too late to make that the default. > >> For your problem at hand, you may want to consider using interfaces >> instead. Or you can possibly embed the owner pointer manually. >> >> -Steve > > Fortunately there's no problem at hand, I was just curious :-) I > actually use nested classes/structs and closures quite rarely. I use nested structs for namespace in dcollections quite frequently. For instance TreeMap.cursor is a nested struct. -Steve |
Copyright © 1999-2021 by the D Language Foundation