[R] avoid <<- in specific case

Duncan Murdoch murdoch.duncan at gmail.com
Fri Oct 5 16:11:29 CEST 2012


On 05/10/2012 9:38 AM, Frans Marcelissen wrote:
> I agree with this. But there is (in my opinion) a much more dangerous point:
> a<b
> If  there is an object  called b in the function, it uses this b. But if you
> forgot to inialise b in the function, it looks in the global environment. So
> the following happens:
> b<<-100
> a<-b (if there is no b in the function, it uses b in the global environment.
> So a=100
> b<9 (writes to b in the local environment)
> Now b in the global environment is 100, while b in the function is 9
> It would be more logical if a<-b would give an error if b does not exist in
> the function (just like pascal does).

If functions didn't have access to objects outside the local frame, they 
couldn't do much of anything at all.  Unlike Pascal, functions in R are 
first class objects.  Even "<-" is an object (found in the base 
package).  So functions need to be able to look outside themselves to 
find the thinks like mean(), var(), "+", "<-", etc.

Duncan Murdoch

> -------------------
> Frans
>
> -----Oorspronkelijk bericht-----
> Van: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org]
> Namens Duncan Murdoch
> Verzonden: vrijdag 5 oktober 2012 14:26
> Aan: Berry Boessenkool
> CC: R Help
> Onderwerp: Re: [R] avoid <<- in specific case
>
> On 05/10/2012 8:19 AM, Berry Boessenkool wrote:
> >
> > Hi all,
> >
> > I improved a function drawing horizontal histograms (code below) which
> uses barplot and works fine.
> > It does,however, need to assign a function to the global environment to
> later find the actual location on the vertical axis, and not the number of
> bars used by barplot.
> > Hopefully, running the examples below will illustrate that.
> >
> > As said, it works perfectly fine and does exactly what I want.
> > The problem arises now that I'm building a package (just for myself,
> > for now) and run into R CMD check telling me 'no visible binding for '<<-'
> assignment'.
> > (wording below)
> > Similar problem as in
> > http://r.789695.n4.nabble.com/R-CMD-check-tells-me-no-visible-binding-
> > for-global-variable-what-does-it-mean-td1837236.html
> >
> > My question is:
> > Is there a way to avoid assigning the function to the global environment
> with <<- but still have it available? I know it is generally not good
> practice.
>
> You can return the function as the value of your function.   A bonus:
> if it is created within the body of your function, it will have access to
> all the local variables there.
>
> You shouldn't write to the global environment, because globalenv belongs to
> the user, not to you.  If the user wants your function in the global
> environment s/he can just assign the value of your function to a variable
> there.
>
> Duncan Murdoch
>
>
> > Or ist it OK in a case like this, and is there a way to avoid the notes
> from the rcmd check (make the function package-compatible)?
> > Or should I just ignore these notes? (I'm completely new to building
> > packages and cannot judge the importance yet.)
> >
> > I'd be very thankful for any hints!
> >
> > Berry
> >
> > PS: I recently read about barcharts in lattice, but by now I'm already
> used to my function. (And I learned a lot writing it a couple of years ago).
> >
> >
> > # Function
> > horiz.hist <- function(Data, breaks="Sturges", col="transparent",
> > las=1, ylim=range(HBreaks), labelat=pretty(ylim), labels=labelat,
> border=par("fg"), ... )
> >    {a <- hist(Data, plot=FALSE, breaks=breaks)
> >    HBreaks <- a$breaks
> >    HBreak1 <- a$breaks[1]
> >    hpos <<- function(Pos) (Pos-HBreak1)*(length(HBreaks)-1)/
> diff(range(HBreaks)) # Assign a function to the global environment with
> values calculated inside the main function.
> >    barplot(a$counts, space=0, horiz=T, ylim=hpos(ylim), col=col,
> border=border,...)
> >    axis(2, at=hpos(labelat), labels=labels, las=las, ...)
> >    print("use hpos() to address y-coordinates") }
> >
> > # Data and basic concept
> > set.seed(8); ExampleData <- rnorm(50,8,5)+5
> > hist(ExampleData)
> > horiz.hist(ExampleData, xlab="absolute frequency") # Caution: the
> > labels at the y-axis are not the real coordinates!
> > # abline(h=2) will draw above the second bar, not at the label value 2.
> Use hpos:
> > abline(h=hpos(11), col=2)
> >
> > # Further arguments
> > horiz.hist(ExampleData, xlim=c(-8,20)) horiz.hist(ExampleData,
> > main="the ... argument worked!", col.axis=3) hist(ExampleData,
> > xlim=c(-10,40)) # with xlim horiz.hist(ExampleData, ylim=c(-10,40),
> > border="red") # with ylim horiz.hist(ExampleData, breaks=20,
> > col="orange") axis(2, hpos(0:10), labels=F, col=2) # another use of
> > hpos()
> >
> > # One shortcoming: doesn't work with breakpoints provided as a vector
> > with different widths of the bars
> >
> >
> > Wording from the rcmd check when building a package:
> > * checking R code for possible problems ... NOTE
> > horiz.hist: no visible binding for '<<-' assignment to 'hpos'
> > horiz.hist: no visible global function definition for 'hpos'
> >
> >
> >   		 	   		
> > 	[[alternative HTML version deleted]]
> >
> > ______________________________________________
> > R-help at r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide
> > http://www.R-project.org/posting-guide.html
> > and provide commented, minimal, self-contained, reproducible code.
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>




More information about the R-help mailing list