R-alpha: buglet in return(invisible()) [R 0.50 and 0.60]

Luke Tierney luke@stat.umn.edu
Thu, 30 Oct 1997 08:52:54 -0600 (CST)


Martin Maechler wrote:
> 
> Evaluate the following example to get the behavior :
> 
> 		--- anybody: patch ? ---
> 
> 
> tst.i <- function(x)
> {
>   if(missing(x))
>     return(invisible())
>   else if(!is.numeric(x)) stop("x must be numeric")
>   ## else
>   invisible((x+3)^2)
> }
> 
> tst.i()#-- should NOT print anything !!
> print(mode(tst.i()))#--gives "NULL"   both in S-plus 3.4 and R 0.60
> 
> tst.i(1)# nothing (ok in R and S-plus)
> 1 + tst.i(1) #> 17

I'm still running 0.49 and there the behavior is a bit different (if I
understand your description right):

tst.i <- function(x=0)
 {
   if(missing(x))
     return(invisible())
   else if(!is.numeric(x)) stop("x must be numeric")
   ## else
   invisible((x+3)^2)
}

gives
> tst.i()
>         # in current R this is NULL?

In any case, here are a few random remarks on this.  Both invisible
and return are somewhat peculiar entities in Splus at least.  In Splus
the official semantics of invisible are (from help)

       the function invisible reaches back 2 frames  and  sets  a
       special  flag, .Auto.print, to FALSE.  This has the effect
       of preventing automatic printing if the  function  calling
       invisible  was called from the top level since .Auto.print
       in frame 1 is set to FALSE.

which means that the argument is pretty much irrelevant;

	function() { invisible(); 1 }
and
	function() { invisible(1) }

are equivalent. I'm not sure what the official semantics of invisible
are in R; operationally these two act differently in 0.49.

Return in Splus is a keyword and doesn't have a function definition,
so it isn't quite clear how return(invisible()) should behave. In R
return seems to be just another function whose action happens to be to
execute a return from one frame back (or whatever). That means that I
would expect

	function(x) { return(invisible(x)) }
and
	function(x) { g(invisible(x)) }

with g<-function(x) { x } to produce identical results as far as
invisibility is concerned, and they do.

I think many users think that invisible() can be thought of as
attaching an invisibility property to its argument and that that
property ought to remain with the argument for a while at least
(probably an assignment should strip it?) -- this would lead to

	return(invisible())

acting as you suggest (and maybe it currently does if I misunderstood
what is happening). It would also mean that

	myprint<- function(...) { print(...) }

would act as you might expect; right now it does in R (and since I'm
not sure about the offical semantics I'm not sure if this should
suprprise me or not) but in Splus (in accord with the semantics given
above) it does not -- you get

>  myprint(1)
[1] 1
[1] 1
>

Officially adding such a property (if it sin't already there -- I'm
not sure on this) might make some things cleaner, but it's not clear
what other cans of worms this would open up.

Other languages take a different approach -- they allow a function
used for side effects to return no values, so there is nothing to
print -- this covers most though not all cases where invisible() is
used now.


-- 
Luke Tierney
University of Minnesota                      Phone:           612-625-7843
School of Statistics                         Fax:             612-624-8868
206 Church Street                            email:      luke@stat.umn.edu
Minneapolis, MN 55455 USA                    WWW:  http://www.stat.umn.edu
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=