Skip to main content
13 events
when toggle format what by license comment
Mar 16, 2017 at 9:52 comment added Alexey Popkov @evanb Yes, it is a best-practice rule: when you use Evaluate always remember that it can break scoping and hence you (possibly) have to introduce additional scoping/protection in order to avoid bugs.
Mar 16, 2017 at 9:48 comment added Alexey Popkov @evanb A detailed explanation of the variable renaming mechanics can be found in this answer (and after reading it I realized that my formulation above wasn't quite correct: actually it is namely RuleDelayed who renames x to x$ inside of Function, because the latter is inert on that stage).
Mar 16, 2017 at 9:47 comment added evanb Gotcha. So here it's more of a best-practices thing, but in other examples it can really save you.
Mar 16, 2017 at 9:26 comment added Alexey Popkov @evanb But your point is correct: in this case we won't get additional safety by using a formal symbol as a parameter because we already have subtle and very limited additional scoping due to the combination of RuleDelayed and Function (I forgot about this possibility when wrote the first comment). Such scoping isn't very reliable though (as I showed above).
Mar 16, 2017 at 9:09 comment added Alexey Popkov @evanb As a result Function renames its local variable x to x$ what in effect protects it from being replaced by the value of x when Evaluate fires. This behavior is (a bit vaguely) documented: "In general, the Wolfram Language renames the formal parameters in an object like Function[vars,body] whenever body is modified in any way by the action of another pure function." In this answer I give extended explanation of this behavior.
Mar 16, 2017 at 9:09 comment added Alexey Popkov @evanb The reason why it works in this case is not that Evaluate "understands" something: evaluating f[n] returns Function[x, FourierSinSeries[2, 3, n]] what demonstrates that the scope is indeed broken. What happend here is that the lexical replacement (which comes from the delayed definition :=) is performed inside of the body of Function before the Evaluate fires, i.e. when the scope is not broken yet. [continued in the next comment]
Mar 16, 2017 at 8:00 comment added evanb I tried x = 3; f[n_] := f[n] = Function[x, Evaluate@FourierSinSeries[x - 1, x, n]] (after quitting the kernel) and it works fine. So in this case there doesn't seem to be any danger---Evaluate must understand that it is inside a Function.
Mar 16, 2017 at 7:52 comment added evanb I see. It's to protect you from picking up state. Thanks for the pointer / link!
Mar 16, 2017 at 7:47 comment added Alexey Popkov @evanb In your function definition your Evaluate breaks the scope of Function and if x has a value, it will be substituted into the FourierSinSeries[x - 1, x, n] expression before evaluation of FourierSinSeries. The safety of formal parameters comes from the fact that they are Protected and you can't assign values to them. More lengthy explanation can be found in this answer.
Mar 16, 2017 at 7:40 comment added evanb Can you demonstrate? I frankly never understood the use of the Formal parameters. Maybe this deserves its own question?
Mar 16, 2017 at 7:16 comment added Alexey Popkov @evanb Good demonstration of currying with memoization. But for safety it is better to use \[FormalX] instead of x in the definition for f.
Mar 16, 2017 at 7:09 comment added evanb Another work around is to curry f. Define f[n_] := f[n] = Function[x, Evaluate@FourierSinSeries[x - 1, x, n]]. Then Plot[{f[1][x], f[5][x]}, {x,0,3}].
Mar 16, 2017 at 6:42 history answered Alexey Popkov CC BY-SA 3.0