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$
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$
  • $\begingroup$ The Unevaluated prefix is what I was looking for. Cool. Thanks! $\endgroup$ – janitor048 Oct 23 '12 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$
  • $\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 '12 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 '12 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 '12 at 12:44
  • $\begingroup$ @janitor048 Aha. Well, there is Mr. Wizards answer now:) $\endgroup$ – Ajasja Oct 23 '12 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 '12 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, privacy policy and cookie policy

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