R Function - Print When Not Assigned - r

I see there is another related question, but the answer isnt what I am looking for. I want a function that can be assigned to an object, but still will print the output even when assigned, but not double print it.
In this case:
fun <- function(x) {
print(x+1)
x+1
}
a <- fun(3)
In this case, it would both save to a, and it would print to console, which is what I want.
But in this case:
fun(3)
It would print to the console twice. Is there a way to get the desired result from case 1, without double printing on case 2?

Assuming that you still want your function to return the 'x+1' value, you could just wrap it in the invisible function:
fun <- function(x) {
print(x+1)
invisible(x+1)
}
> fun(3)
[1] 4
> a = fun(3)
[1] 4
> a
[1] 4
This will only print it out once, while still retaining the 'x+1' value.

You can accomplish this same behavior with any function in R that visibly returns an object by wrapping it in parentheses.
fun <- function(x) {
x+1
}
> (fun(3))
[1] 4
> (a = fun(3))
[1] 4
> a
[1] 4
Or, equivalently, you may simply call print on your assignment.
> print(fun(3))
[1] 4
I'm not sure rolling this functionality into a function has any benefits over using the existing print method outside of a function.

R functions shouldn't have unasked for "side effects". This isn't a rule, but a strong recommendation. As evidence for it being good practice, there are plenty of questions on SO like this one where a poorly behaved function prints output using print or cat that the end user struggles to disable.
Based on this, I would strongly encourage you to either use message() rather than print() or to add an argument that can disable the printing. message() is the "right" way print to the console during execution, but it won't format the result nicely depending on the data structure.
Thus, if your function expects simple outputs then I would recommend doing it like this:
fun <- function(x) {
result = x + 1
message(result)
invisible(result)
}
If it might have more complicated output, you could try something like this (demoing on mtcars):
fun <- function(x) {
result = head(mtcars)
sapply(capture.output(print(result)), message)
invisible(result)
}
Messages can easily be suppressed by wrapping the call in suppressMessages(), and message = F is a handy argument for knitr code chunks to say "ignore the messages".
The other option is to add an argument
fun <- function(x, quietly = FALSE) {
result = x + 1
if (!quietly) print(result)
invisible(result)
}
And I'd also think long and hard about whether this strange behavior is really necessary. Usually, having functions that behave as expected is better than having special cases that throw expectations.

Related

How to print an argument of a function when it fails?

I'm trying to use possibly() to print the argument x as a message when the function sum() fails.
library(purrr)
t <- function(x) {
p <- possibly(sum, otherwise = message(x))
p(x)
}
However, I would not expect the below to retrieve any message, since sum() doesn't fail:
> t(1)
1
[1] 1
Instead, the script below works as expected: sum() fails, thus t() prints the message 'a'
> t('a')
a
NULL
As noted in the other answer, possibly simply does something quite different from what you want.
What you want is tryCatch (part of base R):
t <- function(x) {
tryCatch(sum(x), error = function (.) message(x))
}
t(1)
# [1] 1
t('a')
# a
The argument otherwise of the function purrr::possibly is a value but message(x) is an R expression. According to the documentation:
These functions wrap functions so that instead of generating side effects through printed output, messages, warnings, and errors, they return enhanced output.

What's the meaning of the (x) in the following passage?

During my free time R studying, I read this article on usage of return(). In there, I came across a function, of which one element's meaning escapes my technical background, please see below:
bench_nor2 <- function(x,repeats) { system.time(rep(
# without explicit return
(function(x)vector(length=x,mode="numeric"))(x),repeats)) }
I've played with the codes of the article, but the logic behind this tiny (x) (specifically, it's 2nd occurrence) in the 3rd line is unclear to me.
It's an anonymous function. If we unwrap the code
bench_nor2 <- function(x,repeats) { system.time(rep(
# without explicit return
(function(x)
vector(length=x,mode="numeric")
)(x),
repeats)) }
we can see that within the rep( ... ) call, the first argument is
(function(x)vector(length=x,mode="numeric"))(x)
Now, this is a curious way of putting it. But what you get is that function(x) vector(...) defines a one-liner function (which calls vector to create a numeric vector of length x). Wrapped in parenthesis (function(x) ...) returns the function, and then with (function(x) ...)(x) calls the anonymous function with argument x.
You would get the same result from:
my_vector <- function(y) vector(length=y, mode="numeric")
bench_nor2 <- function(x, repeats) {system.time(rep(my_vector(x), repeats))}

