What is the reason to add quotation marks around R function names? - r

What is the difference between defining a function called myfunction as
"myfunction" <- function(<arguments>){<body>}
and
myfunction <- function(<arguments>){<body>}
furthermore: what about the comments which are usually placed around such a function, i.e.
#myfunction{{{
"myfunction" <- function(<arguments>){<body>}
#}}}
are they just for documentation or are they really necessary (if so for what)?
EDIT: I have been asked for an example where comments like
#myfunction{{{
are used: For example here https://github.com/cran/quantmod/blob/master/R/getSymbols.R

The quoted version allows otherwise illegal function names:
> "my function" <- function() NULL
> "my function"()
NULL
Note that most people use backticks to make it clear they are referring to a name rather than a character string. This allows you to do some really odd things as alluded to in ?assign:
> a <- 1:3
> "a[1]" <- 55
> a[1]
[1] 1
> "a[1]"
[1] "a[1]"
> `a[1]`
[1] 55

Related

Registered Trademark printing extra character

I have some weird variables imported from SAS with unicode values for a superscript registered trademark ® and used gsub to try to make the variable print a registered trademark in R. I made some dummy data below just to show what I did. For some reason it is printing an extra  symbol. Does anyone know why this might be happening?
var1<-factor(c("prod1^{unicode 00AE}","prod2^{unicode 00AE}"))
var2<-as.factor(sapply(var1,gsub,pattern="\\{unicode 00AE\\}",replacement="\u00AE"))
> var2
[1] prod1^® prod2^®
Levels: prod1^® prod2^®
Not sure whats happening with gsub; but str_replace_all provided by stringr is able to provide the required output:
> var1<-factor(c("prod1^{unicode 00AE}","prod2^{unicode 00AE}"))
> var2<-as.factor(sapply(var1,str_replace_all,pattern="\\{unicode 00AE\\}",replacement="\U00AE"))
> var2
[1] prod1^® prod2^®
Levels: prod1^® prod2^®
The error comes from the fact that gsub does not handle \uXXXX notation in the replacement properly, even when fixed=TRUE is used. You actually need to set the result to UTF8 "manually". Look, this will work:
> res <- gsub("{unicode 00AE}", "\u00AE", x, fixed=TRUE)
> res
[1] "prod1^®"
> Encoding(res) <- "UTF-8"
> res
[1] "prod1^®"
In your case, you may just use the replacement="®" and it will display the result correctly:
> var2<-as.factor(sapply(var1,gsub,pattern="{unicode 00AE}",replacement="®", fixed=TRUE))
> var2
[1] prod1^® prod2^®
Levels: prod1^® prod2^®

How can I turn a list of expressions to an expression list

Suppose a function like this:
fun <- function(...) {
dots <- eval(substitute(alist(...)))
# ...
}
... is supposed to be a few expressions that should be evaluated in some other environments in the function. For example, fun(name,age) will result in a ACTUAL list of name objects like:
[[1]]
name
[[2]]
age
However, I want to evaluate an expression (in some environment) like this: list(name,age) which is an EXPRESSION rather than ACTUAL list that include the user-defined arguments.
How can I make that transformation?
I'm not totally clear what you want evaluated where, but if you replace alist with list:
fun <- function(..., e) {
dots <- eval(substitute(list(...)),envir=e)
dots
}
and set:
e=new.env() ; e$name="Fred"; e$age=99
and then:
fun(name,age,age*2,e=e)
[[1]]
[1] "Fred"
[[2]]
[1] 99
[[3]]
[1] 198
which seems to qualify as "evaluate an expression (in some environment) like this: list(name,age)", since, at top level, evaluating list(name,age) is simply this, right:
> name="Joe"
> age=123
> list(name,age)
[[1]]
[1] "Joe"
[[2]]
[1] 123
As always, it is somewhat unclear exactly what you want, But I think
fun <- function(...) {
dots <- eval(substitute(alist(...)))
as.call(c(list(quote(list)),dots))
}
get's the result you want. Here we take the expressions passed in via dots, and use them as parameters to a call to the list() function. This means that
ex <- fun(name, age, gender)
ex
# list(name, age)
class(ex)
# [1] "call"
And really, an expression is just a collection of calls so I'd assume a call would work for you, but if you really wanted an expression, you could use as.expression(ex).

R get objects' names from the list of objects

I try to get an object's name from the list containing this object. I searched through similar questions and find some suggestions about using the deparse(substitute(object)) formula:
> my.list <- list(model.product, model.i, model.add)
> lapply(my.list, function(model) deparse(substitute(model)))
and the result is:
[[1]]
[1] "X[[1L]]"
[[2]]
[1] "X[[2L]]"
[[3]]
[1] "X[[3L]]"
whereas I want to obtain:
[1] "model.product", "model.i", "model.add"
Thank you in advance for being of some help!
You can write your own list() function so it behaves like data.frame(), i.e., uses the un-evaluated arg names as entry names:
List <- function(...) {
names <- as.list(substitute(list(...)))[-1L]
setNames(list(...), names)
}
my.list <- List(model.product, model.i, model.add)
Then you can just access the names via:
names(my.list)
names(my.list) #..............
Oh wait, you didn't actually create names did you? There is actually no "memory" for the list function. It returns a list with the values of its arguments but not from whence they came, unless you add names to the pairlist given as the argument.
You won't be able to extract the information that way once you've created my.list.
The underlying way R works is that expressions are not evaluated until they're needed; using deparse(substitute()) will only work before the expression has been evaluated. So:
deparse(substitute(list(model.product, model.i, model.add)))
should work, while yours doesn't.
To save stuffing around, you could employ mget to collect your free-floating variables into a list with the names included:
one <- two <- three <- 1
result <- mget(c("one","two","three"))
result
#$one
#[1] 1
#
#$two
#[1] 1
#
#$three
#[1] 1
Then you can follow #DWin's suggestion:
names(result)
#[1] "one" "two" "three"

