lua-users home
lua-l archive

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

On 12-Aug-05, at 2:05 PM, Diego Nehab wrote:

Hi Rici,

Don't you think it can get quite complicated to trace where these blocks reside once you start passing them around?

No, I don't.

I didn't mean it would be hard to implement. I meant it might make the
Lua code that uses this functionality very hard to understand. This
could be a limitation of my not being used to non-local returns.  I
remember once not liking coroutines. :)

But I do think we have found a valid use for this non-local return:
error checking.

Wouldn't a simplistic solution be enough, though? How about a construct
that behaves exactly like return, but that forces return of more than
one level? I have no idea of what would be an elegant syntax for that,
so I will go with a function call.

Well, that's exactly what the block structure does, except that it protects you from counting call frames (which is notoriously fragile). It effectively provides a name for the frame you're returning to; you're just responsible for making sure that the called function gets the name.

    function roe(v, ...)
       if v then return v, ...
       else nlr(2, v, ...) end

    function foo()
        local c = roe(socket.connect("localhost", 80))
        roe(socket.send("GET / HTTP/1.0\r\n\r\n"))
        local l = roe(socket.receive())
        return 1

function roe(where, v, ...)
  if v then return v, ...
  else where(v, ...)

function foo(where)
  local c = roe(where, socket.connect("localhost", 80))
  roe(where, socket.send("GET / HTTP/1.0\r\r\n"))
  local l = roe(where, socket.receive())
  return 1

function call_with_ret(func, ...)
  return block (p)
    p(func(p, ...))


--- That would all be a bit more elegant if 'where' were an upvalue in 'roe'. But that's not usually the right thing. The right thing is that 'where' is registered somewhere as the thing to call on an exception; the registration has to be aligned with the dynamic call structure of the program, rather than with the static lexical structure. Non-local exits combined with an exception registry (maintained in synch with scope finalizers) provide a simple solution to this, amongst other, problems.