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.

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.

share|improve this question

3 Answers 3

up vote 6 down vote accepted

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]
share|improve this answer
    
The Unevaluated prefix is what I was looking for. Cool. Thanks! –  janitor048 Oct 23 '12 at 14:16

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] *)
share|improve this answer
    
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? –  janitor048 Oct 23 '12 at 12:01
    
@janitor048 I don't see why you would need to clear HoldAll. Can you give an example? –  Ajasja Oct 23 '12 at 12:09
    
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/… –  janitor048 Oct 23 '12 at 12:44
    
@janitor048 Aha. Well, there is Mr. Wizards answer now:) –  Ajasja Oct 23 '12 at 13:10
    
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. –  janitor048 Oct 23 '12 at 14:15

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]

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.