6
$\begingroup$

I am just beginning to learn about attributes of function in mathematica.

I saw the example "Flat". But there is something I don't get :

SetAttributes[fonction, Flat]

fonction[fonction[x]]

(*fonction[x]*)

fonction[x_] := x^2;

fonction[fonction[x]]

(*$RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of fonction[x].

Hold[fonction[fonction[x]]]*)

Why do I have an error ? Shouldn't it returns me fonction[x]=x^2 because of the flat attribute ?

$\endgroup$
  • 3
    $\begingroup$ Look at the result from just fonction[x], you likely want to add the Attribute OneIdentity. $\endgroup$ – chuy Dec 31 '18 at 17:28
8
$\begingroup$

To understand what has happened, let's just define:

ClearAll[f];
SetAttributes[f, {Flat}];
f[x_] := Hold[x];
f[1]
(*Returns Hold[f[1]]*)

The reason for this extra f in the output is that for a Flat symbol expressions f[x] and f[f[x]] are identical. So, when a pattern-matcher encounters f[1] it treats the expression as f[f[1]] and consequently substitutes f[1], not 1, instead of x in the rhs of the definition. The pattern matcher prefers f[f[1]] over f[1] when matching x_ to allow for matching a sequence of arguments as a whole:

f[1, 2]
(*Returns Hold[f[1, 2]]*)

Here the pattern matcher treated f[1, 2] as f[f[1, 2]] and replaced x by f[1, 2] accordingly.

As chuy has already mentioned in the comments, you can add OneIdentity attribute to a symbol. Then the pattern-mathcer will prefer f[1] over f[f[1]] when matching f[x_] if there is only one argument inside the expression:

ClearAll[f];
SetAttributes[f, {Flat, OneIdentity}];
f[x_] := Hold[x];
f[1]
f[1, 2]
(*Returns Hold[1] and Hold[f[1, 2]]*)

Note, however, that OneIdentity attribute will not save your form recursion when there are more than one argument: f[1, 2] will be matched as f[f[1, 2]], f[1, 2] will be squared, f[1, 2]^2, and the f[1, 2] inside the square will again be matched as f[f[1, 2]]. So, basically, use Flat attribute only for symbols which really stand for some associative operators or you are likely to get into trouble.

ClearAll[f];
SetAttributes[f, {Flat, OneIdentity}];
f[x_] := x^2;
f[1]
f[1, 2]
(*1
  $RecursionLimit::reclim2 bla-bla-bla
  Hold[f[1, 2]^2]
*)
$\endgroup$
4
$\begingroup$

The following example may help:

SetAttributes[f, Flat];
Hold[f[f[x]]] /. HoldPattern[f[x_]] :> x^2

The result is:

Hold[f[f[x]]^2]

To see what's happening, we may run

MatchQ[f[a, b], f[_]]

The result is True. Thus we see that f[a,b] is identified as f[f[a,b]]. This is what the attribute Flat does to a function.

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