---
title: "Flat"
language: "en"
type: "Symbol"
summary: "Flat is an attribute that can be assigned to a symbol f to indicate that all expressions involving nested functions f should be flattened out. This property is accounted for in pattern matching."
keywords: 
- associative
- attribute
- grouping arguments
- auto flattening
canonical_url: "https://reference.wolfram.com/language/ref/Flat.html"
source: "Wolfram Language Documentation"
related_guides: 
  - 
    title: "Attributes"
    link: "https://reference.wolfram.com/language/guide/Attributes.en.md"
  - 
    title: "Defining Variables and Functions"
    link: "https://reference.wolfram.com/language/guide/VariablesAndFunctions.en.md"
  - 
    title: "Patterns"
    link: "https://reference.wolfram.com/language/guide/Patterns.en.md"
related_functions: 
  - 
    title: "Orderless"
    link: "https://reference.wolfram.com/language/ref/Orderless.en.md"
  - 
    title: "OneIdentity"
    link: "https://reference.wolfram.com/language/ref/OneIdentity.en.md"
related_tutorials: 
  - 
    title: "Flat and Orderless Functions"
    link: "https://reference.wolfram.com/language/tutorial/Patterns.en.md#28368"
  - 
    title: "Attributes"
    link: "https://reference.wolfram.com/language/tutorial/EvaluationOfExpressions.en.md#9508"
  - 
    title: "Patterns and Transformation Rules"
    link: "https://reference.wolfram.com/language/tutorial/PatternsAndTransformationRules.en.md"
---
# Flat

Flat is an attribute that can be assigned to a symbol f to indicate that all expressions involving nested functions f should be flattened out. This property is accounted for in pattern matching.

## Details

* ``Flat`` corresponds to the mathematical property of associativity.

* For a symbol ``f`` with attribute ``Flat``, ``f[f[a, b], f[c]]`` is automatically reduced to ``f[a, b, c]``.

* Functions like ``Plus``, ``Times``, and ``Dot`` are ``Flat``.

* For a ``Flat`` function ``f``, the variables ``x`` and ``y`` in the pattern ``f[x_, y_]`` can correspond to any sequence of arguments.

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

---

## Examples (15)

### Basic Examples (3)

Nested expressions with flat functions are flattened out:

```wl
In[1]:= SetAttributes[f, Flat]

In[2]:= f[f[a, b], f[c, f[d, e]]]

Out[2]= f[a, b, c, d, e]
```

---

``Flat`` implements the notion of associativity:

```wl
In[1]:= Attributes[Plus]

Out[1]= {Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected}

In[2]:= a + (b + c)

Out[2]= a + b + c
```

---

``Flat`` allows the pattern matcher to use associativity:

```wl
In[1]:= a + b + c /. x_ + y_ -> {x, y}

Out[1]= {a, b + c}
```

### Scope (3)

Nested expressions with associative functions are flattened out:

```wl
In[1]:= Attributes[NonCommutativeMultiply]

Out[1]= {Flat, OneIdentity, Protected}

In[2]:= (a**(b**c))**(d)

Out[2]= a**b**c**d
```

---

In pattern matching, ``Flat`` allows sequences of elements to be replaced:

```wl
In[1]:= SetAttributes[f, Flat]

In[2]:= f[a, b, c, d, e] /. f[b, c, d] -> x

Out[2]= f[a, x, e]

In[3]:= f[a, b, c, d, e] /. f[b, c, d] -> f[x, y]

Out[3]= f[a, x, y, e]

In[4]:= f[a, b, c, d, e] /. f[b] -> x

Out[4]= f[a, x, c, d, e]
```

---

For flat and orderless functions, any subset of the arguments may match:

```wl
In[1]:= SetAttributes[f, {Flat, Orderless}]

In[2]:= f[a, b, c, d, e] /. f[d, b] -> x

Out[2]= f[a, c, e, x]
```

### Properties & Relations (5)

Nested expressions with flat functions are automatically flattened:

```wl
In[1]:= f[f[a, b], f[c, f[d, e]]]

Out[1]= f[f[a, b], f[c, f[d, e]]]

In[2]:= Flatten[%]

Out[2]= f[a, b, c, d, e]

In[3]:= SetAttributes[g, Flat]

In[4]:= g[g[a, b], g[c, g[d, e]]]

Out[4]= g[a, b, c, d, e]
```

---

For flat functions, a definition for the two-argument case is normally sufficient:

```wl
In[1]:= SetAttributes[g, {Flat, OneIdentity}]

In[2]:= g[x_, y_] := x + y

In[3]:= g[a, b, c, d]

Out[3]= a + b + c + d
```

---

An expression with a flat head is considered matched in its entirety when any sequence is matched:

```wl
In[1]:= a + b + Sin[a + b] /. a + b -> 5

Out[1]= 5 + Sin[a + b]
```

Compare with:

```wl
In[2]:= {a + b, Sin[a + b]} /. a + b -> 5

Out[2]= {5, Sin[5]}
```

``ReplaceRepeated`` may be helpful in ensuring all occurrences are replaced:

```wl
In[3]:= a + b + Sin[a + b] //. a + b -> 5

Out[3]= 5 + Sin[5]
```

---

