The documentation for assignment says:
In all the assignment operator expressions, 'x' can be a name or
an expression defining a part of an object to be replaced (e.g.,
'z[[1]]'). A syntactic name does not need to be quoted, though it
can be (preferably by backticks).
But the implementation allows assignment to a character string (i.e. not a
name), which it coerces to a name:
"foo" <- 23; foo
# returns 23
> is.name("foo")
[1] FALSE
Is this a documentation error or an implementation error?
The coercion is not happening at parse time:
class(quote("foo"<-3)[[2]])
[1] "character"
In fact, bizarrely, not only does it coerce to a name, it actually
*modifies* the parse tree:
> gg <- quote("hij" <- 4)
> gg
"hij" <- 4
> eval(gg)
> gg
hij <- 4
*** The cases below only come up with expression trees generated
programmatically as far as I know, so are much more marginal cases. ***
The <- operator even allows the left-hand-side to be of length > 1, though
it just ignores the other elements, with the same side effect as before:
> gg <- quote(x<-44)
> gg[[2]] <- c("x","y")
> gg
c("x", "y") <- 44
> eval(gg)
> x
[1] 44
> y
Error: object "y" not found
> gg
x <- 44
None of this is documented in ? <-, and it is rather a surprise that
evaluating an expression tree can modify it. I admit we had a feature
(performance hack) like this in MacLisp years ago, where expanded syntax
macros replaced the source code of the macro, but it was a documented,
general, and optional part of the macro mechanism.
Another little glitch:
gg <- quote(x<-44); gg[[2]] <- character(0); eval(gg)
Error in eval(expr, envir, enclos) :
'getEncChar' must be called on a CHARSXP
This looks like an internal error that users shouldn't see.
-s
[[alternative HTML version deleted]]
On Apr 1, 2009, at 15:49 , Stavros Macrakis wrote:> The documentation for assignment says: > > In all the assignment operator expressions, 'x' can be a name or > an expression defining a part of an object to be replaced (e.g., > 'z[[1]]'). A syntactic name does not need to be quoted, though it > can be (preferably by backticks). > > But the implementation allows assignment to a character string (i.e. > not a > name), which it coerces to a name: > > "foo" <- 23; foo > # returns 23 >> is.name("foo") > [1] FALSE > > Is this a documentation error or an implementation error? >Neither - what you're missing is that you are actually quoting foo namely with double-quotes. Hence both the documentation and the implementations are correct. (Technically "name" as referred above can be either a symbol or a character string). Cheers, Simon> The coercion is not happening at parse time: > > class(quote("foo"<-3)[[2]]) > [1] "character" > > In fact, bizarrely, not only does it coerce to a name, it actually > *modifies* the parse tree: > >> gg <- quote("hij" <- 4) >> gg > "hij" <- 4 >> eval(gg) >> gg > hij <- 4 > > *** The cases below only come up with expression trees generated > programmatically as far as I know, so are much more marginal cases. > *** > > The <- operator even allows the left-hand-side to be of length > 1, > though > it just ignores the other elements, with the same side effect as > before: > >> gg <- quote(x<-44) >> gg[[2]] <- c("x","y") >> gg > c("x", "y") <- 44 >> eval(gg) >> x > [1] 44 >> y > Error: object "y" not found >> gg > x <- 44 > > None of this is documented in ? <-, and it is rather a surprise that > evaluating an expression tree can modify it. I admit we had a feature > (performance hack) like this in MacLisp years ago, where expanded > syntax > macros replaced the source code of the macro, but it was a documented, > general, and optional part of the macro mechanism. > > Another little glitch: > > gg <- quote(x<-44); gg[[2]] <- character(0); eval(gg) > Error in eval(expr, envir, enclos) : > 'getEncChar' must be called on a CHARSXP > > This looks like an internal error that users shouldn't see. > > -s > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > >
Stavros Macrakis wrote:> The documentation for assignment says: > > In all the assignment operator expressions, 'x' can be a name or > an expression defining a part of an object to be replaced (e.g., > 'z[[1]]'). A syntactic name does not need to be quoted, though it > can be (preferably by backticks). > > But the implementation allows assignment to a character string (i.e. not a > name), which it coerces to a name: > > "foo" <- 23; foo > # returns 23 > > is.name("foo") > [1] FALSE > > Is this a documentation error or an implementation error? >i think this concords with the documentation in the sense that in an assignment a string can work as a name. note that `foo bar` = 1 is.name(`foo`) # FALSE the issue is different here in that in is.name("foo") "foo" evaluates to a string (it works as a string literal), while in is.name(`foo`) `foo` evaluates to the value of the variable named 'foo' (with the quotes *not* belonging to the name). with only a quick look at the sources (src/main/envir.c:1511), i guess the first element to an assignment operator (i mean the left-assignment operators) is converted to a name, so that in "foo" <- 1 "foo" evaluates to a string and not a name (hence is.name("foo") is false), but internally it is sort of 'coerced' to a name, as in as.name("foo") # `foo` is.name(as.name("foo")) # TRUE> The coercion is not happening at parse time: > > class(quote("foo"<-3)[[2]]) > [1] "character" >i think the internal assignment op really receives a string in a case like "foo" <- 1, it knows it has to treat it as a name without the parser classifying the string as a name. (pure guesswork, again.) the documentation might avoid calling a plain string a 'quoted name', though, it is confusing. a quoted name is something like quote(name) or quote(`name`): is(quote(name)) # "name" "language" is(quote(`name`)) # "name" "language" but *not* something like "name": is("name") # "character" "vector" "data.frameRowLabels" and *not* like quote("name"): is(quote("name")) # "character" "vector" "data.frameRowLabels"> In fact, bizarrely, not only does it coerce to a name, it actually > *modifies* the parse tree: > > > gg <- quote("hij" <- 4) > > gg > "hij" <- 4 > > eval(gg) > > gg > hij <- 4 >wow! that's called 'functional programming' ;) you're right: gg = quote({"a" = 1}) is(gg[[2]][[2]]) # "character" ... eval(gg) is(gg[[2]][[2]]) # "name" ...> *** The cases below only come up with expression trees generated > programmatically as far as I know, so are much more marginal cases. *** > > The <- operator even allows the left-hand-side to be of length > 1, though > it just ignores the other elements, with the same side effect as before: >that's clear from the sources; see src/main/envir.c:1521. it should be documented (maybe it is, i haven't investigated this issue).> > gg <- quote(x<-44) > > gg[[2]] <- c("x","y") > > gg > c("x", "y") <- 44 > > eval(gg)but also this: rm(list=ls()) do.call('=', list(letters, 1)) # just fine a # 1 b # error weird these work. i think it deserves a warning, at the very least, as in c('x', 'y') = 4 # error: assignment to non-language object c(x, y) = 4 # error: could not find function c<- (provided that x and y are already there) btw., that's what you can do with rvalues (using the otherwise semantically void operator `:=`). these could seem equivalent, but they're (obviously) not: 'x' = 1 c('x') = 1 x = 1 c(x) = 1> > x > [1] 44 > > y > Error: object "y" not found > > gg > x <- 44 > > None of this is documented in ? <-, and it is rather a surprise that > evaluating an expression tree can modify it. I admit we had a feature > (performance hack) like this in MacLisp years ago, where expanded syntax > macros replaced the source code of the macro, but it was a documented, > general, and optional part of the macro mechanism. >but - maclisp was designed by computer scientists in a research project, - r is being implemented by statisticians for practical purposes. almost every part differs here (and almost no pun intended).> Another little glitch: > > gg <- quote(x<-44); gg[[2]] <- character(0); eval(gg) > Error in eval(expr, envir, enclos) : > 'getEncChar' must be called on a CHARSXP > > This looks like an internal error that users shouldn't see. >by no means the only example that the interface is no blood-brain barrier. vQ
Maybe Matching Threads
- Samba 4.1.6-Ubuntu on 14.04 domain join seems successful with caveats, testjoin reports no logon servers...
- Samba 4.1.6-Ubuntu on 14.04 domain join seems successful with caveats, testjoin reports no logon servers...
- Samba 4.1.6-Ubuntu on 14.04 domain join seems successful with caveats, testjoin reports no logon servers...
- Internal error in 'ls' for pathological environments (PR#14035)
- read.table, NA assignment, and sep