Thread overview
[Issue 3995] New: Can't access array/AA from function literal defined inside the array/AA's initializer
Mar 20, 2010
Nick Sabalausky
Mar 20, 2010
Nick Sabalausky
Feb 02, 2012
yebblies
Feb 15, 2012
yebblies
March 20, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=3995

           Summary: Can't access array/AA from function literal defined
                    inside the array/AA's initializer
           Product: D
           Version: 1.050
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Keywords: rejects-valid
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: cbkbbejeap@mailinator.com
            Blocks: 340


--- Comment #0 from Nick Sabalausky <cbkbbejeap@mailinator.com> 2010-03-20 12:38:04 PDT ---
I find this idiom very useful, particularly for handling domain-specific languages:

------------------------------
auto dgMap = [
    "foo": (int i) {
        return /+..stuff..+/;
    },
    "bar": (int i) {
        return /+..stuff..+/;
    },
    "bat": (int i) {
        return /+..stuff..+/;
    },
];
dgMap["bar"](4);
------------------------------

However, those functions cannot refer to each other or use recursion even though doing so would be perfectly safe:

------------------------------
auto dgMap = [
    "foo": (int i) {
        if(i < 1)
            return 0;
        else
            // Recursion, would be perfectly safe if allowed.
            // ERROR: undefined identifier dgMap
            return dgMap["foo"](i-1);
    },

    "bar": (int i) {
        // Call different element: would be perfectly safe if allowed.
        // ERROR: undefined identifier dgMap
        return dgMap["foo"](7);;
    }
];
------------------------------

This is a bit of a pain, as it can't be solved without giving up either the locality of the in-line delegate literals or the type inference of the array/AA (which is *very* useful in this sort of situation).

I'm not sure if this counts as an enhancement or a declaration-order bug.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 20, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=3995



--- Comment #1 from Nick Sabalausky <cbkbbejeap@mailinator.com> 2010-03-20 12:48:27 PDT ---
The above example might have a problem inferring the return type of the delegate literals (and therefore the type of 'dgMap' itself). But this alteration doesn't have that problem and still fails to compile with "undefined identifier dgMap":

---------------------
auto dgMap = [
    "foo": delegate int(int i) {
        if(i < 1)
            return 0;
        else
            return dgMap["foo"](i-1);
    },

    "bar": delegate int(int i) {
        return dgMap["foo"](7);;
    }
];
---------------------

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 02, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=3995


yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies@gmail.com
           Platform|Other                       |All
            Version|1.050                       |D1 & D2
             Blocks|340                         |
         OS/Version|Windows                     |All
           Severity|normal                      |enhancement


--- Comment #2 from yebblies <yebblies@gmail.com> 2012-02-02 14:07:15 EST ---
This is working as intended.

Variables are not added to the scope until after their initializers are processed, preventing garbage like this:

int x = x;

And other cases where this would make it possible to refer to uninitialized variables that, even when they have an initializer.

A trivial workaround is the following:

int delegate(int)[string] dgMap;
auto tmp = [ ... delegate definitions referring to dgMap ... ];
dgMap = tmp;

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=3995


yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID


--- Comment #3 from yebblies <yebblies@gmail.com> 2012-02-15 16:42:09 EST ---
I think this is invalid, letting the initializer reference the variable is a real pain in c++, and was intentionally disallowed in D.

While it can be useful in some cases (when used carefully) I doubt it's worth
adding (for this case or in general), especially when there's such a trivial
workaround.

Nick, please reopen if you disagree.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------