When ``Blank`` matches a sequence inside a ``Flat`` function ``f``, it will maintain the head ``f`` :

```wl
In[1]:= SetAttributes[f, Flat]

In[2]:= f[a, b, c] /. f[a, x_] -> {x}

Out[2]= {f[b, c]}

In[3]:= f[a, b, c] /. f[x_] -> {x}

Out[3]= {f[a, b, c]}
```

Sequential patterns like ``BlankSequence`` and ``BlankNullSequence`` are not affected by ``Flat`` :

```wl
In[4]:= f[a, b, c] /. f[a, z__] :> {z}

Out[4]= {b, c}

In[5]:= f[a, b, c] /. f[a, z___] :> {z}

Out[5]= {b, c}
```

---

For a flat function ``f`` that is not ``OneIdentity``, when ``f[x_]`` is compared with ``f[expr]``, the pattern matcher will attempt to bind ``x_`` to ``f[expr]`` first, and only if that fails to ``expr`` :

```wl
In[1]:= SetAttributes[f, Flat]

In[2]:= f[3] /. f[z_] /; IntegerQ[Echo[z]] :> z

>> f[3]

>> 3

Out[2]= 3
```

If the function also has attribute ``OneIdentity``, the first attempt is skipped:

```wl
In[3]:= SetAttributes[fo, {Flat, OneIdentity}]

In[4]:= fo[3] /. fo[z_] /; IntegerQ[Echo[z]] :> z

>> 3

Out[4]= 3
```

### Possible Issues (4)

For flat and orderless functions, pattern matching may have to try a large number of cases:

```wl
In[1]:= SetAttributes[f, {Flat, OneIdentity, Orderless}]

In[2]:= ReplaceList[f[a, b, c, d], f[x_, y_] :> {x, y}]

Out[2]= {{a, f[b, c, d]}, {b, f[a, c, d]}, {c, f[a, b, d]}, {d, f[a, b, c]}, {f[a, b], f[c, d]}, {f[a, c], f[b, d]}, {f[a, d], f[b, c]}, {f[b, c], f[a, d]}, {f[b, d], f[a, c]}, {f[c, d], f[a, b]}, {f[a, b, c], d}, {f[a, b, d], c}, {f[a, c, d], b}, {f[b, c, d], a}}
```

---

``Longest`` can be used to prevent additional matches for shorter subexpressions:

```wl
In[1]:= SetAttributes[f, {Flat, OneIdentity}]

In[2]:= Replace[f[a, b, c, d], f[x_, y__, z_] :> {y}]

Out[2]= {b}

In[3]:= Replace[f[a, b, c, d], f[x_, Longest[y__], z_] :> {y}]

Out[3]= {b, c}
```

---

For a flat function ``f``, the pattern ``f[_]`` matches ``f`` with one or more arguments:

```wl
In[1]:= SetAttributes[f, Flat]

In[2]:= MatchQ[f[1, 2], f[_]]

Out[2]= True
```

``Repeated`` can be used as a pattern that only matches a single argument, even inside a flat function:

```wl
In[3]:= MatchQ[f[1, 2], f[Repeated[_, {1}]]]

Out[3]= False
```

---

Restrictions may behave unexpectedly because ``x_`` matches together with the head of a flat function:

```wl
In[1]:= Replace[a + b + c , Plus[a, x_] :> x]

Out[1]= b + c
```

The following restriction works because ``x_Plus`` matches ``Plus[b, c]`` :

```wl
In[2]:= Replace[a + b + c , Plus[a, x_Plus] :> x]

Out[2]= b + c
```

However, this one will fail because ``x_`` cannot have both head ``Plus`` and ``Symbol`` :

```wl
In[3]:= Replace[a + b + c , Plus[a, x_Symbol] :> x]

Out[3]= a + b + c
```

Using ``BlankSequence`` on the left-hand side produces more consistent results:

```wl
In[4]:= Replace[a + b + c, Plus[a, x__Symbol] :> Plus[x]]

Out[4]= b + c
```

## See Also

* [`Orderless`](https://reference.wolfram.com/language/ref/Orderless.en.md)
* [`OneIdentity`](https://reference.wolfram.com/language/ref/OneIdentity.en.md)

## Tech Notes

* [Flat and Orderless Functions](https://reference.wolfram.com/language/tutorial/Patterns.en.md#28368)
* [Attributes](https://reference.wolfram.com/language/tutorial/EvaluationOfExpressions.en.md#9508)
* [Patterns and Transformation Rules](https://reference.wolfram.com/language/tutorial/PatternsAndTransformationRules.en.md)

## Related Guides

* [`Attributes`](https://reference.wolfram.com/language/guide/Attributes.en.md)
* [Defining Variables and Functions](https://reference.wolfram.com/language/guide/VariablesAndFunctions.en.md)
* [`Patterns`](https://reference.wolfram.com/language/guide/Patterns.en.md)

## Related Links

* [An Elementary Introduction to the Wolfram Language: More about Patterns](https://www.wolfram.com/language/elementary-introduction/41-more-about-patterns.html)
* [NKS\|Online](http://www.wolframscience.com/nks/search/?q=Flat)
* [A New Kind of Science](http://www.wolframscience.com/nks/)

## History

* Introduced in 1988 (1.0)