What Does the Function Invisible() Do

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



Leave a reply



Submit