2
$\begingroup$

This question already has an answer here:

I'm trying to define a function that takes an expression and spits out a pure function involving a replacement rule of that function's variable. An example would be a function f such that f[x^2] returns x^2 /. x -> # & (let's just stick with single-variable function for simplicity's sake).

I have written 2 functions, both aim to do just that. Now, their pure function outputs do work when applied to something else (see last input of block code), but they themselves don't display in the form that I'd like:

(* 1 *)    
Clear[f1]
f1[expr_] := Module[{var},
  var = First@Variables[expr];
  expr /. var -> # &]

f1[x^2]
(* x^2 /. var$77097 -> #1 & *)


(* 2 *)
Clear[f2]
f2[expr_] := expr /. First@Variables[expr] -> # &

f2[x^2]
(* x^2 /. First[Variables[x^2]] -> #1 & *)


{f1[x^2][3], f2[x^2][3]}
(* {9, 9} *)

It seems like Rule holds the evaluation of the left hand side, which I don't really know why. Adding Evaluate to the left hand side did not help. I tried reading the documentation for Rule but couldn't find any relevant information on this behavior. One of its attributes is SequenceHold. Could that be a contribution? Also, if anyone could help me understand the result I got for each of those modules I'd really appreciate it. I'm very fuzzy on evaluation order inside Rule and Module.

Lastly, how can I build such a function mentioned in the beginning of my question?

$\endgroup$

marked as duplicate by eldo, C. E., RunnyKine, Michael E2, bobthechemist Aug 14 '14 at 3:20

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ f2[expr_] := With[{var = First@Variables[expr]}, expr /. var -> # &] $\endgroup$ – Daniel Lichtblau Aug 13 '14 at 19:08
  • $\begingroup$ Thanks so much! Could you help me understand why With will display the correct result but not Module? Please feel free to post that as an answer so I can upvote you. $\endgroup$ – seismatica Aug 13 '14 at 19:10
  • 1
    $\begingroup$ I believe this issue has already been well covered on this site, therefore I wish to close this question as a duplicate unless I can be convinced otherwise. Please review these and tell me which seems closest: (10086) (13757) (20766) (34345) (41640) $\endgroup$ – Mr.Wizard Aug 13 '14 at 21:26
  • $\begingroup$ I think the closest Q&A to this (13757 and 20766) involve using Function within Module where the local variable in Module conflicts with the formal parameter of the Function. I think my question is more of a conflict between a Module variable and the body of an inner Function, which won't let that variable evaluate due to Function's HoldAll attribute (I think that's what the reason was). Leonid's answer in this Q&A comes really close to explaining the issue. $\endgroup$ – seismatica Aug 13 '14 at 21:59
3
$\begingroup$

You can "inject" that variable by grabbing it with With. It then gets put into the body of the With verbatim, hence it gets inside the Function in the desired form.

f2[expr_] := With[{var = First@Variables[expr]}, expr /. var -> # &]

f2[x^2]

(* Out[79]= x^2 /. x -> #1 & *)

This can also be done in the way you had tried, with a bit of work to get past the held arguments to Function. In effect we inject the variable after rather than before we create the function.

f1[expr_] := Module[{var},
  expr /. var -> # & /. var -> First@Variables[expr]]

f1[x^2]

(* Out[87]= x^2 /. x -> #1 & *)
$\endgroup$
  • $\begingroup$ Really appreciate your answer! So were the results that I got due to the HoldAll attribute of Function? If so, why could With seemingly bypass that hold but not Module? $\endgroup$ – seismatica Aug 13 '14 at 19:40
  • $\begingroup$ Okay this answer by @LeonidShifrin seems to explain it: It is instructive to trace the execution of f. You will notice that[, with Using With, the] sum gets replaced by its value very early on, before the body starts evaluating. This is quite unlike Module, where variable entries get replaced by their values in the process of evaluation, just as it woud normally happen were the variables global. I wonder if this distinction is mentioned anywhere in the documentation. $\endgroup$ – seismatica Aug 13 '14 at 19:44
  • 1
    $\begingroup$ It's mentioned, though not quite in this way, under Scope, Applications, and Properties & Relations. That is to say it is documented but this "pre-injection" aspect is not, in my view, heavily emphasized. $\endgroup$ – Daniel Lichtblau Aug 13 '14 at 21:58
  • $\begingroup$ Thank you! It does get mentioned in With documentation quite a bit. $\endgroup$ – seismatica Aug 13 '14 at 22:04

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