How do I continue running the function when errors happen? [duplicate]

I have an example function below that reads in a date as a string and returns it as a date object. If it reads a string that it cannot convert to a date, it returns an error.
testFunction <- function (date_in) {
return(as.Date(date_in))
}
testFunction("2010-04-06") # this works fine
testFunction("foo") # this returns an error
Now, I want to use lapply and apply this function over a list of dates:
dates1 = c("2010-04-06", "2010-04-07", "2010-04-08")
lapply(dates1, testFunction) # this works fine
But if I want to apply the function over a list when one string in the middle of two good dates returns an error, what is the best way to deal with this?
dates2 = c("2010-04-06", "foo", "2010-04-08")
lapply(dates2, testFunction)
I presume that I want a try catch in there, but is there a way to catch the error for the "foo" string whilst asking lapply to continue and read the third date?
Use a tryCatch expression around the function that can throw the error message:
testFunction <- function (date_in) {
return(tryCatch(as.Date(date_in), error=function(e) NULL))
}
The nice thing about the tryCatch function is that you can decide what to do in the case of an error (in this case, return NULL).
> lapply(dates2, testFunction)
[[1]]
[1] "2010-04-06"
[[2]]
NULL
[[3]]
[1] "2010-04-08"
One could try to keep it simple rather than to make it complicated:
Use the vectorised date parsing
R> as.Date( c("2010-04-06", "foo", "2010-04-08") )
[1] "2010-04-06" NA "2010-04-08"
You can trivially wrap na.omit() or whatever around it. Or find the index of NAs and extract accordingly from the initial vector, or use the complement of the NAs to find the parsed dates, or, or, or. It is all here already.
You can make your testFunction() do something. Use the test there -- if the returned (parsed) date is NA, do something.
Add a tryCatch() block or a try() to your date parsing.
The whole things is a little odd as you go from a one-type data structure (vector of chars) to something else, but you can't easily mix types unless you keep them in a list type. So maybe you need to rethink this.
You can also accomplish this kind of task with the purrr helper functions map and possibly. For example
library(purrr)
map(dates2, possibly(testFunction, NA))
Here possibly will return NA (or whatever value you specified if an error occurs.
Assuming the testFunction() is not trivial and/or that one cannot alter it, it can be wrapped in a function of your own, with a tryCatch() block. For example:
> FaultTolerantTestFunction <- function(date_in) {
+ tryCatch({ret <- testFunction(date_in);}, error = function(e) {ret <<- NA});
+ ret
+ }
> FaultTolerantTestFunction('bozo')
[1] NA
> FaultTolerantTestFunction('2010-03-21')
[1] "2010-03-21"

Stop function evaluation using another function in R

I did a test with nested return function in R, but without success. I came from Mathematica, where this code works well. Here is a toy code:
fstop <- function(x){
if(x>0) return(return("Positive Number"))
}
f <- function(x){
fstop(x)
"Negative or Zero Number"
}
If I evaluate f(1), I get:
[1] "Negative or Zero Number"
When I expected just:
[1] "Positive Number"
The question is: there is some non-standard evaluation I can do in fstop, so I can have just fstop result, without change f function?
PS: I know I can put the if direct inside f, but in my real case the structure is not so simple, and this structure would make my code simpler.
Going to stick my neck out and say...
No.
Making a function return not to its caller but to its caller's caller would involve changing its execution context. This is how things like return and other control-flow things are implemented in the source. See:
https://github.com/wch/r-source/blob/trunk/src/main/context.c
Now, I don't think R level code has access to execution contexts like this. Maybe you could write some C level code that could do it, but its not clear. You could always write a do_return_return function in the style of do_return in eval.c and build a custom version of R... Its not worth it.
So the answer is most likely "no".
I think Spacedman is right, but if you're willing to evaluate your expressions in a wrapper, then it is possible by leveraging the tryCatch mechanism to break out of the evaluation stack.
First, we need to define a special RETURN function:
RETURN <- function(x) {
cond <- simpleCondition("") # dummy message required
class(cond) <- c("specialReturn", class(cond))
attr(cond, "value") <- x
signalCondition(cond)
}
Then we re-write your functions to use our new RETURN:
f <- function(x) {
fstop(x)
"Negative or Zero"
}
fstop <- function(x) if(x > 0) RETURN("Positive Number") # Note `RETURN` not `return`
Finally, we need the wrapper function (wsr here stands for "with special return") to evaluate our expressions:
wsr <- function(x) {
tryCatch(
eval(substitute(x), envir=parent.frame()),
specialReturn=function(e) attr(e, "value")
) }
Then:
wsr(f(-5))
# [1] "Negative or Zero"
wsr(f(5))
# [1] "Positive Number"
Obviously this is a little hacky, but in day to day use would be not much different than evaluating expressions in with or calling code with source. One shortcoming is this will always return to the level you call wsr from.

How to retrieve formals of a primitive function?

For the moment, at least, this is an exercise in learning for me, so the actual functions or their complexity is not the issue. Suppose I write a function whose argument list includes some input variables and a function name, passed as a string. This function then calculates some variables internally and "decides" how to feed them to the function name I've passed in.
For nonprimitive functions, I can do (for this example, assume non of my funcname functions have any arguments other than at most (x,y,z). If they did, I'd have to write some code to search for matching names(formals(get(funcname))) so as not to delete the other arguments):
foo <- function (a,b,funcname) {
x <- 2*a
y <- a+3*b
z <- -b
formals(get(funcname)) <- list(x=x, y=y, z=z)
bar <- get(funcname)()
return(bar)
}
And the nice thing is, even if the function funcname will execute without error even if it doesn't use x, y or z (so long as there are no other args that don't have defaults) .
The problem with "primitive" functions is I don't know any way to find or modify their formals. Other than writing a wrapper, e.g. foosin <-function(x) sin(x), is there a way to set up my foo function to work with both primitive and nonprimitive function names as input arguments?
formals(args(FUN)) can be used to get the formals of a primitive function.
You could add an if statement to your existing function.
> formals(sum)
# NULL
> foo2 <- function(x) {
if(is.primitive(x)) formals(args(x)) else formals(x)
## formals(if(is.primitive(x)) args(x) else x) is another option
}
> foo2(sum)
# $...
#
#
# $na.rm
# [1] FALSE
#
> foo2(with)
# $data
#
#
# $expr
#
#
# $...
Building on Richard S' response, I ended up doing the following. Posted just in case anyone else ever tries do things as weird as I do.
EDIT: I think more type-checking needs to be done. It's possible that coleqn could be
the name of an object, in which case get(coleqn) will return some data. Probably I need
to add a if(is.function(rab)) right after the if(!is.null(rab)). (Of course, given that I wrote the function for my own needs, if I was stupid enough to pass an object, I deserve what I get :-) ).
# "coleqn" is the input argument, which is a string that could be either a function
# name or an expression.
rab<-tryCatch(get(coleqn),error=function(x) {} )
#oops, rab can easily be neither NULL nor a closure. Damn.
if(!is.null(rab)) {
# I believe this means it must be a function
# thanks to Richard Scriven of SO for this fix to handle primitives
# we are not allowed to redefine primitive's formals.
qq <- list(x=x,y=y,z=z)
# matchup the actual formals names
# by building a list of valid arguments to pass to do.call
argk<-NULL
argnames<-names(formals(args(coleqn)))
for(j in 1:length(argnames) )
argk[j]<-which(names(qq)==argnames[1] )
arglist<-list()
for(j in 1:length(qq) )
if(!is.na(argk[j])) arglist[[names(qq)[j]]]<-qq[[j]]
colvar<- do.call(coleqn,arglist)
} else {
# the input is just an expression (string), not a function
colvar <- eval(parse(text=coleqn))
}
The result is an object generated either by the expression or the function just created, using variables internal to the main function (which is not shown in this snippet)

Resources