Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
939 views
in Technique[技术] by (71.8m points)

r - Unexpected behaviour with argument defaults

I just ran into something odd, which hopefully someone here can shed some light on. Basically, when a function has an argument whose default value is the argument's name, strange things happen (well, strange to me anyway).

For example:

y <- 5

f <- function(x=y) x^2

f2 <- function(y=y) y^2

I would consider f and f2 to be equivalent; although they use different variable names internally, they should both pick up the y object in the global environment to use as the default. However:

> f()
[1] 25

> f2()
Error in y^2 : 'y' is missing

Not sure why that is happening.

Just to make things even more interesting:

f3 <- function(y=y) y$foo

> f3()
Error in f3() : 
  promise already under evaluation: recursive default argument reference or earlier problems?

I expected f3 to throw an error, but not that one!

This was tested on R 2.11.1, 2.12.2, and 2.14, on 32-bit Windows XP SP3. Only the standard packages loaded.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Default arguments are evaluated inside the scope of the function. Your f2 is similar (almost equivalent) to the following code:

f2 = function(y) {
    if (missing(y)) y = y
    y^2
}

This makes the scoping clearer and explains why your code doesn’t work.

Note that this is only true for default arguments; arguments that are explicitly passed are (of course) evaluated in the scope of the caller.

Lazy evaluation, on the other hand, has nothing to do with this: all arguments are lazily evaluated, but calling f2(y) works without complaint. To show that lazy evaluation always happens, consider this:

f3 = function (x) {
    message("x has not been evaluated yet")
    x
}

f3(message("NOW x has been evaluated")

This will print, in this order:

x has not been evaluated yet
NOW x has been evaluated

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...