Reputation: 21502
This really falls under the purview of "Don't DO that!" ,but..
I wrote this to see what would happen.
circit <-function(x=deparse(substitute(y)),y=deparse(substitute(x)))
{
return(list(x=x,y=y))
}
Two examples:
> circit()
$x
[1] "deparse(substitute(x))"
$y
[1] "deparse(substitute(y))"
> circit(3)
$x
[1] 3
$y
[1] "3"
Notice the subtle swap of "x" and "y" in the output.
I can't follow the logic, so can someone explain how the argument parser handles this absurd pair of default inputs? (the second case is easy to follow)
Upvotes: 2
Views: 62
Reputation: 162351
The key thing to understand/remember is that formal arguments are promise objects, and that substitute()
has special rules for how it evaluates promise objects. As explained in ?substitute
, it returns their expression slot, not their value:
Substitution takes place by examining each component of the parse tree as follows: If it is not a bound symbol in ‘env’, it is unchanged. If it is a promise object, i.e., a formal argument to a function or explicitly created using ‘delayedAssign()’, the expression slot of the promise replaces the symbol. If it is an ordinary variable, its value is substituted, unless ‘env’ is ‘.GlobalEnv’ in which case the symbol is left unchanged.
To make this clearer, it might help to walk through the process in detail. In the first case, you call circuit()
with no supplied arguments, so circuit()
uses the default values of both x=
and y=
.
For x
, that means its value is gotten by evaluating deparse(substitute(y))
. The symbol y
in that expression is matched by the formal argument y
, a promise object. substitute()
replaces the symbol y
with its expression slot, which holds the expression deparse(substitute(x))
. Deparsing that expression returns the text string "deparse(substitute(x))"
, which is what gets assigned to x
's value slot.
Likewise, the value of y
is gotten by evaluating the expression deparse(substitute(x))
. The symbol x
is matched by the formal argument x
, a promise object. Even though the value of x
is something else, its expression slot is still deparse(substitute(y))
, so that's what's returned by evaluating substitute(x)
. As a result, deparse(substitute(x))
returns the string "deparse(substitute(y))"
Upvotes: 3