lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Blah.  noticed a bug right after I posted it.  if the existing _ENV is an environment import() previously created, and it tries to add more "globals" to that existing environment, it'll trigger the __newindex (if it's not redefining other globals) and put it in the parent-parent _ENV (lol)

basically the new_env[pref .. k] = t[k] line needs to be rawset(new_env, pref .. k, t[k])

k bitches, I'm outtie :D-S-<


On Tue, Nov 19, 2013 at 10:51 AM, Sir Pogsalot <sir.pogsalot@gmail.com> wrote:
So it was nagging at me that I could create very "chained" _ENV's with the import() I wrote.  Basically in this new version of import() it inserts the created environments in the envs table, with it weakly-referencing the key and value (either or).  The created environment is used as both the key and value.  So when we import() if it notices the existing _ENV is an environment it created it'll just wind up adding "globals" to that environment, and it won't even reassign "_ENV = _ENV" with debug.setupvalue().  This way it will never create a chained _ENV of more than 2 tables (the new env, and the existing env).

If you put a line like "print('replaced')" in the last if body in import() you can see that when f() is called the _ENV is not replaced, as it is an environment created by import().  It is added to but not replaced with yet another fall-through _ENV.  (yay!)

Now I'm 53% happy =^__^=

PS: I recognize that import() not returning the new environment is less flexible.  This is the interface I'd prefer, though. :\  (user preference)

---------------------------------------------

local envs = setmetatable({}, { __mode = 'kv' }) 

local import =
    function (t, ...)
        require('debug')

        local pref, keys

        if select('#', ...) > 1 or (... ~= nil and type(...) == 'table') then
            keys, pref = ...
        else
            pref, keys = ...
        end

        keys = keys or {} 
        pref = pref or '' 

        if not next(keys) then
            for k in pairs(t) do 
                table.insert(keys, k) 
            end
        end

        local new_env = envs[_ENV] or setmetatable({}, { __index = _ENV, __newindex = _ENV }) 

        -- if envs[_ENV], we wind up adding to _ENV
        for _, k in pairs(keys) do 
            new_env[pref .. k] = t[k]
        end

        if not envs[new_env] then
            envs[new_env] = new_env
            debug.setupvalue(debug.getinfo(1, 'f').func, 1, new_env)
        end
    end

import(string, { 'reverse', 'rep', 'sub' }, 's')

local f =
    function () 
        import(io, 'io_')

        io_write('blah\r\n')
    end

print(sreverse('cat'), srep('donut', 5), ssub('abcdefg', 3, 6))

f()



On Tue, Nov 19, 2013 at 9:59 AM, Sir Pogsalot <sir.pogsalot@gmail.com> wrote:
Moonscript is definitely interesting -- unfortunately I'm one of those programmers with strong opinions about what feels 'right' and 'wrong'.  I'm just not terribly in love with the languages that compile to other languages thing... 

This makes me [51%] happy for now :]

local import =
    function (t, ...)
        require('debug')

        local pref, keys

        if select('#', ...) > 1 or (... ~= nil and type(...) == 'table') then
            keys, pref = ...
        else
            pref, keys = ...
        end

        keys = keys or {} 
        pref = pref or '' 

        if not next(keys) then
            for k in pairs(t) do 
                table.insert(keys, k) 
            end
        end

        local new_env = setmetatable({}, { __index = _ENV }) 

        for _, k in pairs(keys) do 
            new_env[pref .. k] = t[k]
        end


        debug.setupvalue(debug.getinfo(1, 'f').func, 1, new_env)
    end

import(string, { 'reverse', 'rep', 'sub' },'s')

print(sreverse('cat'), srep('donut', 5), ssub('abcdefg', 3, 6))

----------------

I mean it's touching _ENV, so I'm not happy... but I got the frontend I wanted.



On Tue, Nov 19, 2013 at 9:07 AM, steve donovan <steve.j.donovan@gmail.com> wrote:
On Tue, Nov 19, 2013 at 10:44 AM, Sir Pogsalot <sir.pogsalot@gmail.com> wrote:
> the community involvement with upstream is through this list and an overall
> attitude like this will probably hurt Lua in the long run.  Or maybe I'm
> just moping.. ~

I didn't see the response as particularly negative.  Precisely because
Lua is so carefully (and slowly) engineered, most of its fans require
a big leap in utility from any new feature.  And yes, a lot of us do
find the extra _typing_ tedious but just suck it up (or get clever
like Sean).  The reading I have no problem with, and my spell checker
will catch mistakes ;)

Every now and then I suggest people have a look at Moonscript, not
because I think it's _the_ future of Lua, but because it is _a_ future
of Lua - and it compiles to very straightforward Lua.  There is your
import feature there, 'locals-as-default', list comprehensions, really
concise lambdas and just about every 'it would be nice' feature I've
seen on this list. So it's an opportunity to try see how they feel in
practice. tlr;dr: a lot more syntax, and gotchas about local scope -
not for the newbie.

Unfortunately, I am too busy to contemplate marriage proposals at the
moment but the thought is appreciated ;)

steve d.