An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20090401/5b5a1e8d/attachment-0001.pl>
Definition of = vs. <-
10 messages · Duncan Murdoch, Martin Morgan, Stavros Macrakis +2 more
On 4/1/2009 10:38 AM, Stavros Macrakis wrote:
NOTA BENE: This email is about `=`, the assignment operator (e.g. {a=1}
which is equivalent to { `=`(a,1) } ), not `=` the named-argument syntax
(e.g. f(a=1), which is equivalent to
eval(structure(quote(f(1)),names=c('','a'))).
As far as I can tell from the documentation, assignment with = is precisely
equivalent to assignment with <-. Yet they call different primitives:
The parser does treat them differently:
> if (x <- 2) cat("assigned\n")
assigned
> if (x = 2) cat("assigned\n")
Error: unexpected '=' in "if (x ="
The ?"=" man page explains this:
" The operator '<-' can be used anywhere,
whereas the operator '=' is only allowed at the top level (e.g.,
in the complete expression typed at the command prompt) or as one
of the subexpressions in a braced list of expressions. "
though the restriction on '=' seems to be described incorrectly:
> if ((x = 2)) cat("assigned\n")
assigned
in which the assignment is in parentheses, not a braced list.
As to the difference between the operations of the two primitives: see
do_set in src/main/eval.c. The facility is there to distinguish between
them, but it is not used.
Duncan Murdoch
`=`
.Primitive("=")
`<-`
.Primitive("<-")
(Perhaps these are different names for the same internal function?)
Also, the difference is preserved by the parser:
quote({a=b})
{
a = b
}
quote({a<-b})
{
a <- b
}
even though in other cases the parser canonicalizes variant syntax, e.g. ->
to <-:
quote({a->b})
{
b <- a
}
`->`
Error: object "->" not found
Is there in fact some semantic difference between = and <- ?
If not, why do they use a different operator internally, each calling a
different primitive?
Or is this all just accidental inconsistency resulting from the '=', '<-',
and '->' features being added at different times by different people working
off different stylistic conventions?
-s
[[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.
Duncan Murdoch <murdoch at stats.uwo.ca> writes:
On 4/1/2009 10:38 AM, Stavros Macrakis wrote:
NOTA BENE: This email is about `=`, the assignment operator (e.g. {a=1}
which is equivalent to { `=`(a,1) } ), not `=` the named-argument syntax
(e.g. f(a=1), which is equivalent to
eval(structure(quote(f(1)),names=c('','a'))).
As far as I can tell from the documentation, assignment with = is
precisely
equivalent to assignment with <-. Yet they call different primitives:
The parser does treat them differently:
> if (x <- 2) cat("assigned\n")
assigned
> if (x = 2) cat("assigned\n")
Error: unexpected '=' in "if (x ="
The ?"=" man page explains this:
" The operator '<-' can be used anywhere,
whereas the operator '=' is only allowed at the top level (e.g.,
in the complete expression typed at the command prompt) or as one
of the subexpressions in a braced list of expressions. "
though the restriction on '=' seems to be described incorrectly:
> if ((x = 2)) cat("assigned\n")
assigned in which the assignment is in parentheses, not a braced list. As to the difference between the operations of the two primitives: see do_set in src/main/eval.c. The facility is there to distinguish between them, but it is not used.
10.4.2 of R-lang shows they differ in precedence
x = y <- 1 rm(x,y) x <- y = 1
Error in (x <- y) = 1 : object 'x' not found
as reflected in main/names.c (PREC_LEFT vs. PREC_EQ)
{"<-", do_set, 1, 100, -1, {PP_ASSIGN, PREC_LEFT, 1}},
{"=", do_set, 3, 100, -1, {PP_ASSIGN, PREC_EQ, 1}},
and include/Defn.h
PREC_LEFT = 1,
PREC_EQ = 2,
Martin
Duncan Murdoch
`=`
.Primitive("=")
`<-`
.Primitive("<-")
(Perhaps these are different names for the same internal function?)
Also, the difference is preserved by the parser:
quote({a=b})
{
a = b
}
quote({a<-b})
{
a <- b
}
even though in other cases the parser canonicalizes variant syntax,
e.g. ->
to <-:
quote({a->b})
{
b <- a
}
`->`
Error: object "->" not found
Is there in fact some semantic difference between = and <- ?
If not, why do they use a different operator internally, each
calling a
different primitive?
Or is this all just accidental inconsistency resulting from the '=',
<-',
and '->' features being added at different times by different people working
off different stylistic conventions?
-s
[[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.
Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M1 B861 Phone: (206) 667-2793
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20090401/cc395c3b/attachment-0001.pl>
On 4/1/2009 11:39 AM, Stavros Macrakis wrote:
On Wed, Apr 1, 2009 at 10:55 AM, Duncan Murdoch <murdoch at stats.uwo.ca>wrote:
On 4/1/2009 10:38 AM, Stavros Macrakis wrote:
As far as I can tell from the documentation, assignment with = is precisely equivalent to assignment with <-. Yet they call different primitives:
The parser does treat them differently:
if (x <- 2) cat("assigned\n")
assigned
if (x = 2) cat("assigned\n")
Error: unexpected '=' in "if (x ="
Interesting way of handling the classic C glitch (some of us would say "design flaw in C", but...)
The ?"=" man page explains this:
" The operator '<-' can be used anywhere,
whereas the operator '=' is only allowed at the top level (e.g.,
in the complete expression typed at the command prompt) or as one
of the subexpressions in a braced list of expressions. "
though the restriction on '=' seems to be described incorrectly:
if ((x = 2)) cat("assigned\n")
assigned
The restriction is incorrect in many other cases as well, e.g. the following are all assignments: function()a=3; if(...)a=3; while(...)a=3; a=b=3 (two assignments), and even a*b=3 (parses as assignment, but `*<-` happens not to be defined in the default environment). In fact, the only cases I have found where = does *not* mean assignment is in functional or array argument position (f(a=2) and f[a=2]), the following contexts with function-like syntax: function(XXX)..., if(XXX)..., and while(XXX)...; and for (i in XXX).... Are there any others? Perhaps the documentation could be updated? As to the difference between the operations of the two primitives: see
do_set in src/main/eval.c. The facility is there to distinguish between them, but it is not used.
So are you saying that it is planned to make = and <- non-synonymous, unlike a<-b and b->a, which parse the same and are therefore guaranteed to be synonymous?
No, I don't know of any plans like that. That doesn't mean there aren't any, nor does the current implementation of <- and -> guarantee no changes there, but I wouldn't expect either to change. Duncan Murdoch
Stavros Macrakis wrote:
`->`
Error: object "->" not found
that's weird! vQ
Martin Morgan wrote:
x <- y = 1
Error in (x <- y) = 1 : object 'x' not found
this error does not make sense to me... if the precedence is as the
parentheses suggest, the error should be like in
(x <- y)
# error: object 'y' not found
vQ
Wacek Kusnierczyk wrote:
Stavros Macrakis wrote:
`->`
Error: object "->" not found
that's weird!
Why???
O__ ---- Peter Dalgaard ?ster Farimagsgade 5, Entr.B c/ /'_ --- Dept. of Biostatistics PO Box 2099, 1014 Cph. K (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk) FAX: (+45) 35327907
Peter Dalgaard wrote:
Wacek Kusnierczyk wrote:
Stavros Macrakis wrote:
`->`
Error: object "->" not found
that's weird!
Why???
partly because it was april fools.
but more seriously, it's because one could assume that in any syntactic
expression with an operator involved, the operator maps to a semantic
object. it has been claimed on this list (as far as i recall; don't
ask me for reference, but if pressed, i'll find it) that any expression
of the form
<lhs> <op> <rhs>
is a syntactic variant for
`<op>`(<lhs>, <rhs>)
(which would, following that argumentation, make r a lisp-like language)
but this apparently does not apply to '->'. i would (naively, perhaps)
expect that `->` is a function, which, internally, may well just invert
the order of arguments and imemdiately call `<-`. the fact that
expressions involving '->' are converted, at the parse time, into ones
using '<-' is far from obvious to me (it is now, but not a priori):
quote(1->a)
# a <- 1
# why not: 1 -> a
# why not: `->`(1, a)
and btw. the following is also weird:
quote(a=1)
# 1
not because '=' works as named argument specifier (so that the result
would be something like `=`(a, 1)), but because quote has no parameter
named 'a', and i would expect an error to be raised:
# hypothetical
quote(a=1)
# error: unused argument(s): (a = 1)
as in, say
vector(mode='list', i=1)
# error: unused argument(s): (i = 1)
it appears that, in fact, quite many r functions will gladly match a
*named* argument with a *differently named* parameter. it is weird to
the degree that it is *wrong* wrt. the 'r language definition', sec.
4.3.2 'argument matching', which says:
"The first thing that occurs in a function evaluation is the matching of
formal to the actual or
supplied arguments. This is done by a three-pass process:
1. Exact matching on tags. For each named supplied argument the list of
formal arguments is
searched for an item whose name matches exactly. It is an error to
have the same formal
argument match several actuals or vice versa.
2. Partial matching on tags. Each remaining named supplied argument is
compared to the
remaining formal arguments using partial matching. If the name of
the supplied argument
matches exactly with the first part of a formal argument then the
two arguments are con-
sidered to be matched. It is an error to have multiple partial
matches. Notice that if f
<- function(fumble, fooey) fbody, then f(f = 1, fo = 2) is illegal,
even though the 2nd
actual argument only matches fooey. f(f = 1, fooey = 2) is legal
though since the second
argument matches exactly and is removed from consideration for
partial matching. If the
formal arguments contain ?...? then partial matching is only
applied to arguments that
precede it.
3. Positional matching. Any unmatched formal arguments are bound to
unnamed supplied
arguments, in order. If there is a ?...? argument, it will take up
the remaining arguments,
tagged or not.
If any arguments remain unmatched an error is declared.
"
if you now consider the example of quote(a=1), with quote having *one*
formal argument (parameter) named 'expr' (see ?quote), we see that:
1. there is no exact match between the formal 'expr' and the actual 'a'
2. there is no partial match between the formal 'expr' and the actual 'a'
3a. there is an unmatched formal argument ('expr'), but no unnamed
actual argument. hence, 'expr' remains unmatched.
3b. there is no argument '...' (i think the r language definition is
lousy and should say 'formal argument' here, as you can have it as an
actual, too, as in quote('...'=1)). hence, the actual argument named
'a' will not be 'taken up'.
there remain unmatched arguments (i guess the r language definition is
lousy and should say 'unmatched actual arguments', as you can obviously
have unmatched formals, as in eval(1)), hence an error should be
'declared' (i guess 'raised' is more appropriate).
this does not happen in quote(a=1) (and many, many other cases), and
this makes me infer that there is a *bug* in the implementation of
argument matching, since it clearly does not conform to the definiton.
hence, i cc: to r-devel, and will also report a bug in the usual way.
vQ
Wacek Kusnierczyk wrote:
and btw. the following is also weird:
quote(a=1)
# 1
not because '=' works as named argument specifier (so that the result
would be something like `=`(a, 1)),
i meant to write: not because '=' does not work as an assignment operator (or otherwise the result would be ...)
but because quote has no parameter
named 'a', and i would expect an error to be raised:
# hypothetical
quote(a=1)
# error: unused argument(s): (a = 1)
as in, say
vector(mode='list', i=1)
# error: unused argument(s): (i = 1)
it appears that, in fact, quite many r functions will gladly match a
*named* argument with a *differently named* parameter. it is weird to
the degree that it is *wrong* wrt. the 'r language definition', sec.
4.3.2 'argument matching', which says:
"The first thing that occurs in a function evaluation is the matching of
formal to the actual or
supplied arguments. This is done by a three-pass process:
1. Exact matching on tags. For each named supplied argument the list of
formal arguments is
searched for an item whose name matches exactly. It is an error to
have the same formal
argument match several actuals or vice versa.
2. Partial matching on tags. Each remaining named supplied argument is
compared to the
remaining formal arguments using partial matching. If the name of
the supplied argument
matches exactly with the first part of a formal argument then the
two arguments are con-
sidered to be matched. It is an error to have multiple partial
matches. Notice that if f
<- function(fumble, fooey) fbody, then f(f = 1, fo = 2) is illegal,
even though the 2nd
actual argument only matches fooey. f(f = 1, fooey = 2) is legal
though since the second
argument matches exactly and is removed from consideration for
partial matching. If the
formal arguments contain ???...??? then partial matching is only
applied to arguments that
precede it.
3. Positional matching. Any unmatched formal arguments are bound to
unnamed supplied
arguments, in order. If there is a ???...??? argument, it will take up
the remaining arguments,
tagged or not.
If any arguments remain unmatched an error is declared.
"
if you now consider the example of quote(a=1), with quote having *one*
formal argument (parameter) named 'expr' (see ?quote), we see that:
1. there is no exact match between the formal 'expr' and the actual 'a'
2. there is no partial match between the formal 'expr' and the actual 'a'
3a. there is an unmatched formal argument ('expr'), but no unnamed
actual argument. hence, 'expr' remains unmatched.
3b. there is no argument '...' (i think the r language definition is
lousy and should say 'formal argument' here, as you can have it as an
actual, too, as in quote('...'=1)). hence, the actual argument named
'a' will not be 'taken up'.
there remain unmatched arguments (i guess the r language definition is
lousy and should say 'unmatched actual arguments', as you can obviously
have unmatched formals, as in eval(1)), hence an error should be
'declared' (i guess 'raised' is more appropriate).
this does not happen in quote(a=1) (and many, many other cases), and
this makes me infer that there is a *bug* in the implementation of
argument matching, since it clearly does not conform to the definiton.
hence, i cc: to r-devel, and will also report a bug in the usual way.