R lazy evaluation paradox (R bug?) - r

I have multiple functions handing around arguments that may be missing.
e.g. i have
mainfunction <- function(somearg) {
mytest(somearg)
fun <- function() { subfunction(somearg) }
fun()
}
with the interesting aspect that the only interaction of mytest(somearg) with the arg is that it tests if the argument isn’t missing:
mytest = function(somearg) {
print(missing(somearg))
}
subfunction then again tests if it’s missing and treats it accordingly:
subfunction = function(somearg) {
if (missing(somearg))
somearg = NULL
else
somearg = matrix(somearg, cols = 2)
# somearg is used here…
}
the kicker is that, with somearg missing, this doesn’t work: matrix(somearg, cols = 2) throws
argument "somearg" is missing, with no default
during debugging, i found the following:
at the start of mainfunction, missing(somearg) returns TRUE
in mytest, missing(somearg) returns TRUE
insubfunction, missing(somearg) returns FALSE (!!!!)
therefore the matrix branch is hit, but in reality, somearg is missing, so it fails…
wat.

the #BenBolker way:
mainfunction <- function(somearg = NULL) {
mytest(somearg)
fun <- function() { subfunction(somearg) }
fun()
}
mytest = function(somearg) {
print(is.null(somearg))
}
subfunction = function(somearg) {
if (is.null(somearg))
somearg = 1:10
else
somearg = matrix(somearg, ncol = 2)
somearg
}
Another way, using explicit missing argument
mainfunction <- function(somearg) {
is_missing <- missing(somearg)
mytest(is_missing)
fun <- function() { subfunction(somearg, is_missing) }
fun()
}
mytest = function(x) { print(x) }
subfunction = function(somearg, is_arg_missing) {
if (is_arg_missing)
somearg = 1:10
else
somearg = matrix(somearg, ncol = 2)
somearg
}
A third way, using plain missing arg passing:
mainfunction <- function(somearg) {
is_missing <- missing(somearg)
mytest(somearg)
fun <- function() {
if (is_missing) subfunction() else
subfunction(somearg)
}
fun()
}
mytest = function(somearg) {
print(missing(somearg))
}
subfunction = function(somearg) {
if (missing(somearg))
somearg = 1:10
else
somearg = matrix(somearg, ncol = 2)
somearg
}

Related

Defined `tryCatch` function operator incorrect return

I want to define a function operator that will get a plot as input and in case it produces an error it should return another plot.
My try:
handle_plot_error <- function(f) {
wrapper <- function(...) {
tryCatch(
{
f(...)
},
error = function(e) {
hist(1:3)
}
)
}
wrapper
}
But when I try:
handle_plot_error(plot(1,1))
it returns:
function(...) {
tryCatch(
{
return(f(...))
},
error = function(e) {
return(hist(1:3))
}
)
}
<bytecode: 0x7ff29dc38668>
<environment: 0x7ff29d9fab00>
Why are you using wrapper ? You may try :
handle_plot_error <- function(f) {
tryCatch(
{
f
},
error = function(e) {
hist(1:3)
}
)
}
where :
#No error plot
handle_plot_error(plot(1, 1)) #returns
and
#Error plot
handle_plot_error(plot(1:5, a = 2)) #returns

Inside R6 class definition: 'object not found' (or: how to define 'local' objects in R6 classes)

I want to define an R6 class that sets up, updates and closes a progress bar. For these 3 tasks, I have 3 functions. The first, setup_progressbar(), calls R's txtProgressbar() which returns an object (say, pb) which needs to be passed on to the second and third functions, update_progressbar() and close_progressbar(). But the object pb is not found by the latter two functions.
library(R6)
myprogressbar <- R6Class("my_progress_bar",
public = list(
n = numeric(1),
initialize = function(n) {
stopifnot(n >= 1)
self$n <- n
},
setup_progressbar = function() {
pb <- txtProgressBar(max = self$n)
},
update_progressbar = function(i) {
setTxtProgressBar(pb, i)
},
close_progressbar = function () {
close(pb)
cat("\n")
}
))
mypb <- myprogressbar$new(10)
mypb$setup_progressbar()
mypb$update_progressbar(3) # Error in setTxtProgressBar(pb, i) : object 'pb' not found
I tried to add pb to self in the hope it would be found, but then I obtain "cannot add bindings to a locked environment".
Note: In my actual (non-minimal) example, the i is found/provided/visible, so that's not an additional problem (most likely this is just a problem in the above minimal working example once fixed beyond the 'pb' not found error).
The following works:
library(R6)
myprogressbar <- R6Class("my_progress_bar",
public = list(
n = numeric(1),
pb = NULL, # provide as argument
initialize = function(n, pb = NULL) { # provide with default so that $new() doesn't require 'pb'
stopifnot(n >= 1)
self$n <- n
},
setup_progressbar = function() {
self$pb <- txtProgressBar(max = self$n)
},
update_progressbar = function(i) {
setTxtProgressBar(self$pb, i)
},
close_progressbar = function () {
close(self$pb)
cat("\n")
}
))
mypb <- myprogressbar$new(10)
mypb$setup_progressbar()
mypb$update_progressbar(3)

