What does the function invisible() do?
From ?invisible
:
Details:
This function can be useful when it is desired to have functions
return values which can be assigned, but which do not print when
they are not assigned.
So you can assign the result, but it will not be printed if not assigned. It's often used in place of return
. Your print.myPrint
method only prints because you explicitly call print
. The call to invisible(x)
at the end of your function simply returns a copy of x
.
If you didn't use invisible
, x
would also be printed if not assigned. For example:
R> print.myPrint <- function(x, ...){
+ print(unlist(x[1:2]))
+ return(x)
+ }
R> print(x)
v11 v12 v13 v14 v15 v21 v22 v23 v24 v25
1 2 3 4 5 -1 -2 -3 -4 -5
v11 v12 v13 v14 v15 v21 v22 v23 v24 v25
1 2 3 4 5 -1 -2 -3 -4 -5
The Invisibility of the NULL value that is returned by a loop
All functions must return something. invisible
means the return value isn't visible to the user. Consider the simple function below:
f <- function(){
x <- 2
return( x )
}
# Returns 2..
> f()
[1] 2
# Returns 2 but you can't see it
f <- function(){
x <- 2
return( invisible(x) )
}
> f()
>
# But it is still returned...
str(f())
#num 2
You can see the return value of a for
loop like so for example...
str( for( i in 1:3 ){} )
# NULL
Even invisible
itself must return something...
str( invisible() )
# NULL
Return invisible and visible output in R
I think the easiest solution is just to create an S3 print method and add a class tag to the list
create_list = function(a, b) {
l = list(a=a, b=b)
class(l) = "mylist"
l
}
Then create a corresponding print
method that only prints out the second element:
print.mylist = function(x, ...){
x = x["b"]
NextMethod()
}
and that's it:
R> (l = create_list(1:4, 5:10))
$b
[1] 5 6 7 8 9 10
R> str(l)
List of 2
$ a: int [1:4] 1 2 3 4
$ b: int [1:6] 5 6 7 8 9 10
- attr(*, "class")= chr "mylist"
how to output a list with invisible items R while showing only part of the list
All you have to do is define a new class and the corresponding print
method. Something like the following, where I define a class Onyambu
.
set.seed(736) # make the code reproducible
x <- structure(list(
A = sample(0:1, 20, TRUE),
B = sample(letters[1:5], 20, TRUE),
M = 1:5,
N = 6:10,
X = rnorm(10),
Y = rexp(12)
),
class = "Onyambu" # This is the new class
)
# Before the print method for class "Onyambu" is defined
# it prints like a normal list
x
print.Onyambu <- function(x){
cat("Sum: ", sum(x[[1]]), "Mean: ", mean(x[[1]]), "\n")
print(table(x[[2]]))
invisible(x)
}
# After print.Onyambu is defined, it prints like we want it to
x
#Sum: 13 Mean: 0.65
#
#a b c d e
#3 3 6 5 3
is it possible to have an invisible function in R?
It should be possible to use a local environment / closure to do this. The following code uses a scoping assignment to expose f.
local({
g <- function (x) x * x; # "secret" algorithm!
f <<- function (x) g(x);
})
# g is not in scope here, although it is still bound in f's closure
f(4) # => 16
The result of print(f)
only covers f itself only, and not the "secret" in g:
function (x) g(x)
This naturally won't hide the original file source or textual content itself.
As I don't actually use R, I've no idea if the environment can be reflected1 to still expose g (and at some level it must be possible as a .rda file can be generated). However, this approach appears to fulfill the original requirement of not immediately exposing the algorithm.
1As @HongOoi points out, the reflected environment (and g) can be accessed with environment(f)$g
, which once again would expose the "secret".
R: I have a function with an invisible return value, how can I vectorize it and not get a huge null output?
This happens as you are invoking a side effect within bar() and then jumping up to the top level. The function bar() completes the side effect (printing) then returns the last value in the final command to the top level.
This arrangement returns a single NULL regardless of the sizes of a and b. As in...
a <- matrix(1:9,nrow=3,ncol=3)
b <- matrix(1:9,nrow=3,ncol=3,byrow=TRUE)
foo <- function(a,b) {
exists("a")
exists("b")
}
bar <- function(a,b) {
if(foo(a,b)) {print(c(a,b))}
NULL # or equivalently: return()
}
x <- bar(a,b) # x will be a single NULL
Alternatively, you could simply do whatever it is in bar() that you want done, return a and b appropriately and then print outside the function using the returned values. In most cases, this would likely be a better idea. Also the "<<-" operator can be used helpfully here, though global vars have their own issues apart from the side effect here.
Related Topics
Difference Between R-Base and R-Recommended Packages
R Tm Package Vcorpus: Error in Converting Corpus to Data Frame
Combining S4 and S3 Methods in a Single Function
How to Generalize Outer to N Dimensions
Dt[!(X == .)] and Dt[X != .] Treat Na in X Inconsistently
R V3.4.0-2 Unable to Find Libgfortran.So.3 on Arch
How to Add a Table to a Ggplot
What Does the R Function 'Poly' Really Do
R for Loop Skip to Next Iteration Ifelse
Horizontal Dendrogram in R with Labels
Annotate Ggplot with an Extra Tick and Label
Unicode with Knitr and Rmarkdown
Shiny Leaflet Ploygon Click Event
Accurately Converting from Character->Posixct->Character with Sub Millisecond Datetimes
Error with Select Function from Dplyr