8

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?

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
MaPo
  • 909
  • 4
  • 14

4 Answers4

6

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]

Karsten7
  • 27,448
  • 5
  • 73
  • 134
  • 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? – MaPo Sep 20 '16 at 09:32
  • @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. – Karsten7 Sep 20 '16 at 09:56
  • @MaPo What's the difference between Inactive and HoldForm?. For your case I don't see a practical difference between them. – Karsten7 Sep 20 '16 at 09:58
6
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.

march
  • 23,399
  • 2
  • 44
  • 100
3

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]

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
3

... 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]

kglr
  • 394,356
  • 18
  • 477
  • 896