luascopelua-4.0

Lua 4.0 script fails and complains about outer scope


The following Lua 4.0 script fails due to some of the variables being in an 'outer' scope. What are the different ways I can fix this? I would like to avoid putting things in the global scope completely if possible. Thanks.

function flokalAdd(iNx, iNy, iXmin, iSym, fEcc, bInside, fScale)
    TWO_PI = 2 * PI;
    iSx = 4;
    iSy = 4;
    function pow(fA, fB)
        return fA^fB
    end
    function mag(fX, fY)
        return dist(fX, fY, 0, 0)
    end
    function dist(fX1, fY1, fX2, fY2)
        return sqrt(pow(fX2 - fX1, 2) + pow(fY2 - fY1, 2))
    end
    function norm()
        local fY1 = 0;
        local fX1 = 0;
        local fX2 = exp(fX1) * cos(deg(fY1));
        local fY2 = exp(fX1) * sin(deg(fY1)) + fEcc;
        local fD = 0;
        if (bInside == 1) then
            fD = pow(mag(fX2, fY2),  1/iSym);
        else
            fD = pow(mag(fX2, fY2), -1/iSym);
        end
        local fArg = rad(atan2(fX2, fY2)) * -1/iSym;
        local fX3 = fD * cos(deg(fArg))/TWO_PI;
        local fY3 = fD * sin(deg(fArg))/TWO_PI;
        return mag(fX3, fY3)
    end
    function fn(fX, fY)
        local aP = {};
        local fX1 = exp(fX) * cos(deg(fY));
        local fY1 = exp(fX) * sin(deg(fY)) + fEcc;
        local fD = 0;
        if (bInside == 1) then
            fD = pow(mag(fX1, fY1),  1/iSym);
        else
            fD = pow(mag(fX1, fY1), -1/iSym);
        end
        local fArg = rad(atan2(fX1, fY1)) * -1/iSym;
        for i = 0, iSym - 1 do
            local fX2 = fD * cos(deg(fArg + i * TWO_PI/iSym))/TWO_PI;
            local fY2 = fD * sin(deg(fArg + i * TWO_PI/iSym))/TWO_PI;
            aP[i + 1] = {fX2, fY2};
        end
        return aP
    end
    function lines(aP1, aP2)
        for i = 0, iSym - 1 do
            local fX1 = aP1[i + 1][0 + 1];
            local fY1 = aP1[i + 1][1 + 1];
            local fX2 = aP2[i + 1][0 + 1];
            local fY2 = aP2[i + 1][1 + 1];
            --addPebble(<sPebbleType>, <tPosition>, ?, ?, ?)
            --addPebble("Pebble_2", {fX1 * fScale/fNorm, 0 * fScale/fNorm, fY1 * fScale/fNorm,}, 0, 0, 0)

            -----------------------
            -- DO SOMETHING HERE --
            -----------------------
        end
    end
    -- calculate the distance from the origin to the center of each eye, then use it to normalize the shape to within 1 unit of the center
    fNorm = norm();
    for i = 0, iNy - 1 do
        local fY = i * TWO_PI/iNy;
        for j = iXmin * iSx, iNx * iSx - 1 do
            local fX1 = j * TWO_PI/iNx/iSx;
            local fX2 = (j + 1) * TWO_PI/iNx/iSx;
            lines(fn(fX1, fY), fn(fX2, fY))
        end
    end
    for i = iXmin, iNx do
        local fX = i * TWO_PI/iNx;
        for j = 0, iNy * iSy - 1 do
            local fY1 = j * TWO_PI/iNy/iSy;
            local fY2 = (j + 1) * TWO_PI/iNy/iSy;
            lines(fn(fX, fY1), fn(fX, fY2))
        end
    end
end



flokalAdd(16, 16, 12, 5, 256, false, 20000)

Solution

  • This happens due to Lua 4.0 scoping rules:

    Function scopes have a special limitation in that outer scopes (other than the global scope) may not be accessed. This applies to any function, but is most noticeable in the case of nested functions where you may want to access locals of the enclosing scope.

    In your code fEcc is defined in the scope of function flokalAdd, so it can't be accessed from the inner norm function.
    You can fix this using upvalues:

    Upvalues were added to work around the function scope limitation. Prefixing an outer-scope variable reference with % produces a copy of that variable as of the function's instantiation. Only the immediate scope containing the function and the global scope may be accessed in this manner.

    Looking at the code, it seems that copying by value is OK. Here is the fixed version.