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$

4 Answers 4

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$
3
  • $\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$ Commented Sep 20, 2016 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$ Commented Sep 20, 2016 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$ Commented Sep 20, 2016 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$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.