Re: [R] R help
The condition is true all the way until you index outside the vector... Cheers On 31 Mar 2018, 17.29 +0200, Henri Moolman , wrote: > Could you please provide help with something from R that I find rather > puzzling? In the small program below x[1]=1, . . . , x[5]=5. R also > finds that x[1]<=5 is TRUE. Yet when you attempt to execute while, R does > not seem to recognize the condition. Any thoughts on why this happens? > > Regards > > Henri Moolman > > > x=c(1,2,3,4,5) > > x[1] > [1] 1 > > i=1 > > x[1]<=5 > [1] TRUE > > while(x[i]<=5){ > + i=i+1 > + } > Error in while (x[i] <= 5) { : missing value where TRUE/FALSE needed > > [[alternative HTML version deleted]] > > __ > R-help@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. [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Parallel assignments and goto
I did try assign. That was the slowest version from what my profiling could tell, as far as I recall, which really surprised me. I had expected it to be the fastest. The second slowest was using the [[ operator on environments. Or it might be the reverse for those two. They were both slower than the other versions I posted here. Cheers On 27 Feb 2018, 17.16 +0100, Bert Gunter , wrote: > No clue, but see ?assign perhaps if you have not done so already. > > -- Bert > > > > Bert Gunter > > "The trouble with having an open mind is that people keep coming along and > sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Tue, Feb 27, 2018 at 6:51 AM, Thomas Mailund > > wrote: > > > Interestingly, the <<- operator is also a lot faster than using a > > > namespace explicitly, and only slightly slower than using <- with local > > > variables, see below. But, surely, both must at some point insert values > > > in a given environment — either the local one, for <-, or an enclosing > > > one, for <<- — so I guess I am asking if there is a more low-level > > > assignment operation I can get my hands on without diving into C? > > > > > > > > > factorial <- function(n, acc = 1) { > > > if (n == 1) acc > > > else factorial(n - 1, n * acc) > > > } > > > > > > factorial_tr_manual <- function (n, acc = 1) > > > { > > > repeat { > > > if (n <= 1) > > > return(acc) > > > else { > > > .tailr_n <- n - 1 > > > .tailr_acc <- acc * n > > > n <- .tailr_n > > > acc <- .tailr_acc > > > next > > > } > > > } > > > } > > > > > > factorial_tr_automatic_1 <- function(n, acc = 1) { > > > .tailr_n <- n > > > .tailr_acc <- acc > > > callCC(function(escape) { > > > repeat { > > > n <- .tailr_n > > > acc <- .tailr_acc > > > if (n <= 1) { > > > escape(acc) > > > } else { > > > .tailr_n <<- n - 1 > > > .tailr_acc <<- n * acc > > > } > > > } > > > }) > > > } > > > > > > factorial_tr_automatic_2 <- function(n, acc = 1) { > > > .tailr_env <- rlang::get_env() > > > callCC(function(escape) { > > > repeat { > > > if (n <= 1) { > > > escape(acc) > > > } else { > > > .tailr_env$.tailr_n <- n - 1 > > > .tailr_env$.tailr_acc <- n * acc > > > .tailr_env$n <- .tailr_env$.tailr_n > > > .tailr_env$acc <- .tailr_env$.tailr_acc > > > } > > > } > > > }) > > > } > > > > > > microbenchmark::microbenchmark(factorial(1000), > > > factorial_tr_manual(1000), > > > factorial_tr_automatic_1(1000), > > > factorial_tr_automatic_2(1000)) > > > Unit: microseconds > > > expr min lq mean median > > > uq max neval > > > factorial(1000) 884.137 942.060 1076.3949 977.6235 > > > 1042.5035 2889.779 100 > > > factorial_tr_manual(1000) 110.215 116.919 130.2337 118.7350 > > > 122.7495 255.062 100 > > > factorial_tr_automatic_1(1000) 179.897 183.437 212.8879 187.8250 > > > 195.7670 979.352 100 > > > factorial_tr_automatic_2(1000) 508.353 534.328 601.9643 560.7830 > > > 587.8350 1424.260 100 > > > > > > Cheers > > > > > > On 26 Feb 2018, 21.12 +0100, Thomas Mailund , > > > wrote: > > > > Following up on this attempt of implementing the tail-recursion > > > > optimisation — now that I’ve finally had the chance to look at it again > > > > — I find that non-local return implemented with callCC doesn’t actually > > > > incur much overhead once I do it more sensibly. I haven’t found a good > > > > way to handle parallel assignments that isn’t vastly slower than simply > > > > introducing extra va
Re: [R] Parallel assignments and goto
Interestingly, the <<- operator is also a lot faster than using a namespace explicitly, and only slightly slower than using <- with local variables, see below. But, surely, both must at some point insert values in a given environment — either the local one, for <-, or an enclosing one, for <<- — so I guess I am asking if there is a more low-level assignment operation I can get my hands on without diving into C? factorial <- function(n, acc = 1) { if (n == 1) acc else factorial(n - 1, n * acc) } factorial_tr_manual <- function (n, acc = 1) { repeat { if (n <= 1) return(acc) else { .tailr_n <- n - 1 .tailr_acc <- acc * n n <- .tailr_n acc <- .tailr_acc next } } } factorial_tr_automatic_1 <- function(n, acc = 1) { .tailr_n <- n .tailr_acc <- acc callCC(function(escape) { repeat { n <- .tailr_n acc <- .tailr_acc if (n <= 1) { escape(acc) } else { .tailr_n <<- n - 1 .tailr_acc <<- n * acc } } }) } factorial_tr_automatic_2 <- function(n, acc = 1) { .tailr_env <- rlang::get_env() callCC(function(escape) { repeat { if (n <= 1) { escape(acc) } else { .tailr_env$.tailr_n <- n - 1 .tailr_env$.tailr_acc <- n * acc .tailr_env$n <- .tailr_env$.tailr_n .tailr_env$acc <- .tailr_env$.tailr_acc } } }) } microbenchmark::microbenchmark(factorial(1000), factorial_tr_manual(1000), factorial_tr_automatic_1(1000), factorial_tr_automatic_2(1000)) Unit: microseconds expr min lq mean median uq max neval factorial(1000) 884.137 942.060 1076.3949 977.6235 1042.5035 2889.779 100 factorial_tr_manual(1000) 110.215 116.919 130.2337 118.7350 122.7495 255.062 100 factorial_tr_automatic_1(1000) 179.897 183.437 212.8879 187.8250 195.7670 979.352 100 factorial_tr_automatic_2(1000) 508.353 534.328 601.9643 560.7830 587.8350 1424.260 100 Cheers On 26 Feb 2018, 21.12 +0100, Thomas Mailund , wrote: > Following up on this attempt of implementing the tail-recursion optimisation > — now that I’ve finally had the chance to look at it again — I find that > non-local return implemented with callCC doesn’t actually incur much overhead > once I do it more sensibly. I haven’t found a good way to handle parallel > assignments that isn’t vastly slower than simply introducing extra variables, > so I am going with that solution. However, I have now run into another > problem involving those local variables — and assigning to local variables in > general. > > Consider again the factorial function and three different ways of > implementing it using the tail recursion optimisation: > > factorial <- function(n, acc = 1) { > if (n == 1) acc > else factorial(n - 1, n * acc) > } > > factorial_tr_manual <- function (n, acc = 1) > { > repeat { > if (n <= 1) > return(acc) > else { > .tailr_n <- n - 1 > .tailr_acc <- acc * n > n <- .tailr_n > acc <- .tailr_acc > next > } > } > } > > factorial_tr_automatic_1 <- function(n, acc = 1) { > callCC(function(escape) { > repeat { > if (n <= 1) { > escape(acc) > } else { > .tailr_n <- n - 1 > .tailr_acc <- n * acc > n <- .tailr_n > acc <- .tailr_acc > } > } > }) > } > > factorial_tr_automatic_2 <- function(n, acc = 1) { > .tailr_env <- rlang::get_env() > callCC(function(escape) { > repeat { > if (n <= 1) { > escape(acc) > } else { > .tailr_env$.tailr_n <- n - 1 > .tailr_env$.tailr_acc <- n * acc > .tailr_env$n <- .tailr_env$.tailr_n > .tailr_env$acc <- .tailr_env$.tailr_acc > } > } > }) > } > > The factorial_tr_manual function is how I would implement the function > manually while factorial_tr_automatic_1 is what my package used to come up > with. It handles non-local returns, because this is something I need in > general. Finally, factorial_tr_automatic_2 accesses the local
Re: [R] Parallel assignments and goto
recursion / options(expressions=)? Error during wrapup: C stack usage 7990648 is too close to the limit > llength_tr(make_llist(1000)) [1] 1000 I should be able to make the function go faster if I had a faster way of handling the variable assignments, but inside “with”, I’m not sure how to do that… Any suggestions? Cheers On 11 Feb 2018, 16.48 +0100, Thomas Mailund , wrote: > Hi guys, > > I am working on some code for automatically translating recursive functions > into looping functions to implemented tail-recursion optimisations. See > https://github.com/mailund/tailr > > As a toy-example, consider the factorial function > > factorial <- function(n, acc = 1) { > if (n <= 1) acc > else factorial(n - 1, acc * n) > } > > I can automatically translate this into the loop-version > > factorial_tr_1 <- function (n, acc = 1) > { > repeat { > if (n <= 1) > return(acc) > else { > .tailr_n <- n - 1 > .tailr_acc <- acc * acc > n <- .tailr_n > acc <- .tailr_acc > next > } > } > } > > which will run faster and not have problems with recursion depths. However, > I’m not entirely happy with this version for two reasons: I am not happy with > introducing the temporary variables and this rewrite will not work if I try > to over-scope an evaluation context. > > I have two related questions, one related to parallel assignments — i.e. > expressions to variables so the expression uses the old variable values and > not the new values until the assignments are all done — and one related to > restarting a loop from nested loops or from nested expressions in `with` > expressions or similar. > > I can implement parallel assignment using something like rlang::env_bind: > > factorial_tr_2 <- function (n, acc = 1) > { > .tailr_env <- rlang::get_env() > repeat { > if (n <= 1) > return(acc) > else { > rlang::env_bind(.tailr_env, n = n - 1, acc = acc * n) > next > } > } > } > > This reduces the number of additional variables I need to one, but is a > couple of orders of magnitude slower than the first version. > > > microbenchmark::microbenchmark(factorial(100), > + factorial_tr_1(100), > + factorial_tr_2(100)) > Unit: microseconds > expr min lq mean median uq max neval > factorial(100) 53.978 60.543 77.76203 71.0635 85.947 180.251 100 > factorial_tr_1(100) 9.022 9.903 11.52563 11.0430 11.984 28.464 100 > factorial_tr_2(100) 5870.565 6109.905 6534.13607 6320.4830 6756.463 8177.635 > 100 > > > Is there another way to do parallel assignments that doesn’t cost this much > in running time? > > My other problem is the use of `next`. I would like to combine tail-recursion > optimisation with pattern matching as in https://github.com/mailund/pmatch > where I can, for example, define a linked list like this: > > devtools::install_github("mailund/pmatch”) > library(pmatch) > llist := NIL | CONS(car, cdr : llist) > > and define a function for computing the length of a list like this: > > list_length <- function(lst, acc = 0) { > force(acc) > cases(lst, > NIL -> acc, > CONS(car, cdr) -> list_length(cdr, acc + 1)) > } > > The `cases` function creates an environment that binds variables in a > pattern-description that over-scopes the expression to the right of `->`, so > the recursive call in this example have access to the variables `cdr` and > `car`. > > I can transform a `cases` call to one that creates the environment containing > the bound variables and then evaluate this using `eval` or `with`, but in > either case, a call to `next` will not work in such a context. The expression > will be evaluated inside `bind` or `with`, and not in the `list_lenght` > function. > > A version that *will* work, is something like this > > factorial_tr_3 <- function (n, acc = 1) > { > .tailr_env <- rlang::get_env() > .tailr_frame <- rlang::current_frame() > repeat { > if (n <= 1) > rlang::return_from(.tailr_frame, acc) > else { > rlang::env_bind(.tailr_env, n = n - 1, acc = acc * n) > rlang::return_to(.tailr_frame) > } > } > } > > Here, again, for the factorial function since this is easier to follow than > the list-length function. > > This solution will also work if you return values from inside loops, where > `next` wouldn’t work either. > > Using `rlang::return_from` and `rlang::return_to` implements the right > semantics, but costs me another order of magnitude in running time. > > microbenchmark::microbenchmark(factorial(100), > factorial_tr_1(100), > factorial_tr_2(100), > factorial_tr_3(100)) > Unit: microseconds > expr min lq mean median uq max neval > factoria
Re: [R] Parallel assignments and goto
I admit I didn’t know about Recall, but you are right, there is no direct support for this tail-recursion optimisation. For good reasons — it would break a lot of NSE. I am not attempting to solve tail-recursion optimisation for all cases. That wouldn’t work by just rewriting functions. It might be doable with JIT or something like that, but my goal is less ambitious. Using local, though, might be an approach. I will play around with that tomorrow. Cheers On 11 Feb 2018, 18.19 +0100, David Winsemius , wrote: > > > On Feb 11, 2018, at 7:48 AM, Thomas Mailund > > wrote: > > > > Hi guys, > > > > I am working on some code for automatically translating recursive functions > > into looping functions to implemented tail-recursion optimisations. See > > https://github.com/mailund/tailr > > > > As a toy-example, consider the factorial function > > > > factorial <- function(n, acc = 1) { > > if (n <= 1) acc > > else factorial(n - 1, acc * n) > > } > > > > I can automatically translate this into the loop-version > > > > factorial_tr_1 <- function (n, acc = 1) > > { > > repeat { > > if (n <= 1) > > return(acc) > > else { > > .tailr_n <- n - 1 > > .tailr_acc <- acc * acc > > n <- .tailr_n > > acc <- .tailr_acc > > next > > } > > } > > } > > > > which will run faster and not have problems with recursion depths. However, > > I’m not entirely happy with this version for two reasons: I am not happy > > with introducing the temporary variables and this rewrite will not work if > > I try to over-scope an evaluation context. > > > > I have two related questions, one related to parallel assignments — i.e. > > expressions to variables so the expression uses the old variable values and > > not the new values until the assignments are all done — and one related to > > restarting a loop from nested loops or from nested expressions in `with` > > expressions or similar. > > > > I can implement parallel assignment using something like rlang::env_bind: > > > > factorial_tr_2 <- function (n, acc = 1) > > { > > .tailr_env <- rlang::get_env() > > repeat { > > if (n <= 1) > > return(acc) > > else { > > rlang::env_bind(.tailr_env, n = n - 1, acc = acc * n) > > next > > } > > } > > } > > > > This reduces the number of additional variables I need to one, but is a > > couple of orders of magnitude slower than the first version. > > > > > microbenchmark::microbenchmark(factorial(100), > > + factorial_tr_1(100), > > + factorial_tr_2(100)) > > Unit: microseconds > > expr min lq mean median uq max neval > > factorial(100) 53.978 60.543 77.76203 71.0635 85.947 180.251 100 > > factorial_tr_1(100) 9.022 9.903 11.52563 11.0430 11.984 28.464 100 > > factorial_tr_2(100) 5870.565 6109.905 6534.13607 6320.4830 6756.463 > > 8177.635 100 > > > > > > Is there another way to do parallel assignments that doesn’t cost this much > > in running time? > > > > My other problem is the use of `next`. I would like to combine > > tail-recursion optimisation with pattern matching as in > > https://github.com/mailund/pmatch where I can, for example, define a linked > > list like this: > > > > devtools::install_github("mailund/pmatch”) > > library(pmatch) > > llist := NIL | CONS(car, cdr : llist) > > > > and define a function for computing the length of a list like this: > > > > list_length <- function(lst, acc = 0) { > > force(acc) > > cases(lst, > > NIL -> acc, > > CONS(car, cdr) -> list_length(cdr, acc + 1)) > > } > > > > The `cases` function creates an environment that binds variables in a > > pattern-description that over-scopes the expression to the right of `->`, > > so the recursive call in this example have access to the variables `cdr` > > and `car`. > > > > I can transform a `cases` call to one that creates the environment > > containing the bound variables and then evaluate this using `eval` or > > `with`, but in either case, a call to `next` will not work in such a > > context. The expression will be evaluated inside `bind` or `with`, and not > > in the `list_lenght` function. > > > > A version that *will* work, is something like this > > > > factorial_tr_3 <- function (n, acc = 1) > > { > > .tailr_env <- rlang::get_env() > > .tailr_frame <- rlang::current_frame() > > repeat { > > if (n <
[R] Parallel assignments and goto
Hi guys, I am working on some code for automatically translating recursive functions into looping functions to implemented tail-recursion optimisations. See https://github.com/mailund/tailr As a toy-example, consider the factorial function factorial <- function(n, acc = 1) { if (n <= 1) acc else factorial(n - 1, acc * n) } I can automatically translate this into the loop-version factorial_tr_1 <- function (n, acc = 1) { repeat { if (n <= 1) return(acc) else { .tailr_n <- n - 1 .tailr_acc <- acc * acc n <- .tailr_n acc <- .tailr_acc next } } } which will run faster and not have problems with recursion depths. However, I’m not entirely happy with this version for two reasons: I am not happy with introducing the temporary variables and this rewrite will not work if I try to over-scope an evaluation context. I have two related questions, one related to parallel assignments — i.e. expressions to variables so the expression uses the old variable values and not the new values until the assignments are all done — and one related to restarting a loop from nested loops or from nested expressions in `with` expressions or similar. I can implement parallel assignment using something like rlang::env_bind: factorial_tr_2 <- function (n, acc = 1) { .tailr_env <- rlang::get_env() repeat { if (n <= 1) return(acc) else { rlang::env_bind(.tailr_env, n = n - 1, acc = acc * n) next } } } This reduces the number of additional variables I need to one, but is a couple of orders of magnitude slower than the first version. > microbenchmark::microbenchmark(factorial(100), +factorial_tr_1(100), +factorial_tr_2(100)) Unit: microseconds expr min lq meanmedian uq max neval factorial(100) 53.978 60.543 77.76203 71.0635 85.947 180.251 100 factorial_tr_1(100)9.0229.903 11.52563 11.0430 11.984 28.464 100 factorial_tr_2(100) 5870.565 6109.905 6534.13607 6320.4830 6756.463 8177.635 100 Is there another way to do parallel assignments that doesn’t cost this much in running time? My other problem is the use of `next`. I would like to combine tail-recursion optimisation with pattern matching as in https://github.com/mailund/pmatch where I can, for example, define a linked list like this: devtools::install_github("mailund/pmatch”) library(pmatch) llist := NIL | CONS(car, cdr : llist) and define a function for computing the length of a list like this: list_length <- function(lst, acc = 0) { force(acc) cases(lst, NIL -> acc, CONS(car, cdr) -> list_length(cdr, acc + 1)) } The `cases` function creates an environment that binds variables in a pattern-description that over-scopes the expression to the right of `->`, so the recursive call in this example have access to the variables `cdr` and `car`. I can transform a `cases` call to one that creates the environment containing the bound variables and then evaluate this using `eval` or `with`, but in either case, a call to `next` will not work in such a context. The expression will be evaluated inside `bind` or `with`, and not in the `list_lenght` function. A version that *will* work, is something like this factorial_tr_3 <- function (n, acc = 1) { .tailr_env <- rlang::get_env() .tailr_frame <- rlang::current_frame() repeat { if (n <= 1) rlang::return_from(.tailr_frame, acc) else { rlang::env_bind(.tailr_env, n = n - 1, acc = acc * n) rlang::return_to(.tailr_frame) } } } Here, again, for the factorial function since this is easier to follow than the list-length function. This solution will also work if you return values from inside loops, where `next` wouldn’t work either. Using `rlang::return_from` and `rlang::return_to` implements the right semantics, but costs me another order of magnitude in running time. microbenchmark::microbenchmark(factorial(100), factorial_tr_1(100), factorial_tr_2(100), factorial_tr_3(100)) Unit: microseconds expr min lqmean medianuq max neval factorial(100)52.47960.264093.4306967.513083.925 2062.481 100 factorial_tr_1(100) 8.875 9.652549.1959510.694511.217 3818.823 100 factorial_tr_2(100) 5296.350 5525.0745 5973.77664 5737.8730 6260.128 8471.301 100 factorial_tr_3(100) 77554.457 80757.0905 87307.28737 84004.0725 89859.169 171039.228 100 I can live with the “introducing extra variables” solution to parallel assignment, and I could hack my way out of using `with` or `bind` in
Re: [R] define a list with names as variables
Do you mean like this? > f <- function(foo, bar) { + result <- list(bar) + names(result) <- foo + result + } > (x <- f("hello", "world")) $hello [1] "world" > names(x) [1] "hello" -- Thomas Mailund On 4 August 2017 at 12.08.28, Giovanni Gherdovich (g.gherdov...@gmail.com) wrote: Hello, I'm having troubles defining a list where names are variables (of type character). Like this, which gives "foo" instead of "world" (the way I meant it is that "world" is the value of the variable foo). Any hint? > f <- function(foo, bar) { list(foo = bar) } > x <- f("hello", "world") > names(x) [1] "foo" Thanks, Giovanni __ R-help@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. [[alternative HTML version deleted]] __ R-help@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.
Re: [R] ggplot2 geom_bar arrangement
The order the bars are plotted in is determined by the levels in a factor, and your labels are treated as a factor. You can make sure you keep the order of your labels by simply doing this: Lab <- factor(Lab, levels = Lab) before constructing the data frame. Cheers On 27 Jun 2017, 20.43 +0200, Brian Smith , wrote: > Hi, > > I was trying to draw a geom_bar plot. However, by default, the bars are > arranged according to the label, which I don't want. I want the bars to > appear exactly as they appear in the data frame. For example in the code: > > Lab=c(letters[4:6],letters[1:3]) > valuex = c(3.1,2.3,0.4,-0.4,-1.2,-4.4) > df <- data.frame(Lab,valuex) > px <- ggplot(df,aes(Lab,valuex,label=Lab)) + geom_text(aes(y=0)) + > geom_bar(stat = "identity") > px > > > The default arranges the bars in order 'a' through 'f', but I want them > arranged as per df. > > How can I do this? > > thanks! > > [[alternative HTML version deleted]] > > __ > R-help@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. [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Delayed evaluation / lazy expression evaluation
If anyone are interested, I found a solution for lazy lists. A simplified version of their construction and access looks like this: nil <- function() NULL cons <- function(car, cdr) { force(car) force(cdr) function() list(car = car, cdr = cdr) } is_nil <- function(lst) is.null(lst()) car <- function(lst) lst()$car cdr <- function(lst) lst()$cdr An invariant is that a list is always a thunk that evaluates to either NULL or a list tha contains car and cdr where cdr is another list (i.e. a thunk). Operations on lists can be made lazy by wrapping them in a thunk that returns an evaluated promise. The laziness comes from wrapping an expression in a promise and by evaluating this promise we make it behave like the un-wrapped list would do. So we can, for example, implement lazy reversal and concatenation like this: reverse <- function(lst) { do_reverse <- function(lst) { result <- nil while (!is_nil(lst)) { result <- cons(car(lst), result) lst <- cdr(lst) } result } force(lst) lazy_thunk <- function(lst) { function() lst() } lazy_thunk(do_reverse(lst)) } cat <- function(l1, l2) { do_cat <- function(l1, l2) { rev_l1 <- nil while (!is_nil(l1)) { rev_l1 <- cons(car(l1), rev_l1) l1 <- cdr(l1) } result <- l2 while (!is_nil(rev_l1)) { result <- cons(car(rev_l1), result) rev_l1 <- cdr(rev_l1) } result } force(l1) force(l2) lazy_thunk <- function(lst) { function() lst() } lazy_thunk(do_cat(l1, l2)) } As an example of how this laziness works, we can test concatenation. Concatenating two lists is a fast operation, because we don’t actually evaluate the concatenation, but when we access the list afterward we pay for both the concatenation and the access. vector_to_list <- function(v) { lst <- nil for (x in v) lst <- cons(x, lst) reverse(lst) } l1 <- vector_to_list(1:1) l2 <- vector_to_list(1:1) library(microbenchmark) microbenchmark(lst <- cat(l1, l2), times = 1) # fast operation microbenchmark(car(lst), times = 1) # slow operation microbenchmark(car(lst), times = 1) # faster operation Of course, such a lazy list implementation is just a slow way of implementing lists, but it makes it possible to exploit a combination of amortised analysis and persistent data structures to implement queues http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf Cheers On 24 Apr 2017, 16.35 +0200, Thomas Mailund , wrote: > Hi, I’m playing around with ways of implementing lazy evaluation of > expressions. In R, function arguments are evaluated as promises but > expressions are evaluated immediately, so I am trying to wrap expressions in > thunks—functions with no arguments that evaluate an expression—to get > something the resembles lazy evaluation of expressions. > > As an example, consider this: > > lazy <- function(value) { > function() value > } > > f <- lazy((1:10)[1]) > > If we evaluate f we have to create the long vector and then get the first > element. We delay the evaluation to f so the first time we call f we should > see a slow operation and if we evaluate it again we should see faster > evaluations. If you run this benchmark, you will see that this is indeed what > we get: > > library(microbenchmark) > microbenchmark(f(), times = 1) > microbenchmark(f(), times = 1) > microbenchmark(f(), times = 1) > microbenchmark(f(), times = 1) > > Now, I want to use this to implement lazy linked lists. It is not > particularly important why I want to do this, but if you are interested, it > is because you can implement persistent queues with amortised constant time > operations this way, which is what I am experimenting with. > > I have this implementation of linked lists: > > list_cons <- function(elem, lst) > structure(list(head = elem, tail = lst), class = "linked_list") > > list_nil <- list_cons(NA, NULL) > empty_list <- function() list_nil > is_empty.linked_list <- function(x) identical(x, list_nil) > > > You can implement it simpler using NULL as an empty list, but this particular > implementation lets me use polymorphism to implement different versions of > data structures — the reasoning is explained in chapter 2 of a book I’m > working on: https://www.dropbox.com/s/qdnjc0bx4yivl8r/book.pdf?dl=0 > > Anyway, that list implementation doesn’t evaluate the lists lazily, so I am > trying to wrap these lists in calls to lazy(). > > A simple implementation looks like this: > > > lazy_empty_list <- lazy(empty_list()) > lazy_cons <- function(elm, lst) { > lazy(list_cons(elm, lst())) > } > > Now, this works fine for adding an
Re: [R] asking for help
If you write something like indices <- rep(1:(163863/6069), each = 6069) you can get the i’th block of rows with table[indices == i,] It looks like a little more work than a loop would be since you have to run through all rows for each block, but the implicit loop in this approach is likely to be faster than an explicit for-loop. Cheers Thomas On 25 Apr 2017, 07.01 +0200, Saifuddin, Miah Mohammad , wrote: I have a data frame having 163863 values. I want to subset it so that each set has 6069 values in it. for example 1:6069 as first, 6070: 6070+6068 as second. how can I do that, preferably in a loop. TIA [[alternative HTML version deleted]] __ R-help@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. [[alternative HTML version deleted]] __ R-help@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.
[R] Delayed evaluation / lazy expression evaluation
Hi, I’m playing around with ways of implementing lazy evaluation of expressions. In R, function arguments are evaluated as promises but expressions are evaluated immediately, so I am trying to wrap expressions in thunks—functions with no arguments that evaluate an expression—to get something the resembles lazy evaluation of expressions. As an example, consider this: lazy <- function(value) { function() value } f <- lazy((1:10)[1]) If we evaluate f we have to create the long vector and then get the first element. We delay the evaluation to f so the first time we call f we should see a slow operation and if we evaluate it again we should see faster evaluations. If you run this benchmark, you will see that this is indeed what we get: library(microbenchmark) microbenchmark(f(), times = 1) microbenchmark(f(), times = 1) microbenchmark(f(), times = 1) microbenchmark(f(), times = 1) Now, I want to use this to implement lazy linked lists. It is not particularly important why I want to do this, but if you are interested, it is because you can implement persistent queues with amortised constant time operations this way, which is what I am experimenting with. I have this implementation of linked lists: list_cons <- function(elem, lst) structure(list(head = elem, tail = lst), class = "linked_list") list_nil <- list_cons(NA, NULL) empty_list <- function() list_nil is_empty.linked_list <- function(x) identical(x, list_nil) You can implement it simpler using NULL as an empty list, but this particular implementation lets me use polymorphism to implement different versions of data structures — the reasoning is explained in chapter 2 of a book I’m working on: https://www.dropbox.com/s/qdnjc0bx4yivl8r/book.pdf?dl=0 Anyway, that list implementation doesn’t evaluate the lists lazily, so I am trying to wrap these lists in calls to lazy(). A simple implementation looks like this: lazy_empty_list <- lazy(empty_list()) lazy_cons <- function(elm, lst) { lazy(list_cons(elm, lst())) } Now, this works fine for adding an element to an empty list: lst <- lazy_cons(2, lazy_empty_list) lst() It also works fine if I add another element to an expression for constructing a list: lst <- lazy_cons(1, lazy_cons(2, lazy_empty_list)) lst() I can construct lists as long as I want, as long as I explicitly give the lazy_cons() function an expression for the list: lst <- lazy_cons(1, lazy_cons(2, lazy_cons(3, lazy_empty_list))) lst() However, if I save intermediate lists in a variable, it breaks down. This code: lst <- lazy_cons(2, lazy_empty_list) lst <- lazy_cons(1, lst) lst() gives me this error: Error in lst() : promise already under evaluation: recursive default argument reference or earlier problems? Now, I am particularly dense today, it being Monday and all, so there is likely to be something very obvious I am missing, but I would think that the “lit” variable, when passed to lazy_cons(), would be interpreted as a promise to be evaluated in the parent environment, so I don’t see why it is considered a circular definition of it. If I force the list to be evaluated, it all works, and the first evaluation is more expensive than the following: lazy_cons <- function(elm, lst) { force(lst) lazy(list_cons(elm, lst())) } lst <- lazy_cons(1, lazy_empty_list) lst <- lazy_cons(2, lst) lst <- lazy_cons(3, lst) microbenchmark(lst(), times = 1) microbenchmark(lst(), times = 1) microbenchmark(lst(), times = 1) But if I do the exact same thing in a for-loop, it breaks again—this does not work and I get the same error as earlier: lst <- lazy_empty_list() for (e in 1:3) { lst <- lazy_cons(e, lst) } microbenchmark(lst(), times = 1) microbenchmark(lst(), times = 1) microbenchmark(lst(), times = 1) I really can’t see what the difference is between the loop version and the explicitly unwrapping of the loop, but R certainly sees a difference… I would really love to hear if any of you guys have any insights to what is going on here... Cheers [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Peformance question
I did try to profile it but I'll throw some more experiments at it. Right now I suspect it is mostly a problem of wrapping the data in objects which I do more for the purely functional version than the other two, but I'll experiment some more Cheers Thomas On 21 Apr 2017, 13.20 +0200, Paul Johnson , wrote: > I dont understand your code. But I do have suggestion. Run the functions in > the profiler, maybe differences will point at the enemy. > > Know what I mean? > > Rprof('check.out') > #run code > Rprof(NULL) > summaryRprof('check.out') > > Do that for each method. That may be uninformative. > > I wondered if you tried to compile your functions? In some cases it helps > erase differences like this. Norman Matloff has examples like that in Art of > R Programming. > > I keep a list of things that are slow, if we can put finger on problem, I > will add to list. I suspect slow here is in runtime object lookup. The > environment ones have info located more quickly by the runtime, I expect. > Also, passing info back and forth from the R runtime system using [ is a > common cause of slow. It is why everybody yells 'vectorize' and 'use lapply' > all the time. Then again, I'm guessing because I dont understand your code:) > > Good luck, > PJ > > > > > On Apr 11, 2017 7:44 PM, "Thomas Mailund" (mailto:thomas.mail...@gmail.com)> wrote: > > Hi y’all, > > > > I’m working on a book on how to implement functional data structures in R, > > and in particular on a chapter on implementing queues. You get get the > > current version here > > https://www.dropbox.com/s/9c2yk3a67p1ypmr/book.pdf?dl=0 and the relevant > > pages are 50-59. I’ve implemented three versions of the same idea, > > implementing a queue using two linked lists. One list contains the elements > > you add to the end of a list, the other contains the elements at the front > > of the list, and when you try to get an element from a list and the > > front-list is empty you move elements from the back-list to the front. The > > asymptotic analysis is explained in this figure > > https://www.dropbox.com/s/tzi84zmyq16hdx0/queue-amortized-linear-bound.png?dl=0 > > and all my implementations do get a linear time complexity when I evaluate > > them on a linear number of operations. However, the two implementations > > that uses environments seem to be almost twice as fast as the > > implementation that gives me a persistent data structure (see > > https://www.dropbox.com/s/i9dyab9ordkm0xj/queue-comparisons.png?dl=0), and > > I cannot figure out why. > > > > The code below contains the implementation of all three versions of the > > queue plus the code I use to measure their performances. I’m sorry it is a > > little long, but it is a minimal implementation of all three variants, the > > comments just make it look longer than it really is. > > > > Since the three implementations are doing basically the same things, I am a > > little stumped about why the performance is so consistently different. > > > > Can anyone shed some light on this, or help me figure out how to explore > > this further? > > > > Cheers > > > > Thomas > > > > > > > > ## Implementations of queues ## > > > > #' Test if a data structure is empty > > #' @param x The data structure > > #' @return TRUE if x is empty. > > #' @export > > is_empty <- function(x) UseMethod("is_empty") > > > > #' Add an element to a queue > > #' @param x A queue > > #' @param elm An element > > #' @return an updated queue where the element has been added > > #' @export > > enqueue <- function(x, elm) UseMethod("enqueue") > > > > #' Get the front element of a queue > > #' @param x A queue > > #' @return the front element of the queue > > #' @export > > front <- function(x) UseMethod("front") > > > > #' Remove the front element of a queue > > #' @param x The queue > > #' @return The updated queue > > #' @export > > dequeue <- function(x) UseMethod("dequeue") > > > > ## Linked lists # > > > > #' Add a head item to a linked list. > > #' @param elem The item to put at the head of the list. > > #' @param lst The list -- it will become the tail of the new list. > > #' @return a new linked list. > > #' @expor
[R] Peformance question
Hi y’all, I’m working on a book on how to implement functional data structures in R, and in particular on a chapter on implementing queues. You get get the current version here https://www.dropbox.com/s/9c2yk3a67p1ypmr/book.pdf?dl=0 and the relevant pages are 50-59. I’ve implemented three versions of the same idea, implementing a queue using two linked lists. One list contains the elements you add to the end of a list, the other contains the elements at the front of the list, and when you try to get an element from a list and the front-list is empty you move elements from the back-list to the front. The asymptotic analysis is explained in this figure https://www.dropbox.com/s/tzi84zmyq16hdx0/queue-amortized-linear-bound.png?dl=0 and all my implementations do get a linear time complexity when I evaluate them on a linear number of operations. However, the two implementations that uses environments seem to be almost twice as fast as the implementation that gives me a persistent data structure (see https://www.dropbox.com/s/i9dyab9ordkm0xj/queue-comparisons.png?dl=0), and I cannot figure out why. The code below contains the implementation of all three versions of the queue plus the code I use to measure their performances. I’m sorry it is a little long, but it is a minimal implementation of all three variants, the comments just make it look longer than it really is. Since the three implementations are doing basically the same things, I am a little stumped about why the performance is so consistently different. Can anyone shed some light on this, or help me figure out how to explore this further? Cheers Thomas ## Implementations of queues ## #' Test if a data structure is empty #' @param x The data structure #' @return TRUE if x is empty. #' @export is_empty <- function(x) UseMethod("is_empty") #' Add an element to a queue #' @param x A queue #' @param elm An element #' @return an updated queue where the element has been added #' @export enqueue <- function(x, elm) UseMethod("enqueue") #' Get the front element of a queue #' @param x A queue #' @return the front element of the queue #' @export front <- function(x) UseMethod("front") #' Remove the front element of a queue #' @param x The queue #' @return The updated queue #' @export dequeue <- function(x) UseMethod("dequeue") ## Linked lists # #' Add a head item to a linked list. #' @param elem The item to put at the head of the list. #' @param lst The list -- it will become the tail of the new list. #' @return a new linked list. #' @export list_cons <- function(elem, lst) structure(list(head = elem, tail = lst), class = "linked_list") list_nil <- list_cons(NA, NULL) #' @method is_empty linked_list #' @export is_empty.linked_list <- function(x) identical(x, list_nil) #' Create an empty linked list. #' @return an empty linked list. #' @export empty_list <- function() list_nil #' Get the item at the head of a linked list. #' @param lst The list #' @return The element at the head of the list. #' @export list_head <- function(lst) lst$head #' Get the tail of a linked list. #' @param lst The list #' @return The tail of the list #' @export list_tail <- function(lst) lst$tail #' Reverse a list #' @param lst A list #' @return the reverse of lst #' @export list_reverse <- function(lst) { acc <- empty_list() while (!is_empty(lst)) { acc <- list_cons(list_head(lst), acc) lst <- list_tail(lst) } acc } ## Environment queues # queue_environment <- function(front, back) { e <- new.env(parent = emptyenv()) e$front <- front e$back <- back class(e) <- c("env_queue", "environment") e } #' Construct an empty closure based queue #' @return an empty queue #' @export empty_env_queue <- function() queue_environment(empty_list(), empty_list()) #' @method is_empty env_queue #' @export is_empty.env_queue <- function(x) is_empty(x$front) && is_empty(x$back) #' @method enqueue env_queue #' @export enqueue.env_queue <- function(x, elm) { x$back <- list_cons(elm, x$back) x } #' @method front env_queue #' @export front.env_queue <- function(x) { if (is_empty(x$front)) { x$front <- list_reverse(x$back) x$back <- empty_list() } list_head(x$front) } #' @method dequeue env_queue #' @export dequeue.env_queue <- function(x) { if (is_empty(x$front)) { x$front <- list_reverse(x$back) x$back <- empty_list() } x$front <- list_tail(x$front) x } ## Closure queues # queue <- function(front, back) list(front = front, back = back) queue_closure <- function() { q <- queue(empty_list(), empty_list()) get_queue <- function() q queue_is_empty <- function() is_empty(q$front) && is_empty(q$back) enqueue <- function(elm) { q <<- queue(q$front, list_cons(elm, q$back)) } front <- function() { if (queue_is_empty()) stop("Taking the f
Re: [R] Assessing the name of an object within an argument
Yes, I was too fast there, sorry. I sent a correction right after but must have picked Reply instead of Replay All. Cheers Thomas On 10 January 2017 at 10:31:30, Bert Gunter (bgunter.4...@gmail.com<mailto:bgunter.4...@gmail.com>) wrote: This is false. formals() gives the FORMAL argument list of the function, not the ACTUAL arguments supplied. That is obtained by the construction deparse(substitute(dataset)) The OP should consult a good R tutorial for this and other uses of substitute(), part of the "computing on the language" functionality of R. Bert On Jan 10, 2017 4:04 AM, "Thomas Mailund" mailto:mail...@birc.au.dk>> wrote: You can get that using `formals()`. my_func <- function(dataset = iris) { #print(dataset) # here I do not want to print the dataset but the name # of the object - iris in this case - instead print(formals()$dataset) # this is what you want } This gives you what the arguments were as an alist. It won’t always be a name, of course, but when it is, as in this case, that will be a symbol you can print. Cheers Thomas On 10 January 2017 at 09:51:55, g.maub...@weinwolf.de<mailto:g.maub...@weinwolf.de> (g.maub...@weinwolf.de<mailto:g.maub...@weinwolf.de>(mailto:g.maub...@weinwolf.de<mailto:g.maub...@weinwolf.de>)) wrote: > Hi All, > > I have a function like > > my_func <- function(dataset) > { > some operation > } > > Now I would like not only to operate on the dataset (how this is done is > obvious) but I would like to get the name of the dataset handed over as an > argument. > > Example: > > my_func <- function(dataset = iris) > { > print(dataset) # here I do not want to print the dataset but the name > of the object - iris in this case - instead > # quote() does not do the trick cause it prints "dataset" instead of > "iris" > # as.name<http://as.name>() gives an error saying that the object can not > coerced to a > symbol > } > > Is there a way to do this? > > Kind regards > > Georg > > __ > R-help@r-project.org<mailto:R-help@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. __ R-help@r-project.org<mailto:R-help@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. [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Assessing the name of an object within an argument
You can get that using `formals()`. my_func <- function(dataset = iris) { #print(dataset) # here I do not want to print the dataset but the name # of the object - iris in this case - instead print(formals()$dataset) # this is what you want } This gives you what the arguments were as an alist. It won’t always be a name, of course, but when it is, as in this case, that will be a symbol you can print. Cheers Thomas On 10 January 2017 at 09:51:55, g.maub...@weinwolf.de (g.maub...@weinwolf.de(mailto:g.maub...@weinwolf.de)) wrote: > Hi All, > > I have a function like > > my_func <- function(dataset) > { > some operation > } > > Now I would like not only to operate on the dataset (how this is done is > obvious) but I would like to get the name of the dataset handed over as an > argument. > > Example: > > my_func <- function(dataset = iris) > { > print(dataset) # here I do not want to print the dataset but the name > of the object - iris in this case - instead > # quote() does not do the trick cause it prints "dataset" instead of > "iris" > # as.name() gives an error saying that the object can not coerced to a > symbol > } > > Is there a way to do this? > > Kind regards > > Georg > > __ > R-help@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. __ R-help@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.
Re: [R] Please help me, I'm trying to update my version of R
Hi Ken, You are trying to install R as a package. That won't work. The .pkg file you downloaded from https://cran.r-project.org/bin/macosx/ is an installer, though, so if you just double-click on it, it should take you through the installation. After that you probably need to install a number of packages, since the ones you have installed for version 3.2 R won't be available in the 3.3 installation, but *those* packages you can install using install.packages. Cheers -- Thomas Mailund On 22 August 2016 at 22:17:50, KMNanus (kmna...@gmail.com<mailto:kmna...@gmail.com>) wrote: I’m a newbie running 3.2.4 on a mac equipped with Yosemite (10.10.5). I want to update to 3.3.1 and have downloaded the package, but have not been able to install it. I’ve tried install.packages("R-3.3.1.tar.gz”) and install.packages("R-3.3.1.pkg”) after downloading both files. I get an error msg - "package ‘R-3.3.1.pkg’ is not available (for R version 3.2.4)" I know this question has shown up on several message boards but I’m having trouble understanding the process. Is there a straightforward way to update my version of R and, if successful, will R automatically work with the packages I’ve installed? Ken Nanus kmna...@gmail.com 914-450-0816 (tel) 347-730-4813 (fax) __ R-help@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. [[alternative HTML version deleted]] __ R-help@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.
Re: [R] optimize the filling of a diagonal matrix (two for loops)
The nested for-loops could very easily be moved to Rcpp which should speed them up. Using apply functions instead of for-loops will not make it faster; they still have to do the same looping. At least, when I use `outer` to replace the loop I get roughly the same speed for the two versions — although the `outer` solution does iterate over the entire matrix and not just the upper-triangular matrix. library(stringdist) # I don’t have TSmining library installed so I tested with this instead for_loop_test <- function() { matrixPrepared <- matrix(NA, nrow = nrow(dataS), ncol = nrow(dataS)) for (i in 1:(nrow(dataS)-1)){ for (j in (1+i):nrow(dataS)){ matrixPrepared[i, j] <- stringdist(paste0(as.character(dataS[i,]), collapse=""), paste0(as.character(dataS[j,]), collapse="")) } } matrixPrepared } apply_test <- function() { get_dist <- function(i, j) { if (i <= j) NA else stringdist(paste0(as.character(dataS[i,]), collapse=""), paste0(as.character(dataS[j,]), collapse="")) } get_dist <- Vectorize(get_dist) t(outer(1:nrow(dataS), 1:nrow(dataS), get_dist)) } library(microbenchmark) equivalent <- function(x, y) (is.na(x) && is.na(y)) || (x == y) check <- function(values) all(equivalent(values[[1]], values[[2]])) microbenchmark(for_loop_test(), apply_test(), check = check, times = 5) Cheers Thomas On 18 August 2016 at 17:41:01, AURORA GONZALEZ VIDAL (aurora.gonzal...@um.es(mailto:aurora.gonzal...@um.es)) wrote: > Hello > > I have two for loops that I am trying to optimize... I looked for > vectorization or for using some funcions of the apply family but really > cannot do it. I am writting my code with some small data set. With this > size there is no problem but sometimes I will have hundreds of rows so it > is really important to optimize the code. Any suggestion will be very > welcomed. > > library("TSMining") > dataS = data.frame(V1 = sample(c(1,2,3,4),30,replace = T), > V2 = sample(c(1,2,3,4),30,replace = > T), > V3 = sample(c(1,2,3,4),30,replace = > T), > V4 = sample(c(1,2,3,4),30,replace = > T)) > saxM = Func.matrix(5) > colnames(saxM) = 1:5 > rownames(saxM) = 1:5 > matrixPrepared = matrix(NA, nrow = nrow(dataS), ncol = nrow(dataS)) > > FOR(I IN 1:(NROW(DATAS)-1)){ > FOR(J IN (1+I):NROW(DATAS)){ > MATRIXPREPARED[I,J] = FUNC.DIST(AS.CHARACTER(DATAS[I,]), > AS.CHARACTER(DATAS[J,]), SAXM, N=60) > } > } > matrixPrepared > > Thank you! > > > -- > Aurora González Vidal > Phd student in Data Analytics for Energy Efficiency > > Faculty of Computer Sciences > University of Murcia > > @. aurora.gonzal...@um.es > T. 868 88 7866 > www.um.es/ae > > [[alternative HTML version deleted]] > > __ > R-help@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. __ R-help@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.
Re: [R] get() within function
Hi Ivan, ls() inside a function gives you the variables in the local scope. If you want to get the variables defined in the global scope you need to tell ls() that. Check the difference between these three functions: > foo <- function() ls() > foo() Returns character(0) because there are no local variables. > bar <- function(x) ls() > bar(1) Returns “x” because ls() sees the function parameter > baz <- function() ls(envir = .GlobalEnv) > baz() Returns all the variables in the global environment. If you change your function foo() to this, it should work: foo <- function() { selected_names <- sapply(ls(.GlobalEnv), function(x) class(get(x))) %in% c("data.frame","list") df.list <- ls(.GlobalEnv)[selected_names] dat.str <- select.list(choices=df.list, title="Select object") dat <- get(dat.str) str(dat) } Cheers Thomas On 18 August 2016 at 12:21:33, Ivan Calandra (ivan.calan...@univ-reims.fr(mailto:ivan.calan...@univ-reims.fr)) wrote: > Dear useRs, > > For an interactive use, I am trying to write a function that looks for > all data.frames and lists in the environment and ask the user to select > one of them. I then run some operations on this object. > > This is what I am trying: > > foo <- function(){ > df.list <- ls()[sapply(ls(), function(x) class(get(x))) %in% > c("data.frame","list")] > dat.str <- select.list(choices=df.list, title="Select object") > dat <- get(dat.str) > str(dat) > } > > Let's say I have these three objects: > vec <- 1:10 > mylist <- list(1:3) > datf <- data.frame(var1=rnorm(10), var2=rnorm(10)) > > I would like the function to show me only mylist and datf in the dialog > box. Everything works fine if I take the code out of the function, but > when I run foo() I get this error: > "Error in get(dat.str) : first argument incorrect" > > Is there a problem with using get() within a function? Maybe a problem > with environments? > > Thank you in advance for any help! > Ivan > > -- > Ivan Calandra, PhD > Scientific Mediator > University of Reims Champagne-Ardenne > GEGENAA - EA 3795 > CREA - 2 esplanade Roland Garros > 51100 Reims, France > +33(0)3 26 77 36 89 > ivan.calan...@univ-reims.fr > -- > https://www.researchgate.net/profile/Ivan_Calandra > https://publons.com/author/705639/ > > __ > R-help@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. __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
I don’t know… that was the behaviour I had yesterday, but on the laptop where I was doing the experiments I updated R from 3.2 to 3.3 earlier today and now the original make_thunk make_thunk <- function(f, …) function() f(…) also works for me. I don’t know what else I can say to that :) Cheers Thomas On 11 August 2016 at 23:05:29, Duncan Murdoch (murdoch.dun...@gmail.com<mailto:murdoch.dun...@gmail.com>) wrote: On 10/08/2016 1:28 PM, Duncan Murdoch wrote: > On 10/08/2016 1:10 PM, Thomas Mailund 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. > > The original version > > make_thunk <- function(f, ...) function() f(…) > > says to construct a new function whose body evaluates the expression > f(...). It never evaluates f nor ... , so they don't get evaluated > until the first time you evaluate that new function. > > My version containing list(...) forces evaluation of ... . It would > have been even better to use > > make_thunk <- function(f, ...) { list(f, ...); function() f(…) } > > because that forces evaluation of both arguments. > > I suspect you would have problems with > > make_thunk <- function(f, ...) function() do.call(f, list(...)) > > for exactly the same reasons as the original; I'm surprised that you > found it appears to work. I have done some experimentation, and am unable to reproduce the behaviour you described. Using do.call() doesn't affect things. Duncan Murdoch [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
Yes, I am aware of this situation and I agree that it is better to force f. I was simply trying to figure out why it was necessary in this particular program where the only repeated assignment anywhere in the code is in trampoline, in a scope none of the thunks can see. What ever my problem was, it was not that the binding of f changes. The code works correctly if I output info with cat, so unless cat could affect this it can't be. I still don't quite understand that but I suspect it is ... that is doing something I don't understand. Either that or my understanding of in which scope lazy parameters get evaluated is completely wrong. Anyway, that being said, you are of course right that it is better to force f in my actual program, and I will. Thanks On 10 August 2016 at 22:22:32, Duncan Murdoch (murdoch.dun...@gmail.com<mailto:murdoch.dun...@gmail.com>) wrote: On 10/08/2016 2:39 PM, Thomas Mailund wrote: 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)) } Where that will fail is in a situation like this: thunklist <- list(thunk_factorial, thunk_somethingelse) for (i in seq_along(thunklist)) thunklist[[i]] <- make_thunk(thunklist[[i]]) The problem is that the first time thunklist[[1]] is evaluated, it will call the function thunklist[[2]] (or something else if i has been modified in the meantime), and things will go bad. That's why it's important to force both f and ... in make_thunk. Duncan Murdoch 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 (mail...@birc.au.dk(mailto:mail...@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 th
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
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 (mail...@birc.au.dk(mailto:mail...@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@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. __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
Well, they stay at 3 when I call cat (except for the final step going down in they recursion where `identity` is called, where they are 4). They do that both when I evaluate ... in the `make_thunk` function and when I don’t. But then, when I call `cat` it also worked before. I cannot keep `cat` in there and still get the error, something that is *really* puzzling me. On 10 August 2016 at 19:48:47, William Dunlap (wdun...@tibco.com(mailto:wdun...@tibco.com)) wrote: > You may gain some understanding of what is going on by adding > the output of sys.nframe() or length(sys.calls()) to the cat() statement. > __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
I am not sure I can see exactly how the parameters are changing at all, regardless of which of the versions I am using. Nowhere in the code do I ever modify assign to a variable (except for defining the global-level functions). I think my problem is that I don’t really understand ... here. I would expect these two cases, with and without a thunk, to give me the same output, but they clearly do not. x <- function(...) eval(substitute(alist(...))) x(a = 2, b = 3) x(c = 4, d = 5) xx <- function(...) function() eval(substitute(alist(...))) xx(a = 2, b = 3)() xx(c = 4, d = 5)() The first gives me the parameters and the second just … back. How is the thunk actually seeing ... and why does it work with do.call and not with direct call? library(pryr) xxx <- function(...) function() do.call(eval %.% substitute %.% alist, list(...)) xxx(a = 2, b = 3)() xxx(c = 4, d = 5)() gives me the same results as the xx case, so it is not the do.call that does it, even though that works in my examples. With <- function(...) { list(...) ; function() eval(substitute(alist(...))) } (a = 2, b = 3)() (c = 4, d = 5)() it is the same. Explicitly naming the parameters, of course works fine y <- function( ...) { params <- list(...) ; function() params } y(a = 2, b = 3)() y(c = 4, d = 5)() Here I get the expected lists out. I guess I just shouldn’t be using ... in an inner function that refers to the parameters in an outer function. I’m not even sure what that should be expected to do and I certainly do not understand what is happening :) Explicitly remembering the parameters seems to work fine, though. Cheers Thomas On 10 August 2016 at 19:28:43, Duncan Murdoch (murdoch.dun...@gmail.com(mailto:murdoch.dun...@gmail.com)) wrote: > On 10/08/2016 1:10 PM, Thomas Mailund 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. > > The original version > > make_thunk <- function(f, ...) function() f(…) > > says to construct a new function whose body evaluates the expression > f(...). It never evaluates f nor ... , so they don't get evaluated > until the first time you evaluate that new function. > > My version containing list(...) forces evaluation of ... . It would > have been even better to use > > make_thunk <- function(f, ...) { list(f, ...); function() f(…) } > > because that forces evaluation of both arguments. > > I suspect you would have problems with > > make_thunk <- function(f, ...) function() do.call(f, list(...)) > > for exactly the same reasons as the original; I'm surprised that you > found it appears to work. > > Duncan Murdoch > > > > > 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@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
On 10 Aug 2016, at 19:15, Bert Gunter mailto:bgunter.4...@gmail.com>> wrote: make_thunk is probably unnecessary and apparently problematic. I think you could use do.call() instead, as do.call(f,list(...)) . Yes, make_thunk <- function(f, ...) function() do.call(f, list(...)) also works as far as I can see, yes. I do need to turn it into a thunk, though, as far as I can see. Thanks Thomas [[alternative HTML version deleted]] __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
But wait, how is it actually changing? And how did calling `cat` make the problem go away? Ok, I will go think about it… Thanks anyway, it seems to do the trick. > On 10 Aug 2016, at 19:10, Thomas Mailund 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@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. __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
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@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
An alternative implementation, closer to what I need when I have more than one recursion in each step, but still using factorial as the example, is this one: thunk_factorial <- function(n, continuation = identity) { force(continuation) # if I remove this line I get an error cat("call: ", n, "\n") # same for this line if (n == 1) { continuation(1) } else { new_continuation <- function(result) { cat("thunk: ", result, "\n”) # remove this line and it fails, keep it and it works make_thunk(continuation, n * result) } make_thunk(thunk_factorial, n - 1, new_continuation) } } trampoline(thunk_factorial(1)) Here I am making a continuation instead of passing along an accumulator, which I need to do for more complex cases, and with that continuation I can also get it to complete without errors if I output the text inside it. Removing the `cat` line and I get the recursion error… Cheers Thomas > On 10 Aug 2016, at 18:53, 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. > > Sorry > Thomas > > > > __ > R-help@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. __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
> 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. Sorry Thomas __ R-help@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.
Re: [R] Continuation-parsing / trampoline / infinite recursion problem
Oh, I see that the make_thunk function is missing in my example. It is just this one make_thunk <- function(f, ...) f(...) On 9 August 2016 at 21:57:05, Thomas Mailund (mail...@birc.au.dk(mailto:mail...@birc.au.dk)) wrote: > [I’m really sorry if you receive this mail twice. I just noticed I had sent > it from a different account that the one I signed up to the mailing list on > and I don’t know if that means it will be filtered; at least I haven’t > received it myself yet.] > > > I am playing around with continuation-passing style recursions and want to > use the trampoline approach to avoiding too deep recursions. I want to do > recursions on a tree so I cannot simply simulate a tail-recursion with a loop > and need something else, and rather than simulating my own stack I want to > use the method that solves this in general. > > I cannot seem to get out of problems with the > > Error: evaluation nested too deeply: infinite recursion / > options(expressions=)? > Error during wrapup: evaluation nested too deeply: infinite recursion / > options(expressions=)? > > error, so I reduced the problem to just computing factorials to see if I > could at least get it to work there, but here I get the problem as well, and > in the example below I am completely stumped as to why. > > trampoline <- function(thunk) { > while (is.function(thunk)) thunk <- thunk() > thunk > } > > thunk_factorial <- function(n, continuation = identity, acc = 1) { > force(continuation) # if I remove this line I get an error > cat("call: ", n, " : ", acc, "\n") # same for this line > if (n == 1) { > continuation(acc) > } else { > make_thunk(thunk_factorial, n - 1, continuation, n * acc) > } > } > trampoline(thunk_factorial(1)) > > This version works for me. If I remove the “force(continuation)” it doesn’t — > even though I never modify the contination in this function (in the tree I > want to do recursion on I will have to). I get all the way down the simulated > recursion to the final call of the continuation and then I get the error. So > as far as I would expect I should just get the identity of the final > accumulator at the end, but instead I get the error. > > If I remove the cat-call I also get the error. That *really* puzzles me. What > is cat doing that lets me complete the function when it is involved but not > when I comment out that line? > > There is clearly something about this infinite recursion error I am > completely missing. Any help would be greatly appreciated. > > Cheers > Thomas > __ R-help@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.
[R] Continuation-parsing / trampoline / infinite recursion problem
[I’m really sorry if you receive this mail twice. I just noticed I had sent it from a different account that the one I signed up to the mailing list on and I don’t know if that means it will be filtered; at least I haven’t received it myself yet.] I am playing around with continuation-passing style recursions and want to use the trampoline approach to avoiding too deep recursions. I want to do recursions on a tree so I cannot simply simulate a tail-recursion with a loop and need something else, and rather than simulating my own stack I want to use the method that solves this in general. I cannot seem to get out of problems with the Error: evaluation nested too deeply: infinite recursion / options(expressions=)? Error during wrapup: evaluation nested too deeply: infinite recursion / options(expressions=)? error, so I reduced the problem to just computing factorials to see if I could at least get it to work there, but here I get the problem as well, and in the example below I am completely stumped as to why. trampoline <- function(thunk) { while (is.function(thunk)) thunk <- thunk() thunk } thunk_factorial <- function(n, continuation = identity, acc = 1) { force(continuation) # if I remove this line I get an error cat("call: ", n, " : ", acc, "\n") # same for this line if (n == 1) { continuation(acc) } else { make_thunk(thunk_factorial, n - 1, continuation, n * acc) } } trampoline(thunk_factorial(1)) This version works for me. If I remove the “force(continuation)” it doesn’t — even though I never modify the contination in this function (in the tree I want to do recursion on I will have to). I get all the way down the simulated recursion to the final call of the continuation and then I get the error. So as far as I would expect I should just get the identity of the final accumulator at the end, but instead I get the error. If I remove the cat-call I also get the error. That *really* puzzles me. What is cat doing that lets me complete the function when it is involved but not when I comment out that line? There is clearly something about this infinite recursion error I am completely missing. Any help would be greatly appreciated. Cheers Thomas [[alternative HTML version deleted]] __ R-help@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.