Nested functions - better example?

new topic     » topic index » view thread      » older message » newer message

Good afternoon all, prepare youself for a techie bamboozle!

Nearly four years ago, I spent a sunday afternoon (about 6 hours) partially implementing nested functions, and it has remained in that partially broken state ever since. While it might be nice to solve the funarg problem and have proper closures (the ability for e() below to reference/update c and d even after b() has left the building) but I have to accept that's never going to happen without a drastic replacement of the whole call stack mechanism and all of our beloved pass by reference/copy-on-write semantics.

The better approach (for Phix) is to spot any attempt to write closure-like code and issue an error. [DONE, see [1]] In the following, e() must instead be explicitly passed anything it needs (such as c and/or d). Just this week, I suddenly realised that we could pass reference types to e(), namely a dictionary or a class instance, and it could update those directly, as opposed to the more traditional types atom/integer/string/sequence, which it can modify and return, but not update directly (cow-semantics). Anyway, I've hit a bit of a snag trying to clearly document these concepts (no s**t sherlock).

The following illustrates (hah!) nested scope rules:

object a = 1 
function b(object c) 
    object d = 2 
    function e(object f) 
        object g = 3 
        -- a,b,e,f,g in scope 
        -- c not in scope (except as a named parameter) 
        -- d not in scope 
--      ?c -- error -- 18,11,14,6   -- see note [1] 
--      ?f -- 18,11,14,6 
--      ?d -- error -- 3,3,3,3(!!)  -- see note [1] 
--      ?g -- 3,3,3,3 
        return {"a",a,"b45",iff(f==11?b(c:=4):5),"e67",iff(f==11?e(6):7),"f",f,"g",g} 
    end function 
    -- a,b,c,d,e in scope 
    -- f not in scope (except as a named parameter) 
    -- g not in scope 
    --?f -- error 
    --?g -- error 
--  ?c -- 1,8,4 
    return {"a",a,"b89",iff(c==1?b(8):9),"c",c,"d",d,"e",e(f:=c+10)} 
end function 
-- a,b in scope 
-- c not in scope (except as a named parameter) 
-- d,e,f,g not in scope 
pp(b(c:=a)) -- fine 
-- the output, albeit somewhat meaningless, is: 
--  {`a`, 1, `b89`, 
--   {`a`, 1, `b89`, 9, `c`, 8, `d`, 2, `e`, 
--    {`a`, 1, `b45`, 5, `e67`, 7, `f`, 18, `g`, 3}}, `c`, 1, `d`, 2, `e`, 
--   {`a`, 1, `b45`, 
--    {`a`, 1, `b89`, 9, `c`, 4, `d`, 2, `e`, 
--     {`a`, 1, `b45`, 5, `e67`, 7, `f`, 14, `g`, 3}}, `e67`, 
--    {`a`, 1, `b45`, 5, `e67`, 7, `f`, 6, `g`, 3}, `f`, 11, `g`, 3}} 
--?c -- error 
--?d -- error 
--?e -- error 
--?f -- error 
--?g -- error 

[1] I have now added the necessary hideScope/restoreScope to make c,d invisible from e(), though of course that's in pre-0.8.3 and has not been released yet. On 0.8.2 the first ?c will actually give the same results as ?f, since c and f match in a stack-frame-relative-wise way, ditto d and g.

I will just say this: I've used closures in JavaScript quite a bit recently, and they are pretty neat, especially if you've got no other way to handle them. The trouble is they are "hidden magic". There is absolutely nowhere, for instance, that I could ever output closure values in an ex.err. At best they would be an anonymous automatic construct from some point in a now destroyed stack. And that in turn would mean they are virtually completely and utterly impossible to ever debug. And you know me, I have no patience for any "waaah, I have to type it in, waaahh" programmers (granted for many that prolly stems from the 88,000 lines of boilerplate needed to start an empty project).

OK, back to the question at hand: The problem is simply that the above is (too stress-testy and) totally abstract, and therefore totally meaningless, and almost impossible to relate to any real-world use. Can anyone do better?

What might you use nested functions for, and would you cope, or cry like a baby 'cos you can't reference c and d?

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu