[R] Continuation-parsing / trampoline / infinite recursion problem

Thomas Mailund
Wed, 10 Aug 2016 18:39:03 -0000

?
Ok, I think maybe I am beginning to see what is going wrong...

Explicitly remembering the thunk parameters in a list works fine, as far as I
can see.

make_thunk <- function(f, ...) {
? remembered <- list(...)
? function(...) do.call(f, as.list(remembered))
}

thunk_factorial <- function(n, continuation = identity) {
? if (n == 1) {
? ? continuation(1)
? } else {
? ? new_continuation <- function(result) {
? ? ? make_thunk(continuation, n * result)
? ? }
? ? make_thunk(thunk_factorial, n - 1, new_continuation)
? }
}

trampoline <- function(thunk) {
? while (is.function(thunk)) thunk <- thunk()
? thunk
}

trampoline(thunk_factorial(100))


But if I delay the evaluation of the parameters to thunk I get an error

make_thunk <- function(f, ...) {
? remembered <- eval(substitute(alist(...))) # not evaluating parameters yet
? function(...) do.call(f, as.list(remembered))
}

thunk_factorial <- function(n, continuation = identity) {
? if (n == 1) {
? ? continuation(1)
? } else {
? ? new_continuation <- function(result) {
? ? ? make_thunk(continuation, n * result)
? ? }
? ? make_thunk(thunk_factorial, n - 1, new_continuation)
? }
}

trampoline(thunk_factorial(100))

Running this version I am told, when applying the function, that it doesn?t see
variable `n`.


As far as I can see, the thunk remembers the parameters just fine. At least this
gives me the parameters I made it remember

x <- 1
f <- make_thunk(list, a = 1 * x, b = 2 * x)
g <- make_thunk(list, c = 3 * x)
f()
g()

Here I just get the parameters back in a list because the wrapped function is
`list`. (The reason I have `x` as a global variable and use it in the arguments
is so I get call objects that needs to be evaluated lazily instead of just
values).

These values contain the expressions I gave the `make_thunk` function, of
course, and they are not evaluated. So in the factorial function the missing `n`
is because I give it the expression `n - 1` that it of course cannot evaluate in
the thunk.

So I cannot really delay evaluation.

Does this sound roughly correct?

Now why I can still get it to work when I call `cat` remains a mystery?

Cheers
	Thomas



On 10 August 2016 at 19:12:41, Thomas Mailund (mailund at
birc.au.dk(mailto:mailund at birc.au.dk)) wrote:

>
> That did the trick!
>
> I was so focused on not evaluating the continuation that I completely
forgot that the thunk could hold an unevaluated value? now it seems to be
working for all the various implementations I have been playing around with.
>
> I think I still need to wrap my head around *why* the forced evaluation is
necessary there, but I will figure that out when my tired brain has had a little
rest.
>
> Thanks a lot!
>
> Thomas
>
>
> > On 10 Aug 2016, at 19:04, Duncan Murdoch wrote:
> >
> > On 10/08/2016 12:53 PM, Thomas Mailund wrote:
> >> > On 10 Aug 2016, at 13:56, Thomas Mailund wrote:
> >> >
> >> > make_thunk <- function(f, ...) f(...)
> >>
> >> Doh! It is of course this one:
> >>
> >> make_thunk <- function(f, ...) function() f(?)
> >>
> >> It just binds a function call into a thunk so I can delay its
evaluation.
> >
> > I haven't looked closely at the full set of functions, but this
comment:
> >
> > force(continuation) # if I remove this line I get an error
> >
> > makes it sound as though you're being caught by lazy evaluation.
The "make_thunk" doesn't appear to evaluate ..., so its value can
change between the time you make the thunk and the time you evaluate it. I think
you could force the evaluation within make_thunk by changing it to
> >
> > make_thunk <- function(f, ...) { list(...); function() f(?) }
> >
> > and then would be able to skip the force() in your thunk_factorial
function.
> >
> > Duncan Murdoch
> >
> >
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.