Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

If I have a function, that returns a function, for example:

f[a_] := a^2 * # &

then

f[3] == 3^2 # &

Is there a way to tell mathematica that I want part of the function evaluated, so that

f[3] == 9 # &

Obviously this example is quite simple, but in general the evaluation may be slow, and better if it's only performed once. I tried wrapping the important part (in this case, a^2) in 'Evaluate', but that didn't help.

Thanks!

share|improve this question
2  
You need to wrap the whole thing in Evaluate. Try: Evaluate[a^2 * # ] & –  rm -rf Feb 8 at 18:26

2 Answers 2

up vote 8 down vote accepted

The general way to construct functions with partially evaluated pieces is to use With, which is a general device for injecting evaluated pieces in otherwise unevaluated or held expressions. In your case, it would look like

f[a_] := With[{sqa = a^2}, sqa * # &]

The method based on Evaluate is generally less powerful, since evaluation of the entire body may be not desirable, while more deeply nested Evaluate will not result in what you want, due to the (local) way of how Evaluate works (because Function does not evaluate its body at the time it is constructed, the evaluation process, associated with the construction of the function, simply won't come to more deeply nested Evaluate instructions).

share|improve this answer
1  
I thought the OP wants to cache the result of f[3] such that f[3] can be run many times without calculating a^2 again and again (though he is happy with this answer). In this case, a single With or Evaluate doesn't help. Caching is also needed: f[a_] := f[a] = With[{x = a^2}, x*# &]. One can use Trace to see the difference. –  Yi Wang Feb 8 at 19:46
1  
With your answer, if I run f[3] // Trace, the result is {f[3],With[{sqa=3^2},sqa #1&],{3^2,9},9 #1&}. I guess the OP does not only want to run f[3] and get 9 # &, but also f[3] is only calculated once. This is what I can read from his sentence "Obviously this example is quite simple, but in general the evaluation may be slow, and better if it's only performed once. " I didn't see how With[...] can speed up things here without memorization. –  Yi Wang Feb 8 at 20:23
1  
Well, I think there are two cases depending on how to use f[3] with the calculation "only performed once". One way is let, say, g=f[3], and use g many times. Another is directly use f[3] many times. In the former case you are right, and your answer fully fills the OP's need. In the latter case, memorization is also needed. I don't know which is the exact case here... –  Yi Wang Feb 8 at 20:30
1  
@YiWang No need to explain to me why f[3] recomputes every time with my method, I don't disagree with you on that. My point is that, from where I stand, the OP did not ask for the f[n] calls optimization, and his problem was how to inject evaluated parts into otherwise unevaluated body of the function. In my experience, it is often better to not make additional assumptions, w.r.t. those made by the OP. Particularly in this case, where the question has been formulated quite clearly. If the OP wants memoization, there is plenty of information on it on this site already. –  Leonid Shifrin Feb 8 at 20:35
1  
@LeonidShifrin For what it's worth, I understood the question the same way as Yi Wang, i.e. define f so that 3^2 is not computed each time in f[3] (but not necessarily via memoization). I don't disagree with your answer though. –  rm -rf Feb 9 at 3:13

Leonid already named the big one, With, but there are a few more approaches I'd like to outline. First of all you can use Evaluate if you wish to evaluate the entire body of the Function, and if the Function isn't part of some larger held expression. I fully agree with Leonid however that With is more general and less prone to surprises here. Nevertheless for reference:

f[a_] := Evaluate[a^2 #] &
f[7]
49 #1 &

Likewise you can Apply Function to a List (or any other inert Head without a hold attribute):

f[a_] := Function @@ {a^2 #}
f[7]
49 #1 &

For spot evaluation in a deeper expression (like With) you can use a replacement rule in an inverted fashion. (See this Q&A for more examples.)

f[a_] := a^2 /. x_ :> (x # + 2 + 2 &)
f[7]
49 #1 + 2 + 2 &

Note that 2 + 2 is not evaluated. Also note the placement of ( ) to group the right-hand-side of RuleDelayed, because & has low operator precedence.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.