subset() drops attributes on vectors; how to maintain/persist them?

Let's say I have a vector where I've set a few attributes:
vec <- sample(50:100,1000, replace=TRUE)
attr(vec, "someattr") <- "Hello World"
When I subset the vector, the attributes are dropped. For example:
tmp.vec <- vec[which(vec > 80)]
attributes(tmp.vec) # Now NULL
Is there a way to, subset and persist attributes without having to save them to another temporary object?
Bonus: Where would one find documentation of this behaviour?
I would write a method for [ or subset() (depending on how you are subsetting) and arrange for that to preserve the attributes. That would need a "class" attribute also adding to your vector so that dispatch occurs.
vec <- 1:10
attr(vec, "someattr") <- "Hello World"
class(vec) <- "foo"
At this point, subsetting removes attributes:
> vec[1:5]
[1] 1 2 3 4 5
If we add a method [.foo we can preserve the attributes:
`[.foo` <- function(x, i, ...) {
attrs <- attributes(x)
out <- unclass(x)
out <- out[i]
attributes(out) <- attrs
out
}
Now the desired behaviour is preserved
> vec[1:5]
[1] 1 2 3 4 5
attr(,"someattr")
[1] "Hello World"
attr(,"class")
[1] "foo"
And the answer to the bonus question:
From ?"[" in the details section:
Subsetting (except by an empty index) will drop all attributes except names, dim and dimnames.
Thanks to a similar answer to my question #G. Grothendieck, you can use collapse::fsubset see here.
library(collapse)
#tmp_vec <- fsubset(vec, vec > 80)
tmp_vec <- sbt(vec, vec > 80) # Shortcut for fsubset
attributes(tmp_vec)
# $someattr
# [1] "Hello World"

R's behaviour using ifelse and eval in combination

disclaimer: this code is bad practice., and only works due to something bug-like. Never use it in a real situation. This question is about the interesting behaviour of R, nothing else than that.
After reading this question I got pretty puzzled. Apparently, ifelse can access information that should be hidden.
Say we do :
> x <- expression(dd <- 1:3)
> y <- expression(dd <- 4:6)
> z <- c(1,0)
> eval(x)
> eval(y)
>
We get no output. Logic, as both expressions are actually assignments of a vector dd. eval() is not supposed to give output then. But strangely enough, when you try the funny code
> ifelse(z==0,eval(x),eval(y))
[1] 4 2
You get output??? Somebody has an explanation for this?
It's not as simple as "R evaluates and then uses dd". Whatever order you give z, whatever condition you use, dd is always the last mentioned eval().
> ifelse(z==0,eval(x),eval(y))
> dd
[1] 4 5 6
> ifelse(z==1,eval(x),eval(y))
> dd
[1] 4 5 6
> z <- c(0,1)
> ifelse(z==0,eval(x),eval(y))
> dd
[1] 4 5 6
> ifelse(z==1,eval(x),eval(y))
> dd
[1] 4 5 6
> ifelse(z==1,eval(y),eval(x))
> dd
[1] 1 2 3
EDIT:
a closer look at the source code of ifelse shows that the line making sure this happens, is the rep() :
> x <- expression(dd <- 1:3)
> eval(x)
> rep(eval(x),2)
[1] 1 2 3 1 2 3
Still, it doesn't solve the question...
This is not a bug
The 'output' onto the console of the result of a command is conditional. This can be determined by the function itself - for example:
> f=function(x)x;
> g=function(x)invisible(x);
> f(1)
[1] 1
> g(2)
> .Last.value
[1] 2
The value is still being returned just fine - it's just not printed on the console.
What's happening here is the eval marks its output invisible but rep and ifelse do not, and in fact effectively strip the invisible property off their input.
It appears the invisible is a special property of the variable, and is not passed through the rep operation. It's also not passed through assignment:
> h=function(x){y=x;y;}
> f(g(1))
> h(g(1))
[1] 1
>
See ?invisible for a little more background.
R always evaluates the two alternatives to an ifelse command. You can rationalize that as being necessary in order to be ready to choose which item in each vector to return to the calling environment. The opposite is true of an if (cond) {affirm-conseq} else {neg-conseq}. The basis of "dd" always getting set based on evaluation of the third ifelse argument is revealed when on looks at the code for ifelse. The "no"-vector code gets evaluated after the "yes"-vector in order to choose which items in negative consequent vector get assigned to the "ans"-output vector.

Resources