11
$\begingroup$

Given an expression expresion in terms of a function f and given another function g, how could I write a Module that replaces the function f by the function g in the expresion expresion and returns it?

An example:

MyFunction[expresion_, f_, g_] := (...)

MyFunction[f[x]-3, f, Sin[x]] should evaluate to Sin[x]-3

MyFunction[D[f[x],x], f, x] should evaluate to 1

MyFunction[f[x], f, 19] should evaluate to 19

I hope it's clear.

$\endgroup$
4
  • 3
    $\begingroup$ f[x]-3 /. f-> Sin or more generally f[x]-3/. f-> Function[x,Sin[x]//Evaluate]? D[f[x],x]/. f-> #& $\endgroup$
    – chris
    Nov 27, 2012 at 12:17
  • $\begingroup$ How would that work for the 3º example? $\endgroup$
    – José D.
    Nov 27, 2012 at 12:19
  • $\begingroup$ @Trollkemada. Degree is not a function, but a constant like Pi, so it's not a valid argument for MyFunction as you have specified it. You could define toRadians[x_] := x Degree and use that as g. $\endgroup$
    – m_goldberg
    Nov 27, 2012 at 14:01
  • 1
    $\begingroup$ This question is quite puzzling, because neither Sin[x] nor x can reliably be construed as "functions." Shouldn't the first example return Sin[x][x]-3? If that seems silly, suppose Sin were a function that returns a function, as in sin[x_]:=Function[{y},y+x]. Now both sin[x][x] and sin[x] make sense, but only the former conforms to the problem statement in the first line (and evaluates to x+x, by the way). $\endgroup$
    – whuber
    Nov 27, 2012 at 21:52

4 Answers 4

5
$\begingroup$

replace function name with expression

I think the problem you try to solve is ill posed: if you want this to make sense you need to at least define some restrictions on what arguments the function f as it appears in the expression may have. What would you want the following to evaluate to?

MyFunction[f[x]-f[1,y]+f[z], f, Sin[x]]

The question becomes ill posed and hard to answer because you are intermixing expressions and functions in a way that makes things unnecessarily complicated. From your comments I understand that you can not aribtrarily change the calling syntax, but I would strongly suggest to discuss this with your collaborators, as a change will make all your lives a lot easier.

The following will do what I think you want (at least it succeeds for your example :-) with the restriction that the function f can only appear with one argument in expr and that that argument must be unique within expr (there is no checks whether that condition is fulfilled, though):

replaceFunctionWithExpression[expr_, f_, g_] := Module[{arg}, 
  arg = Cases[
     expr, (f[args___] | 
        Derivative[___][f][args___]) :> {args}, {0, Infinity}, 
     Heads -> True][[1, 1]];
  expr /. f -> (Function[g] /. arg -> #)
  ]

The whole task becomes somewhat involved because we need to find what the argument of the function f in expr is so we can find that within the expression g to generate the pure function with which to replace f. A bullet-proof version of this might use the HoldAll attribute for replaceFunctionWithExpression and implement some localization of at least the function argument, but I left that out. I would also like to emphazise avoiding this doesn't only make the code somewhat simpler but also demonstrates that Hold attributes are not necessary to get this to work for the derivatives example. With the HoldAll attribute you could get rid of the extra pattern for Derivatives, though, but that's only the part that searches for the arguments of f, the actual replacement works on the evaluated Derivative expressions just fine!

replace named function with function

You should note that with only a tiny change in how to call the function the task becomes essentially trivial: if we replace a named function with a (named or pure) function and not with an expression, the function you are looking for is actually too trival to justify any extra name for it:

replaceFunctionWithFunction[expr_, f_, g_] := expr /. f -> g

your examples would look like that for this:

replaceFunctionWithFunction[f[x] - 3, f, Sin]
replaceFunctionWithFunction[D[f[x], x], f, # &]
replaceFunctionWithFunction[f[x], f, 19 &]

Please note that this will do the (presumably) correct thing even with arbitrary arguments and number of arguments:

replaceFunctionWithFunction[D[f[a, 5], a] + f[a, b], f, #1*#2 &]

Things like the second and third of your examples would be formulated with pure functions (search for Function in the docs). The second could also be done with using Identity instead of #&. If you don't like the shortcut variant of Function you could also use the variant with named arguments, e.g. Function[x,x] instead of #&. Since Version 8 Mathematica also has the \[Function] special character which will provide a nice "mathematical" function notation, if you like that (e.g. x \[Function] x).

replace expression with expression

Finally I would like to mention that it is also possible to achieve the same thing in a relatively simple way if you replace expressions with expressions, as here:

replaceExpressionWithExpression[expr_, f_[arg_], g_] := expr /. f -> (Function[g] /. arg -> #)

which then would be called like this:

replaceExpressionWithExpression[f[x] - 3, f[x], Sin[x]]
replaceExpressionWithExpression[D[f[x], x], f[x], x]
replaceExpressionWithExpression[f[x], f[x], 19]

but this probably not as general (and elegant) as the "replace function with function" approach.

$\endgroup$
8
$\begingroup$

Unless I'm mistaken about what you are asking, the following seems to work.

SetAttributes[myFunction, HoldFirst]

myFunction[expr_, f_, g_] := Unevaluated[expr] /. f :> (g &)

For your examples it gives the following.

myFunction[f[x] - 3, f, Sin[x]]

(* -3 + Sin[x] *)

myFunction[D[f[x], x], f, x]

(*1*)

myFunction[f[x], f, 19]

(*19*)
$\endgroup$
0
3
$\begingroup$

chris's comment to the original question is perfect (not sure if/why //Evaluate is needed), but I just wanted to extend it. In my case I needed to perform small angle approximation (assume sin(x)~x, cos(x)~1), so I needed to replace a bunch of Sin[] with their arguments and Cos[] with 1.

Accordingly, this would remove sines:

Sin[a + b] /. Sin -> Function[x, x]
a + b

and my trigonometric equation turns into an algebraic one:

-4 Cos[g] Sin[a + b] Sin[t] - 4 Cos[g] /. {Sin -> Function[x, x], Cos -> Function[x, 1]}
-4 - 4 (a + b) t

which does not to depend on g. Now it is much easier to solve it (even though it is only an approximation for small angles) and see the logic behind how different angles interact.

Then, to take it one step further, replacing trig functions with their Taylor series up to 2rd order (sin has a zero for second Taylor coefficient, so it is still just x) results in a more intertwined relation:

Series[Sin[x], {x, 0, 2}]
-4Cos[g]Sin[a+b]Sin[t]-4Cos[g]/.{Sin->Function[x,x],Cos->Function[x, 1-x^2/2]}
-4 (1 - g^2/2) - 4 (a + b) (1 - g^2/2) t
$\endgroup$
0
$\begingroup$

It's not clear what you have in mind but maybe you just need an "operator" and a function on which it operates :

myFunction[oper_, f_] := oper[f]

myFunction[# - 3 &, Sin[x]]    
(* -3 + Sin[x] *)

myFunction[D[#, x] &, x]
(* 1 *) 

myFunction[# &, 19]
(* 19 *)
$\endgroup$
4
  • $\begingroup$ Yes, i need that, but I need something that works for my examples, i can't change the call to my function. $\endgroup$
    – José D.
    Nov 27, 2012 at 12:32
  • $\begingroup$ In which way my suggestion is not working for your examples ? $\endgroup$ Nov 27, 2012 at 12:36
  • $\begingroup$ MyFunction[f[x]-3, f, Sin[x]] doesn't return Sin[x]-3 with your implementation (It should be called like MyFunction[# -3 &,Sin[x]], I know, but i cant change the way the function is called (is a group-project) $\endgroup$
    – José D.
    Nov 27, 2012 at 12:43
  • $\begingroup$ Would myFunction2[expr_, f_, g_] := expr /. {f -> g}, myFunction2[f[x] - 3, f, Sin[#] &] be acceptable ? $\endgroup$ Nov 27, 2012 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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