would like to receive expert opinion to avoid potential trouble
[..]
i think the following is the most secure way if one really
really has to do assignment in a function call
f({a=3})
and if one keeps this convention, <- can be dropped altogether.
secure is relative, since due to R's lazy evaluation you never know whether a function's argument is being evalutated, look at:
f<- function(x)TRUE
x <- 1
f((x=2)) # obscured attempt to assign in a function call
[1] TRUE
x
[1] 1
Thus there is dangerous advice in the referenced blog which reads:
"
f(x <- 3)
which means "assign 3 to x, and call f with the first argument set to the value 3
"
This might be the case in C but not in R. Actually in R "f(x <- 3)" means: call f with a first unevaluated argument "x <- 3", and if and only if f decides to evaluate its first argument, then the assignment is done. To make this very clear:
f <- function(x)if(runif(1)>0.5) TRUE else x
x <- 1
print(f(x <- x + 1))
[1] TRUE
print(f(x <- x + 1))
[1] 2
print(f(x <- x + 1))
[1] 3
print(f(x <- x + 1))
[1] TRUE
print(f(x <- x + 1))
[1] 4
print(f(x <- x + 1))
[1] 5
print(f(x <- x + 1))
[1] TRUE
print(f(x <- x + 1))
[1] 6
print(f(x <- x + 1))
[1] TRUE
Here it is unpredictable whether your assignment takes place. Thus assigning like f({x=1}) or f((x=1))is the maximum dangerous thing to do: even if you have a code-reviewer and the guy is aware of the danger of f(x<-1) he will probably miss it because f((x=1)) does look too similar to a standard call f(x=1).
According to help("<-"), R's assignment operator is rather "<-" than "=":
"
The operators <- and = assign into the environment in which they are evaluated. 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.
"
So my recommendation is
1) use R's assignment operator with two spaces around (or assign()) and don't obscure assignments by using C's assignment operator (or other languages equality operator)
2) do not assign in function arguments unless you have good reasons like in system.time(x <- something)
HTH
Jens Oehlschl?gel
P.S. Disclaimer: you can consider me biased towards "<-", never trust experts, whether experienced or not.
P.P.S. a puzzle, following an old tradition:
What is going on here? (and what would you need to do to prove it?)
# Tip: no standard packages modified, no extra packages loaded, neither classes nor methods defined, no print methods hiding anything, if you would investigate my R you would not find any false bottom anymore
version
_
platform i386-pc-mingw32
arch i386
os mingw32
system i386, mingw32
status
major 2
minor 8.1
year 2008
month 12
day 22
svn rev 47281
language R
version.string R version 2.8.1 (2008-12-22)
--
would like to receive expert opinion to avoid potential trouble
[..]
i think the following is the most secure way if one really
really has to do assignment in a function call
f({a=3})
and if one keeps this convention, <- can be dropped altogether.
secure is relative, since due to R's lazy evaluation you never know whether a function's argument is being evalutated,
for sure, but that's not different between <- and {=}. in both cases,
if the argument is not used, assignment will not be made.
f<- function(x)TRUE
x <- 1
f((x=2)) # obscured attempt to assign in a function call
[1] TRUE
x
[1] 1
same with f(x<-2)
Thus there is dangerous advice in the referenced blog which reads:
"
f(x <- 3)
which means "assign 3 to x, and call f with the first argument set to the value 3
"
This might be the case in C but not in R. Actually in R "f(x <- 3)" means: call f with a first unevaluated argument "x <- 3", and if and only if f decides to evaluate its first argument, then the assignment is done.
indeed. i have already argued that using assignment within function
calls is not a good idea; but pick any book on r, you likely to find
numerous examples of it, without an appropriate warning.
<snip>
Here it is unpredictable whether your assignment takes place. Thus assigning like f({x=1}) or f((x=1))
or f(x<-1)
is the maximum dangerous thing to do: even if you have a code-reviewer and the guy is aware of the danger of f(x<-1) he will probably miss it because f((x=1)) does look too similar to a standard call f(x=1).
sorry, to me f({x=1}) looks pretty much unlike f(x=1). if someone uses
assignments in function calls and does not know what he's doing, it's
his fault.
According to help("<-"), R's assignment operator is rather "<-" than "=":
"
The operators <- and = assign into the environment in which they are evaluated. 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.
to me, it doesn't say anything like that R's assignment operator is
rather "<-" than "=".
"
So my recommendation is
1) use R's assignment operator with two spaces around (or assign()) and don't obscure
... but do beautify ...
assignments by using C's
don't acknowledge c for it
assignment operator (or other languages equality operator)
2) do not assign in function arguments unless you have good reasons like in system.time(x <- something)
certainly good advice.
P.P.S. a puzzle, following an old tradition:
What is going on here? (and what would you need to do to prove it?)
On Thu, Mar 12, 2009 at 8:29 AM, "Jens Oehlschl?gel" <oehl_list at gmx.de> wrote:
Thus there is dangerous advice in the referenced blog which reads:
"
f(x <- 3)
which means "assign 3 to x, and call f with the first argument set to the value 3
"
The thrust of the blog post was the stylistic question of whether to
use <- or = for assignment, not a recommendation to use constructs
like this. ?(In fact, the next line reads "This is a contrived example
though, and never really occurs in real-world programming.") But I've
added your sound advice that such constructs are best avoided. I've
never seen the need to perform assignments in function calls before,
but I'll avoid them now knowing about potential for mischief from lazy
evaluation. Thanks.
http://blog.revolution-computing.com/2008/12/use-equals-or-arrow-for-assignment.html
# David Smith
--
David M Smith <david at revolution-computing.com>
Director of Community, REvolution Computing www.revolution-computing.com
Tel: +1 (206) 577-4778 x3203 (Seattle, USA)
On Thu, 2009-03-12 at 17:10 -0700, David M Smith wrote:
On Thu, Mar 12, 2009 at 8:29 AM, "Jens Oehlschl?gel" <oehl_list at gmx.de> wrote:
Thus there is dangerous advice in the referenced blog which reads:
"
f(x <- 3)
which means "assign 3 to x, and call f with the first argument set to the value 3
"
The thrust of the blog post was the stylistic question of whether to
use <- or = for assignment, not a recommendation to use constructs
like this. (In fact, the next line reads "This is a contrived example
though, and never really occurs in real-world programming.") But I've
added your sound advice that such constructs are best avoided. I've
never seen the need to perform assignments in function calls before,
but I'll avoid them now knowing about potential for mischief from lazy
evaluation. Thanks.
http://blog.revolution-computing.com/2008/12/use-equals-or-arrow-for-assignment.html
# David Smith
--
David M Smith <david at revolution-computing.com>
Director of Community, REvolution Computing www.revolution-computing.com
Tel: +1 (206) 577-4778 x3203 (Seattle, USA)
Simon Blomberg, BSc (Hons), PhD, MAppStat.
Lecturer and Consultant Statistician
School of Biological Sciences
The University of Queensland
St. Lucia Queensland 4072
Australia
Room 320 Goddard Building (8)
T: +61 7 3365 2506
http://www.uq.edu.au/~uqsblomb
email: S.Blomberg1_at_uq.edu.au
Policies:
1. I will NOT analyse your data for you.
2. Your deadline is your problem.
The combination of some data and an aching desire for
an answer does not ensure that a reasonable answer can
be extracted from a given body of data. - John Tukey.
Dear Jens and Wacek:
I appreciate your answers very much.
I came up an example based on your comments.
I feel the example helped me to understand...(I could be missing your points
though :( )
If so, please let me know.
Simon pointed out the following link:
http://www.stat.auckland.ac.nz/mail/archive/r-downunder/2008-October/000300.html
I am still trying to understand it...
My question is how my conclusion (see at the end of the example below) drawn
from "lexical scope" perspective is related to
an understanding from an "environment" perspective (if an understanding from
"environment" perspective validly exists).
Thank you all again very much!
-Sean Zhang
#My little example is listed below
f1<-function(a=1,b=2) {print(a); print(b); print(a-b) }
f1() #get 3, makes sense
-1?
f1(2,) #get 0, makes sense
a <- 10
b <- 20
f1(a=a+1,b=a)
a #get 10 a is not changed outside function scope
b #get 20, b is not changed outside function scope
a <- 10
b <- 20
f1(a <- a+1, b <- a)
this is what you *really* shouldn't do unless you know what you're
doing. here you have not only the issue of whether the assignment will
actually be made, but also the issue of the order of evaluation of the
argument expressions, which depends on the when the arguments are used
within the function.
f = function(a, b, c)
if (c) a-b
else b-a
a=1; b=1; f(a <- a+1, b <- a, TRUE)
# 0
a
# 2
b
# 2
a=1; b=1; f(a <- a+1, b <- a, FALSE)
# -1
a
# 2
b
# 1
a #a is now 11, a is changed outside function
b #b is now 11 b is changed outside function
a <- 10
b <- 20
f1({a=a+1},{b = a})
a #a is changed into 11
b #b is changed into a(i.e., 11)
a <- 10
b <- 20
f1((a=a+1),(b = a))
a #a is changed into 11
b #b is changed into a(i.e., 11)
#my conclusion based on testing the example above is below
#say argument is a, when used inside paraenthesis of
whatever.fun<-function()
#a<-something, (a=something) , and {a<-something}
#are the same. They all change the values outside the function's scope.
#Typically, this breaks the desired lexical scope convention. so it is
dangerous.