Interesting discussion. A few things occurred to me.

Apologies to Iris Simmons: I mixed up his answer with Bert's question.

Bert raises questions about promises, and I think they are related to John 
Sorkin's question. A big difference between R and most other languages is that 
function arguments are computed lazily. match.call & substitute tell us what 
expressions will be evaluated if function arguments are needed but not the 
environments in which that will happen. The usual suspects are environment() 
and parent.frame(), but parent.frame(k) & maybe even other environments are 
possible. If you are really determined then I guess you can keep evaluating 
match.call() in parent frames until you have accounted for all the inputs.

It's not clear to what extent John Sorkin is concerned about writing functions 
as opposed to using functions. Lazy computation has advantages but leads to 
some issues.
Exactly matching the function's default expression for an input is not 
necessarily the same as omitting the input. The evaluation environment is 
different.
If the caller uses an expression with side effects then there is no guarantee 
that the side effects will happen. If there are side effects from two or more 
inputs then the order is uncertain. (If an argument is not supplied and the 
default has side effects then they might not happen either. However, I don't 
know why the function writer would specify any side effect except stop(), and 
then he or she has probably arranged for it to happen exactly when it should.)
If a default value depends on another input and that input is modified inside 
the function then order of evaluation of inputs becomes important. Even if you 
know exactly what you're doing when you write the function, you should make it 
clear to future maintainers. An explicit call to force clarifies that the input 
needs to be computed with the existing values of anything that is used in the 
default, even if the code is refactored so that the value is not used 
immediately. If you really want to modify another input before evaluating the 
default then specify that in a comment.

Jeff Newmiller makes a good point. You can still change your mind about 
inspecting a particular input without breaking old code that uses your 
function, and you don�t necessarily need default values.

Old definition: f <- function(�) {<code that passes � to other functions and 
does some other things>}

New definition:
f <- function(�, a = <default expression, possibly stop()>)
{ <pass �, a=a to another function>
  <do something with the output>
}

OR

f <- function(�, a)
{ if (missing(a)) # OK, this becomes clunky if there are several such inputs
  { < pass � to another function >}
  else
 { <inspect or modify a> # Pitfall: Changing the order of evaluation may break 
old code, but then the design was probably too devious in the first place.
    <pass �, a=a to another function>
  }
  <do something with the output>
}

Regards,
Jorgen Harmse.




        [[alternative HTML version deleted]]

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide https://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to