Re: Dynamic Scope / Continuation Marks

  • From: Laurent Deniau <Laurent.Deniau@xxxxxxx>
  • To: "luajit@xxxxxxxxxxxxx" <luajit@xxxxxxxxxxxxx>
  • Date: Fri, 4 Nov 2016 07:15:58 +0000

Hello,

Just for curiosity, is x always the same in your recursive calls or you have 
different x?

function withx(x, body)
  if x == globalx then
    return body()
  end
  local oldx = globalx
  globalx = x
  local result = {body()}
  globalx = oldx
  return unpack(result)
end

Maybe be an easy option…

Best,
Laurent.

--
Laurent Deniau                           http://cern.ch/mad
Accelerators Beam Physics        mad@xxxxxxx
CERN, CH-1211 Geneva 23       Tel: +41 (0) 22 767 4647

On 04 Nov 2016, at 01:27, Brandon Bloom <brandon.d.bloom@xxxxxxxxx> wrote:

Of course, that example code should be:

function withx(x, body)
  local oldx = globalx
  globalx = x
  local result = {body()}
  globalx = oldx
  return unpack(result)
end

On Thu, Nov 3, 2016 at 5:16 PM, Brandon Bloom <brandon.d.bloom@xxxxxxxxx> 
wrote:
Hello,

Is it possible to accomplish dynamic scope in a way that respects tail calls 
with luajit?

I've been approximating dynamic scope for a particular algorithm in the 
classic set/restore manner:

function withx(x, body)
  local oldx = globalx
  local result = {body()}
  globalx = oldx
  return unpack(result)
end

Unfortunately, while simple, this approach evaluates the body function in a 
non-tail position. Until now, this wasn't a problem, but I've run in to a 
recursive use case which now suffers from stack overflows.

Racket accomplishes dynamic scope via "continuation marks" (see [1] and [2]) 
that, if manipulated in tail position, modify a cell in the current frame, so 
these "marks" with dynamic extent can be used without affecting space 
complexity. The documentation for the "parameterize" macro calls out the 
body-in-tail-position behavior explicitly [3].

A blog post [4] suggests that dynamic scope can hack-ily be accomplished via 
debug.getlocal, but the specific code posted there is incorrect in the 
presence of tail calls (try adding a 'return' to the fn call in run_func). I 
suppose Lua 5.2's getinfo with what='t' can return istailcall to workaround 
this, but we've gotten pretty far in to hack territory and I'd like to stay 
on luajit.

I don't care if the resulting code achieves normal variable syntax or not. 
I'm fine with function call syntax to get the current dynamic value.

So to recap: Is there a way in luajit to accomplish tail-call-safe dynamic 
scope or otherwise associate per-stack-frame data?

Thanks,
Brandon


[1] https://docs.racket-lang.org/reference/contmarks.html
[2] "Adding Delimited and Composable Control to a Production Programming 
Environment" - Flatt, et al.
[3] 
https://docs.racket-lang.org/reference/parameters.html?q=parameterize#%28form._%28%28lib._racket%2Fprivate%2Fmore-scheme..rkt%29._parameterize%29%29
[4] http://leafo.net/guides/dynamic-scoping-in-lua.html


Attachment: smime.p7s
Description: S/MIME cryptographic signature

Other related posts: