# Flat attribute : example I don't understand

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 ? • Look at the result from just fonction[x], you likely want to add the Attribute OneIdentity. – chuy Dec 31 '18 at 17:28 ## 2 Answers To understand what has happened, let's just define: ClearAll[f]; SetAttributes[f, {Flat}]; f[x_] := Hold[x]; f (*Returns Hold[f]*)  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 it treats the expression as f[f] and consequently substitutes f, not 1, instead of x in the rhs of the definition. The pattern matcher prefers f[f] over f 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 over f[f] when matching f[x_] if there is only one argument inside the expression: ClearAll[f]; SetAttributes[f, {Flat, OneIdentity}]; f[x_] := Hold[x]; f f[1, 2] (*Returns Hold 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 f[1, 2] (*1$RecursionLimit::reclim2 bla-bla-bla
Hold[f[1, 2]^2]
*)


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.