After add new code, things cannot knit out

I met a wired situation. After add new code The code cannot knit out.
function_name <- function (...)
{
output <- if (output_format == "list") {
evolved.ts
} else if (output_format == "tsibble") {
as.tsibble(evolved.ts)
}
return(output)
}
You could read the arguments with args <- list(...):
function_name <- function (...)
{
args <- list(...)
# Code
output <- if (args$output_format == "list") {
evolved.ts
} else if (output_format == "tsibble") {
as.tsibble(evolved.ts)
}
return(output)
}

R function wrapper than maintains function signature

I am trying to write a very simple function wrapper in R, that will accept f and return g where g returns zero whenever the first argument is negative. I have the following code
wrapper <- function(f) {
function(x, ...) {
if( x <= 0 ) { 0 }
else { f(x, ...) }
}
}
Thge wrapper works as expected, but is there are way to maintain the function signature
> wdnorm <- wrapper(dnorm)
> args(dnorm)
function (x, mean = 0, sd = 1, log = FALSE)
NULL
> args(wdnorm)
function (x, ...)
NULL
I would like to do something like this (but obviously it doesn't work)
args(g) <- args(f)
is this possible in R?
Here is what you want. Tho, do you really need this?
wrapper <- function(f) {
f2 = function(x) {
if (x <= 0) { 0 }
else { do.call(f, as.list( match.call())[-1]) }
}
formals(f2) = formals(f)
f2
}
wdnorm <- wrapper(dnorm)
args(dnorm)
args(wdnorm)
wdnorm(-5)
wdnorm(5)
output
> args(dnorm)
function (x, mean = 0, sd = 1, log = FALSE)
NULL
> args(wdnorm)
function (x, mean = 0, sd = 1, log = FALSE)
NULL
> wdnorm(-5)
[1] 0
> wdnorm(5)
[1] 1.48672e-06

Output to pdf not working with ReferenceClasses methods in R?

Output to pdf not working with ReferenceClasses methods in R?
This is an example taken from the ReferenceClasses R doc, with some minor
modification:
mEdit = setRefClass("mEdit", fields = list(data="matrix", edits="list"))
mEdit$methods(
edit = function(i, j, value) {
backup = list(i, j, data[i, j])
data[i, j] <<- value
edits <<- c(edits, list(backup))
invisible(value)
}
)
mEdit$methods(
undo = function() {
prev = edits
if(length(prev)) {
prev = prev[[length(prev)]]
}
else {
stop("No more edits to undo!")
}
edit(prev[[1]], prev[[2]], prev[[3]])
length(edits) <<- length(edits) - 2
invisible(prev)
}
)
mEdit$methods(
show = function() {
message("ClassName: ", classLabel(class(.self)))
message("Data:")
methods::show(data)
message("Undo list length: ", length(edits))
}
)
mEdit$methods(
.DollarNames.mEdit = function(x, pattern) {
grep(pattern, getRefClass(class(x))$methods(), value=TRUE)
}
)
x = matrix(1:24, 3, 8)
xx = mEdit(data=x)
xx$edit(2,2,0)
xx$show()
xx$edit(3, 5, 1)
xx$show()
xx$undo()
xx$show()
mv = setRefClass(
"matrixViewer",
fields=c("viewerDevice", "viewerFile"),
contains="mEdit"
)
mv$methods(
.DollarNames.mEdit = function(x, pattern) {
grep(pattern, getRefClass(class(x))$methods(), value=TRUE)
}
)
mv$methods(
view = function() {
## dd = dev.cur();
## dev.set(viewerDevice)
## devAskNewPage(FALSE)
image(
data,
main=paste("After", length(edits), "edits")
)
## dev.set(dd)
}
)
mv$methods(
edit = function(i,j, value) {
callSuper(i,j, value)
view()
}
)
mv$methods(
initialize = function(file="./mv.pdf", ...) {
viewerFile <<- file
## pdf(viewerFile)
## viewerDevice <<- dev.cur()
## dev.set(dev.prev())
callSuper(...)
}
)
mv$methods(
finalize = function() {
dev.off(viewerDevice)
}
)
x = matrix(rnorm(64, 0, 34), 8, 8)
xx = mv(file="/tmp/x.pdf", data=x)
xx$edit(2,2,0)
xx$edit(3, 5, 1)
xx$edit(4, 4, 2.3)
xx$undo()
xx$view()
Note that I have commented out those lines concerning switch
of output devices, so it uses the default device all through,
otherwise when the view method
is called, the plot is not written to the pdf file at all.
Any idea why this is happening?
Call rm on xx and then call garbage collection. finalize will then be called which will invoke dev.off and the pdf will be written. This assumes everything is uncommented.
rm(xx)
gc()
Also your .DollarNames should be
.DollarNames.mEdit = function(x, pattern) {
grep(pattern, getRefClass(class(x))$methods(), value=TRUE)
}
.DollarNames.matrixViewer = function(x, pattern) {
grep(pattern, getRefClass(class(x))$methods(), value=TRUE)
}
and are not methods of the Reference class. They are external functions seperate to the Reference classes.
So the main takeaway here is that finalize is not called until the object is garbage collected.

Resources