4
$\begingroup$

I would like, as an example, to build a Times-like function. Take the following example

SetAttributes[f, OneIdentity];
f[] := 1;
f[a_] := a;
SetAttributes[f, Flat];
f[a_ + b_, c_] := f[a, c] + f[b, c];

This works perfectly. Notice that had I grouped the Attributes, an infinite recursion would have happened:

SetAttributes[f, {OneIdentity,Flat}];
f[] := 1;
f[a_] := a;
f[a_ + b_, c_] := f[a, c] + f[b, c];

The reason why it happens is explained in several posts (for instance here). However in Mathematica guide for Flat there is written:

The Flat attribute must be assigned before defining any values for a Flat function.

My (first) example does not respect this principle but works. I would like to know if there exist an "official" best practice to implement function with Flat attributes. It would be nice to see the implementation of Times, but of course it must be hard-coded.

$\endgroup$

marked as duplicate by Carl Woll, Henrik Schumacher, MarcoB, Coolwater, Sektor Jun 4 '18 at 21:28

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2
$\begingroup$

Per the linked question, you could do:

SetAttributes[f, {Flat, OneIdentity}];
Verbatim[f][] := 1
Verbatim[f][a_] := a
f[a_ + b_, c_] := f[a, c] + f[b, c]

Then, there are no iteration/recursion errors:

f[]
f[a]
f[x, y]
f[x + y, z]

1

a

f[x, y]

f[x, z] + f[y, z]

$\endgroup$

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