8
$\begingroup$

I would like to define an distributive function like this:

com[x__Plus, y_] := c @@@ Distribute[c[x, y]];

which is Ok. I know that it's possible to define it simply exploiting the fact that Plus is Flat, but consider what I wrote just as a toy model of a more refined example.

Here the point is that I cannot write

com[x__Plus, y_] :=  Distribute[com[x, y]];

since I would have an infinite recursion. But is there a way to obtain the result I got in the first example without using that trick, just with Hold and ReleaseHold commands?

$\endgroup$
6
$\begingroup$

With

com[x__Plus, y_] := Distribute[Inactive[com][x, y]] // Activate

you get, for example,

com[Plus[a, b], c]

com[a, c] + com[b, c]

$\endgroup$
  • $\begingroup$ I noticed that another solution can be `com[x__Plus, y_] := Distribute[HoldForm[com][x, y]] '. Do you have any suggestion when one has to choose between these two ways? $\endgroup$ – MaPo Sep 20 '16 at 9:32
  • $\begingroup$ @MaPo When using com[x__Plus, y_] := Distribute[HoldForm[com][x, y]] the output is displayed as com[a, c] + com[b, c], but its FullForm is Plus[HoldForm[com][a,c],HoldForm[com][b,c]]. One can get rid of these HoldForms (assuming that's wanted) using ReleaseHold. I think you should add the HoldForm version as a self-answer. $\endgroup$ – Karsten 7. Sep 20 '16 at 9:56
  • $\begingroup$ @MaPo What's the difference between Inactive and HoldForm?. For your case I don't see a practical difference between them. $\endgroup$ – Karsten 7. Sep 20 '16 at 9:58
6
$\begingroup$
com[x__Plus, y_] := Block[{com}, Distribute[com[x, y]]]

This Blocks the evaluation of com until after Distribute has done its work by momentarily treating com as a variable local to the Block scoping construct and hence momentarily losing all of its definitions and Attributes.

$\endgroup$
3
$\begingroup$

I think you can just use Unevaluated here:

com[x__Plus, y_] := Distribute[Unevaluated @ com[x, y]]

Examples:

com[a+b, c]
com[a+b, c+d+e, f]

com[a, c] + com[b, c]

com[a, c, f] + com[a, d, f] + com[a, e, f] + com[b, c, f] + com[b, d, f] + com[b, e, f]

$\endgroup$
3
$\begingroup$

... just with Hold and ReleaseHold commands

ClearAll[com]
com[x__Plus, y_] := ReleaseHold @ Distribute[Hold[com][x, y]]

com[a + b, c]

com[a, c] + com[b, c]

com[a + b + c, d + e, f]

com[a, d, f] + com[a, e, f] + com[b, d, f] + com[b, e, f] + com[c, d, f] + com[c, e, f]

$\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.