4
$\begingroup$

I guess there is an easy way to do this, but I can't seem to figure it out. What I would like to do is to distribute a generic (i.e. without specifying what this function really does) binary function. So

f[a,b+c]

should be mapped to

f[a,b] + f[a,c]

And this must happen prior to any simplification or evaluation of the b+c term.

$\endgroup$
0

3 Answers 3

6
$\begingroup$

This is normally accomplished with Distribute and Unevaluated:

{a, b, c} = {1, 2, 3};

Distribute[ Unevaluated @ f[a, b + c] ]

f[1, 2] + f[1, 3]

This can be rolled into a function if desired:

SetAttributes[heldDistribute, HoldFirst]

heldDistribute[x_, args___] := Distribute[Unevaluated @ x, args]

f[a, b + c] // heldDistribute
f[1, 2] + f[1, 3]
heldDistribute[f[4, 5*7], Times]
f[4, 5] f[4, 7]
$\endgroup$
1
  • $\begingroup$ The Unevaluated prefix is what I was looking for. Cool. Thanks! $\endgroup$
    – janitor048
    Oct 23, 2012 at 14:16
6
$\begingroup$

Distribute works if a and b are unevaluated

Distribute[f[a, b + c]]
(* f[a, b] + f[a, c] *)

If you want to ensure that the function is distributed before the evaluation of b+c you can use the HoldAll attribute.

SetAttributes[f, HoldAll]
Distribute[f[a, 5 + 3]]
(* f[a, 3] + f[a, 5] *)
$\endgroup$
5
  • $\begingroup$ Ok, the Hold-stuff is what I was missing. Thanks. One thing though. I need to set the HoldAll, Distribute and then clear the HoldAll for further evaluation. Is there a way to do this in one go? Or to set HoldAll temporary? $\endgroup$
    – janitor048
    Oct 23, 2012 at 12:01
  • $\begingroup$ @janitor048 I don't see why you would need to clear HoldAll. Can you give an example? $\endgroup$
    – Ajasja
    Oct 23, 2012 at 12:09
  • $\begingroup$ Because in the next step the arguments of f need to be checked in some sort of pattern matching. More explicitly, f is the f from the answer by celtschk to this question mathematica.stackexchange.com/questions/13320/… $\endgroup$
    – janitor048
    Oct 23, 2012 at 12:44
  • $\begingroup$ @janitor048 Aha. Well, there is Mr. Wizards answer now:) $\endgroup$
    – Ajasja
    Oct 23, 2012 at 13:10
  • $\begingroup$ Yep, I'm employing Mr. Wizards approach now as it allows to only temporarily hold f and later proceed with the normal f. But I will definitely keep in mind for later uses that one can permanently set a HoldAll attribute to generic functions. Thanks again. $\endgroup$
    – janitor048
    Oct 23, 2012 at 14:15
3
$\begingroup$

A more convoluted version. Internal Hold is required so that Map does not evaluate 1+2+3.

SetAttributes[map, HoldAll];
map[func_, sum_Plus] := ReleaseHold@Map[func, Hold@sum, {2}];

Test:

map[f[a, #] &, x + y + z]

f[a, x] + f[a, y] + f[a, z]

map[f[a, #] &, 1 + 2 + 3]

f[a, 1] + f[a, 2] + f[a, 3]

$\endgroup$

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.