diff --git a/docs/README.md b/docs/README.md
index 5d0b0555..fc642285 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -42,21 +42,17 @@ Tutorials
* [Complex projects?](./tutorial/complex-projects/)
-### Contributed tutorials
-
-* [Découvrir et utiliser XOD](http://formations.open-elearning.fr/modules/electronique/xod/decouverte/) (French, by [@pepe](https://forum.xod.io/u/pepe/summary))
-
-### Obsolete tutorials
-
-The articles which are going to be superseeded by the crash course above.
-
-1. [Nodes and Links](./tutorial/nodes-and-links/)
-1. [Data Types and Conversions](./tutorial/data-types-and-conversions/)
-1. [Patch Nodes](./tutorial/patch-nodes/)
-
User’s guide
------------
+### Concepts
+
+* [Program structure](./guide/program-structure/)
+* [Data types](./guide/data-types/)
+* [Linking rules](./guide/linking-rules/)
+* [Execution model](./guide/execution-model/)
+* [Variadic nodes](./guide/variadics/)
+
### Making your own nodes
* [Creating nodes for XOD in XOD](./guide/nodes-for-xod-in-xod/)
@@ -65,18 +61,12 @@ User’s guide
* [Creating nodes for XOD in C++](./guide/nodes-for-xod-in-cpp/)
* [Dealing with state in C++](./guide/cpp-state/)
* [Dealing with time in C++](./guide/cpp-time/)
+* [Creating variadic patch nodes](./guide/creating-variadics/)
### Doing things sequentially
* [Simple traffic light example](./guide/simple-traffic-light/)
-### Concepts
-
-* [Program structure](./guide/program-structure/)
-* [Data types](./guide/data-types/)
-* [Linking rules](./guide/linking-rules/)
-* [Execution model](./guide/execution-model/)
-
### Projects and libraries
* [Working on projects](./guide/projects/)
diff --git a/docs/guide/README.md b/docs/guide/README.md
index 9dbc4d4d..dc37bc9f 100644
--- a/docs/guide/README.md
+++ b/docs/guide/README.md
@@ -5,6 +5,14 @@ title: User’s Guide
User’s Guide
============
+## Concepts
+
+* [Program structure](./program-structure/)
+* [Data types](./data-types/)
+* [Linking rules](./linking-rules/)
+* [Execution model](./execution-model/)
+* [Variadic nodes](./variadics/)
+
## Making your own nodes
* [Creating nodes for XOD in XOD](./nodes-for-xod-in-xod/)
@@ -13,18 +21,12 @@ User’s Guide
* [Creating nodes for XOD in C++](./nodes-for-xod-in-cpp/)
* [Dealing with state in C++](./cpp-state/)
* [Dealing with time in C++](./cpp-time/)
+* [Creating variadic patch nodes](./creating-variadics/)
## Doing things sequentially
* [Simple traffic light example](./simple-traffic-light/)
-## Concepts
-
-* [Program structure](./program-structure/)
-* [Data types](./data-types/)
-* [Linking rules](./linking-rules/)
-* [Execution model](./execution-model/)
-
### Projects and libraries
* [Working on projects](./projects/)
diff --git a/docs/guide/creating-variadics/README.md b/docs/guide/creating-variadics/README.md
new file mode 100644
index 00000000..d50841c4
--- /dev/null
+++ b/docs/guide/creating-variadics/README.md
@@ -0,0 +1,84 @@
+---
+title: Creating Variadic Patch Nodes
+---
+
+# Creating Variadic Patch Nodes
+
+Declaring your patch node to be variadic allows its user to add or remove
+similar input pins dynamically. For you, it is a way to avoid creating a list
+of mechanical variations to support the various number of inputs like:
+
+* `foobar`
+* `foobar-2`
+* `foobar-3`
+* …
+* `foobar-8`
+
+Make sure you’re familiar with the [variadic nodes](../variadics/) concept
+and understand how the expansion process works.
+
+## Markers
+
+To make your patch node variadic, you should place a special marker node on it.
+Find the marker node under the `xod/patch-nodes` library. You need
+`variadic-1`, `variadic-2`, or `variadic-3`. The number defines the arity step,
+that is the group size by which the rightmost input pins replicate.
+
+The `variadic-*` node itself does nothing and is stripped out during
+compilation. It exists solely to define indefinite arity support.
+
+## Pin assignments
+
+Whenever you place a variadic node marker, the input pins get roles depending
+on their position relative to each other. Consider a patch node draft with a
+`variadic-2` marker:
+
+
+
+To make the expansion XOD split pins of a variadic patch node into three
+groups.
+
+**Variadic pins** (aka value pins). The rightmost pins get this role. Their
+number equals to the arity step. In the example above they are `V1` and
+`V2`. Values for the inputs on each level are provided by a node user.
+
+**Accumulator pins**. Pins in the middle get this role. Their number equals the
+output number. In the example they are `A1`, `A2`, and `A3`. The user provides
+values only for the top level of the cascade; all other levels get accumulator
+values straightly from output pins of the respective upstream node.
+
+**Shared pins**. The leftmost pins which are not variadic nor accumulator get
+this role. In the example they are `S1` and `S2`. The values are provided by
+the user, and they are delivered to each level in the cascade as is. In many
+cases there will be no shared pins.
+
+Finally, consider a string join node example. We want a node which takes an
+arbitrary number (two or more) of input strings and joins them together
+inserting a delimiter between each. For example, it joins `"foo"`, `"bar"`,
+`"baz"` with delimiter `"; "` into `"foo; bar; baz"`. The delimiter is shared
+between all levels of expansion, so its input terminal goes left. We want the
+arity to increment one by one, so we use the `variadic-1` marker. Finally, a
+possible patch node implementation may look like this:
+
+
+
+
+## Rules
+
+To let XOD properly expand your variadic node when transpiling you must satisfy
+several natural restrictions:
+
+1. There should be no more than a single `variadic-*` marker.
+2. A variadic patch node should have at least one output.
+3. The total number of inputs should be equal or greater than the number of
+ outputs plus the arity step.
+4. The types of accumulator inputs must strictly match the types of the outputs
+ even if an implicit cast is allowed in other cases.
+
+On the patch board, the variadic marker nodes either render usually or in red
+color. The later case tells you’re breaking some rules.
+
+
+
+Hover the node to see the error. You have to resolve all issues or remove the
+marker node to make the program compile successfully.
diff --git a/docs/guide/creating-variadics/assignments.patch.png b/docs/guide/creating-variadics/assignments.patch.png
new file mode 100644
index 00000000..e9a4e8d4
Binary files /dev/null and b/docs/guide/creating-variadics/assignments.patch.png differ
diff --git a/docs/guide/creating-variadics/join.patch.png b/docs/guide/creating-variadics/join.patch.png
new file mode 100644
index 00000000..b14bdeef
Binary files /dev/null and b/docs/guide/creating-variadics/join.patch.png differ
diff --git a/docs/guide/creating-variadics/marker-error.png b/docs/guide/creating-variadics/marker-error.png
new file mode 100644
index 00000000..35addff6
Binary files /dev/null and b/docs/guide/creating-variadics/marker-error.png differ
diff --git a/docs/guide/creating-variadics/samples.xodball b/docs/guide/creating-variadics/samples.xodball
new file mode 100644
index 00000000..7dd0cbdd
--- /dev/null
+++ b/docs/guide/creating-variadics/samples.xodball
@@ -0,0 +1,122 @@
+{
+ "name": "",
+ "patches": {
+ "@/pin-assignments": {
+ "nodes": {
+ "BJWCx5LOf": {
+ "id": "BJWCx5LOf",
+ "label": "V1",
+ "position": {
+ "x": 68,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "Bk_ie9U_G": {
+ "id": "Bk_ie9U_G",
+ "label": "S2",
+ "position": {
+ "x": -102,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-boolean"
+ },
+ "HJmbW9Udz": {
+ "id": "HJmbW9Udz",
+ "position": {
+ "x": 34,
+ "y": -102
+ },
+ "type": "xod/patch-nodes/output-number"
+ },
+ "HkKneq8Oz": {
+ "id": "HkKneq8Oz",
+ "label": "A1",
+ "position": {
+ "x": -68,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "Hy4TgcIdz": {
+ "id": "Hy4TgcIdz",
+ "label": "V2",
+ "position": {
+ "x": 102,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-pulse"
+ },
+ "HyTTlqUOz": {
+ "id": "HyTTlqUOz",
+ "label": "A4",
+ "position": {
+ "x": 34,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "S1rl-5Iuz": {
+ "id": "S1rl-5Iuz",
+ "position": {
+ "x": 0,
+ "y": -102
+ },
+ "type": "xod/patch-nodes/output-boolean"
+ },
+ "SkgjecUOf": {
+ "id": "SkgjecUOf",
+ "label": "S1",
+ "position": {
+ "x": -136,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "SyR2g5LdG": {
+ "id": "SyR2g5LdG",
+ "label": "A2",
+ "position": {
+ "x": -34,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "SySAe9LuM": {
+ "id": "SySAe9LuM",
+ "label": "A3",
+ "position": {
+ "x": 0,
+ "y": -306
+ },
+ "type": "xod/patch-nodes/input-boolean"
+ },
+ "r1n0lq8Oz": {
+ "id": "r1n0lq8Oz",
+ "position": {
+ "x": -68,
+ "y": -102
+ },
+ "type": "xod/patch-nodes/output-string"
+ },
+ "ryCCx9IuG": {
+ "id": "ryCCx9IuG",
+ "position": {
+ "x": -34,
+ "y": -102
+ },
+ "type": "xod/patch-nodes/output-string"
+ },
+ "rydW-cIOf": {
+ "id": "rydW-cIOf",
+ "position": {
+ "x": 204,
+ "y": -204
+ },
+ "type": "xod/patch-nodes/variadic-2"
+ }
+ },
+ "path": "@/pin-assignments"
+ }
+ }
+}
diff --git a/docs/guide/variadics/README.md b/docs/guide/variadics/README.md
new file mode 100644
index 00000000..e5a9df54
--- /dev/null
+++ b/docs/guide/variadics/README.md
@@ -0,0 +1,90 @@
+---
+title: Variadic Nodes
+---
+
+# Variadic Nodes
+
+There are operations which can be applied to an arbitrary number of input
+values. For example, consider the addition operation. Sure, intuitively you
+know how it works for two values, three values, or 42 values:
+
+* 1 + 6 = 7
+* 1 + 6 + 3 = 10
+* 1 + 6 + 3 + …more summands… = someNumber
+
+Other examples of such functions include number multiplication, string
+concatenation or joining, booleans AND’ing or OR’ing, n-th element choice, and
+so on.
+
+To natively support such operations, XOD offers a mechanism called *variadic*
+nodes. The variadic nodes can scale the number of their input pins to accept
+more or fewer values.
+
+In XOD IDE the variadic nodes have a little gripper on the right, and the pins
+which can scale are marked with the ellipsis (⋯) on mouse hover. Drag the right
+border of the node to add as many groups of variadic pins as you need.
+
+
+
+The variadic pins replication count is called *arity level*. By default, the
+arity level for a node is 1. When you add a pin to, for example, the `multiply`
+node, the arity level becomes 2, etc.
+
+## Expansion
+
+A variadic node developer is responsible only for creating a node
+implementation for the first arity level. All subsequent arity level
+implementations are induced automatically by XOD. To achieve it, when
+transpiling the program each particular variadic node passes an *expansion*
+stage in which the system replaces it with a cascade of primitive level-1
+nodes. The replacement principle is better illustrated with an example.
+
+
+
+
+Pro
+Developers with functional programming experience could note the expansion is
+nothing more but a reduce/fold operation. Indeed! XOD variadics work through
+input value list folding.
+
+
+## Bigger arity steps
+
+In the examples above the nodes have exactly one variadic pin. It is not always
+the case. Nodes may have two or three variadic pins. An example of such node is
+[`select`](/libs/xod/core/select/) which have two. Every time you increment an
+arity level of the `select` node it gets two additional input pins.
+
+
+
+Formally speaking, the number of variadic input pins which replicate together
+in a group is called *arity step*.
+
+Expansion process for the nodes with an arity step greater than one looks
+similar.
+
+
+
+## Shared pins
+
+When a variadic node has more inputs than necessary to expand it, the leftmost
+extraneous pins are shared between all nodes in the cascade.
+
+For example, consider textual string join operation which concatenates input
+strings placing a specified delimiter between them (e.g., space or comma). The
+delimiter will be shared between all expanded nodes, so you’ll get the result
+you expect.
+
+
+
+In the example above there was a single shared pin. However, there can be more
+if the author decided the node to be so.
+
+---
+
+As a node user, you’ll rarely meditate on which pins are shared, and which are
+not. The usage pattern should be pretty apparent from the node designation.
+
+Arranging pins properly is a puzzle for the node creator. Read about all rules
+and nuances if you want to [create a new variadic
+node](../creating-variadics/) by yourself.
diff --git a/docs/guide/variadics/expansion.patch.png b/docs/guide/variadics/expansion.patch.png
new file mode 100644
index 00000000..8ad6cd36
Binary files /dev/null and b/docs/guide/variadics/expansion.patch.png differ
diff --git a/docs/guide/variadics/join-expansion.patch.png b/docs/guide/variadics/join-expansion.patch.png
new file mode 100644
index 00000000..9830c70e
Binary files /dev/null and b/docs/guide/variadics/join-expansion.patch.png differ
diff --git a/docs/guide/variadics/overview.patch.png b/docs/guide/variadics/overview.patch.png
new file mode 100644
index 00000000..fcb947e0
Binary files /dev/null and b/docs/guide/variadics/overview.patch.png differ
diff --git a/docs/guide/variadics/samples.xodball b/docs/guide/variadics/samples.xodball
new file mode 100644
index 00000000..11b01e3d
--- /dev/null
+++ b/docs/guide/variadics/samples.xodball
@@ -0,0 +1,874 @@
+{
+ "name": "",
+ "patches": {
+ "@/01-overview": {
+ "comments": {
+ "Byl9xSNdM": {
+ "content": "As many pins as necessary",
+ "id": "Byl9xSNdM",
+ "position": {
+ "x": 68,
+ "y": -204
+ },
+ "size": {
+ "height": 51,
+ "width": 136
+ }
+ },
+ "HkJ3lrVuf": {
+ "content": "Works for any data types",
+ "id": "HkJ3lrVuf",
+ "position": {
+ "x": 68,
+ "y": 102
+ },
+ "size": {
+ "height": 51,
+ "width": 238
+ }
+ },
+ "r1XKgBN_f": {
+ "content": "The same `add` node\n🔻🔻🔻",
+ "id": "r1XKgBN_f",
+ "position": {
+ "x": -374,
+ "y": -204
+ },
+ "size": {
+ "height": 51,
+ "width": 170
+ }
+ }
+ },
+ "nodes": {
+ "B1HIeBNdf": {
+ "arityLevel": 4,
+ "id": "B1HIeBNdf",
+ "position": {
+ "x": -374,
+ "y": 204
+ },
+ "type": "xod/core/add"
+ },
+ "B1TMgSEuf": {
+ "arityLevel": 3,
+ "id": "B1TMgSEuf",
+ "position": {
+ "x": -374,
+ "y": 102
+ },
+ "type": "xod/core/add"
+ },
+ "BkUGlS4Of": {
+ "arityLevel": 9,
+ "id": "BkUGlS4Of",
+ "position": {
+ "x": -34,
+ "y": -102
+ },
+ "type": "xod/core/multiply"
+ },
+ "ByC31SNuM": {
+ "id": "ByC31SNuM",
+ "position": {
+ "x": -374,
+ "y": -102
+ },
+ "type": "xod/core/add"
+ },
+ "H1j9fBEdz": {
+ "id": "H1j9fBEdz",
+ "position": {
+ "x": -34,
+ "y": 102
+ },
+ "type": "xod/core/or"
+ },
+ "r1BggH4uf": {
+ "arityLevel": 2,
+ "id": "r1BggH4uf",
+ "position": {
+ "x": -374,
+ "y": 0
+ },
+ "type": "xod/core/add"
+ },
+ "rJmjfrVuf": {
+ "arityLevel": 9,
+ "id": "rJmjfrVuf",
+ "position": {
+ "x": -34,
+ "y": 204
+ },
+ "type": "xod/core/or"
+ },
+ "ry3ZgB4uG": {
+ "id": "ry3ZgB4uG",
+ "position": {
+ "x": -34,
+ "y": -204
+ },
+ "type": "xod/core/multiply"
+ }
+ },
+ "path": "@/01-overview"
+ },
+ "@/02-expansion": {
+ "links": {
+ "B1l-7SNdz": {
+ "id": "B1l-7SNdz",
+ "input": {
+ "nodeId": "S16J7BNuz",
+ "pinKey": "HkqmLAOrD1W"
+ },
+ "output": {
+ "nodeId": "SkaxXrVdM",
+ "pinKey": "__out__"
+ }
+ },
+ "B1qemrVdM": {
+ "id": "B1qemrVdM",
+ "input": {
+ "nodeId": "rk8ymBEuf",
+ "pinKey": "BJnQUR_BwyZ"
+ },
+ "output": {
+ "nodeId": "B1_l7rEuM",
+ "pinKey": "__out__"
+ }
+ },
+ "BykWmBV_G": {
+ "id": "BykWmBV_G",
+ "input": {
+ "nodeId": "SJke7rV_G",
+ "pinKey": "HkqmLAOrD1W"
+ },
+ "output": {
+ "nodeId": "SkeTl7HVuG",
+ "pinKey": "__out__"
+ }
+ },
+ "H14xmBV_G": {
+ "id": "H14xmBV_G",
+ "input": {
+ "nodeId": "S16J7BNuz",
+ "pinKey": "BJnQUR_BwyZ"
+ },
+ "output": {
+ "nodeId": "B1tkXBNdG",
+ "pinKey": "SyomIRurDJ-"
+ }
+ },
+ "HJmZQHNdM": {
+ "id": "HJmZQHNdM",
+ "input": {
+ "nodeId": "rk8ymBEuf",
+ "pinKey": "HkqmLAOrD1W"
+ },
+ "output": {
+ "nodeId": "SynxmSVdG",
+ "pinKey": "__out__"
+ }
+ },
+ "HyzZQH4dz": {
+ "id": "HyzZQH4dz",
+ "input": {
+ "nodeId": "B1tkXBNdG",
+ "pinKey": "HkqmLAOrD1W"
+ },
+ "output": {
+ "nodeId": "H1e2gXBEuM",
+ "pinKey": "__out__"
+ }
+ },
+ "SyMl7HNuM": {
+ "id": "SyMl7HNuM",
+ "input": {
+ "nodeId": "B1tkXBNdG",
+ "pinKey": "BJnQUR_BwyZ"
+ },
+ "output": {
+ "nodeId": "rk8ymBEuf",
+ "pinKey": "SyomIRurDJ-"
+ }
+ },
+ "SyYZQBEOz": {
+ "id": "SyYZQBEOz",
+ "input": {
+ "nodeId": "Byv-7BNuG",
+ "pinKey": "__in__"
+ },
+ "output": {
+ "nodeId": "SJke7rV_G",
+ "pinKey": "SyomIRurDJ-"
+ }
+ },
+ "rkHemHVuM": {
+ "id": "rkHemHVuM",
+ "input": {
+ "nodeId": "SJke7rV_G",
+ "pinKey": "BJnQUR_BwyZ"
+ },
+ "output": {
+ "nodeId": "S16J7BNuz",
+ "pinKey": "SyomIRurDJ-"
+ }
+ }
+ },
+ "nodes": {
+ "B1_l7rEuM": {
+ "id": "B1_l7rEuM",
+ "position": {
+ "x": 34,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "B1tkXBNdG": {
+ "id": "B1tkXBNdG",
+ "position": {
+ "x": 68,
+ "y": 204
+ },
+ "type": "xod/core/add"
+ },
+ "Byv-7BNuG": {
+ "id": "Byv-7BNuG",
+ "position": {
+ "x": 136,
+ "y": 510
+ },
+ "type": "xod/patch-nodes/output-number"
+ },
+ "H1e2gXBEuM": {
+ "id": "H1e2gXBEuM",
+ "position": {
+ "x": 102,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "S16J7BNuz": {
+ "id": "S16J7BNuz",
+ "position": {
+ "x": 102,
+ "y": 306
+ },
+ "type": "xod/core/add"
+ },
+ "SJke7rV_G": {
+ "id": "SJke7rV_G",
+ "position": {
+ "x": 136,
+ "y": 408
+ },
+ "type": "xod/core/add"
+ },
+ "SkaxXrVdM": {
+ "id": "SkaxXrVdM",
+ "position": {
+ "x": 136,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "SkeTl7HVuG": {
+ "id": "SkeTl7HVuG",
+ "position": {
+ "x": 170,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "SynxmSVdG": {
+ "id": "SynxmSVdG",
+ "position": {
+ "x": 68,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "rk8ymBEuf": {
+ "id": "rk8ymBEuf",
+ "position": {
+ "x": 34,
+ "y": 102
+ },
+ "type": "xod/core/add"
+ }
+ },
+ "path": "@/02-expansion"
+ },
+ "@/03-select-a2": {
+ "comments": {
+ "SJeRmH4uz": {
+ "content": "`select` inputs grow in pairs",
+ "id": "SJeRmH4uz",
+ "position": {
+ "x": 204,
+ "y": 102
+ },
+ "size": {
+ "height": 51,
+ "width": 238
+ }
+ }
+ },
+ "nodes": {
+ "B1Y3mBNOM": {
+ "id": "B1Y3mBNOM",
+ "position": {
+ "x": 34,
+ "y": 102
+ },
+ "type": "xod/core/select"
+ },
+ "S1Bp7B4uG": {
+ "arityLevel": 4,
+ "id": "S1Bp7B4uG",
+ "position": {
+ "x": 34,
+ "y": 408
+ },
+ "type": "xod/core/select"
+ },
+ "SJ3nQHEdG": {
+ "arityLevel": 2,
+ "id": "SJ3nQHEdG",
+ "position": {
+ "x": 34,
+ "y": 204
+ },
+ "type": "xod/core/select"
+ },
+ "r1eTXH4_M": {
+ "arityLevel": 3,
+ "id": "r1eTXH4_M",
+ "position": {
+ "x": 34,
+ "y": 306
+ },
+ "type": "xod/core/select"
+ }
+ },
+ "path": "@/03-select-a2"
+ },
+ "@/04-expansion-a2": {
+ "links": {
+ "B14MzSNOf": {
+ "id": "B14MzSNOf",
+ "input": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "S10qrR6UZ"
+ },
+ "output": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "S1yaHC6UW"
+ }
+ },
+ "BkHGzSNOf": {
+ "id": "BkHGzSNOf",
+ "input": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "rkmiHCaIZ"
+ },
+ "output": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "rkWHDAW_f"
+ }
+ },
+ "BkPSfSVdM": {
+ "id": "BkPSfSVdM",
+ "input": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "rJUjrCTUb"
+ },
+ "output": {
+ "nodeId": "HJlTQfHVOz",
+ "pinKey": "__out__"
+ }
+ },
+ "BkQMGH4uG": {
+ "id": "BkQMGH4uG",
+ "input": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "rkmiHCaIZ"
+ },
+ "output": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "rkWHDAW_f"
+ }
+ },
+ "ByArzB4uf": {
+ "id": "ByArzB4uf",
+ "input": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "rygjH06LW"
+ },
+ "output": {
+ "nodeId": "BygNfHNuz",
+ "pinKey": "__out__"
+ }
+ },
+ "H1iHfHEdz": {
+ "id": "H1iHfHEdz",
+ "input": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "rygjH06LW"
+ },
+ "output": {
+ "nodeId": "BJJ4zSVdG",
+ "pinKey": "__out__"
+ }
+ },
+ "HJHSMSNOG": {
+ "id": "HJHSMSNOG",
+ "input": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "rygjH06LW"
+ },
+ "output": {
+ "nodeId": "rkaQfrEuG",
+ "pinKey": "__out__"
+ }
+ },
+ "HJKrfBEuf": {
+ "id": "HJKrfBEuf",
+ "input": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "rkmiHCaIZ"
+ },
+ "output": {
+ "nodeId": "BJH7fSNdf",
+ "pinKey": "__out__"
+ }
+ },
+ "HkdHMH4Of": {
+ "id": "HkdHMH4Of",
+ "input": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "S10qrR6UZ"
+ },
+ "output": {
+ "nodeId": "SyazMr4uM",
+ "pinKey": "__out__"
+ }
+ },
+ "HycIGSNOG": {
+ "id": "HycIGSNOG",
+ "input": {
+ "nodeId": "Hy_LMSEOf",
+ "pinKey": "__in__"
+ },
+ "output": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "S1yaHC6UW"
+ }
+ },
+ "SJezzBN_f": {
+ "id": "SJezzBN_f",
+ "input": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "S10qrR6UZ"
+ },
+ "output": {
+ "nodeId": "SJWZzHVuf",
+ "pinKey": "S1yaHC6UW"
+ }
+ },
+ "SyhSGB4_f": {
+ "id": "SyhSGB4_f",
+ "input": {
+ "nodeId": "ryIbfHEdM",
+ "pinKey": "rJUjrCTUb"
+ },
+ "output": {
+ "nodeId": "rklkNMHN_M",
+ "pinKey": "__out__"
+ }
+ },
+ "rJyvfB4dM": {
+ "id": "rJyvfB4dM",
+ "input": {
+ "nodeId": "rk6IMrEdf",
+ "pinKey": "__in__"
+ },
+ "output": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "rkWHDAW_f"
+ }
+ },
+ "rklLzrEdM": {
+ "id": "rklLzrEdM",
+ "input": {
+ "nodeId": "r1Y-MSEOG",
+ "pinKey": "rJUjrCTUb"
+ },
+ "output": {
+ "nodeId": "SyexEMrV_f",
+ "pinKey": "__out__"
+ }
+ }
+ },
+ "nodes": {
+ "BJH7fSNdf": {
+ "id": "BJH7fSNdf",
+ "label": "S1",
+ "position": {
+ "x": 68,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-pulse"
+ },
+ "BJJ4zSVdG": {
+ "id": "BJJ4zSVdG",
+ "label": "X3",
+ "position": {
+ "x": 170,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "BygNfHNuz": {
+ "id": "BygNfHNuz",
+ "label": "X4",
+ "position": {
+ "x": 238,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "HJlTQfHVOz": {
+ "id": "HJlTQfHVOz",
+ "label": "S2",
+ "position": {
+ "x": 136,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-pulse"
+ },
+ "Hy_LMSEOf": {
+ "id": "Hy_LMSEOf",
+ "position": {
+ "x": 170,
+ "y": 408
+ },
+ "type": "xod/patch-nodes/output-number"
+ },
+ "SJWZzHVuf": {
+ "id": "SJWZzHVuf",
+ "position": {
+ "x": 34,
+ "y": 102
+ },
+ "type": "xod/core/select"
+ },
+ "SyazMr4uM": {
+ "id": "SyazMr4uM",
+ "label": "X1",
+ "position": {
+ "x": 34,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "SyexEMrV_f": {
+ "id": "SyexEMrV_f",
+ "label": "S4",
+ "position": {
+ "x": 272,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-pulse"
+ },
+ "r1Y-MSEOG": {
+ "id": "r1Y-MSEOG",
+ "position": {
+ "x": 170,
+ "y": 306
+ },
+ "type": "xod/core/select"
+ },
+ "rk6IMrEdf": {
+ "id": "rk6IMrEdf",
+ "position": {
+ "x": 204,
+ "y": 408
+ },
+ "type": "xod/patch-nodes/output-pulse"
+ },
+ "rkaQfrEuG": {
+ "id": "rkaQfrEuG",
+ "label": "X2",
+ "position": {
+ "x": 102,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-number"
+ },
+ "rklkNMHN_M": {
+ "id": "rklkNMHN_M",
+ "label": "S3",
+ "position": {
+ "x": 204,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-pulse"
+ },
+ "ryIbfHEdM": {
+ "id": "ryIbfHEdM",
+ "position": {
+ "x": 102,
+ "y": 204
+ },
+ "type": "xod/core/select"
+ }
+ },
+ "path": "@/04-expansion-a2"
+ },
+ "@/05-join-expansion": {
+ "links": {
+ "B18ShHE_M": {
+ "id": "B18ShHE_M",
+ "input": {
+ "nodeId": "HkyX2r4_M",
+ "pinKey": "rJJHNrVuM"
+ },
+ "output": {
+ "nodeId": "rJeonVHV_f",
+ "pinKey": "__out__"
+ }
+ },
+ "BkVrnBN_z": {
+ "id": "BkVrnBN_z",
+ "input": {
+ "nodeId": "By9G2BNdf",
+ "pinKey": "rJJHNrVuM"
+ },
+ "output": {
+ "nodeId": "rJonESV_M",
+ "pinKey": "__out__"
+ }
+ },
+ "H1sN3rN_f": {
+ "id": "H1sN3rN_f",
+ "input": {
+ "nodeId": "rkMXnBNuf",
+ "pinKey": "rJGQNB4df"
+ },
+ "output": {
+ "nodeId": "rywcVS4_f",
+ "pinKey": "__out__"
+ }
+ },
+ "HJYEhBVOG": {
+ "id": "HJYEhBVOG",
+ "input": {
+ "nodeId": "HkyX2r4_M",
+ "pinKey": "rJGQNB4df"
+ },
+ "output": {
+ "nodeId": "rywcVS4_f",
+ "pinKey": "__out__"
+ }
+ },
+ "HygS2H4_z": {
+ "id": "HygS2H4_z",
+ "input": {
+ "nodeId": "S17mnrE_G",
+ "pinKey": "HynENHNOz"
+ },
+ "output": {
+ "nodeId": "rkMXnBNuf",
+ "pinKey": "HJrBNr4dG"
+ }
+ },
+ "HyzS2rV_f": {
+ "id": "HyzS2rV_f",
+ "input": {
+ "nodeId": "BJrJHSEOf",
+ "pinKey": "__in__"
+ },
+ "output": {
+ "nodeId": "S17mnrE_G",
+ "pinKey": "HJrBNr4dG"
+ }
+ },
+ "S1hV2SNdz": {
+ "id": "S1hV2SNdz",
+ "input": {
+ "nodeId": "S17mnrE_G",
+ "pinKey": "rJGQNB4df"
+ },
+ "output": {
+ "nodeId": "rywcVS4_f",
+ "pinKey": "__out__"
+ }
+ },
+ "SktS2BEOG": {
+ "id": "SktS2BEOG",
+ "input": {
+ "nodeId": "rkMXnBNuf",
+ "pinKey": "rJJHNrVuM"
+ },
+ "output": {
+ "nodeId": "SyanESVOf",
+ "pinKey": "__out__"
+ }
+ },
+ "SkvE2HVOM": {
+ "id": "SkvE2HVOM",
+ "input": {
+ "nodeId": "By9G2BNdf",
+ "pinKey": "rJGQNB4df"
+ },
+ "output": {
+ "nodeId": "rywcVS4_f",
+ "pinKey": "__out__"
+ }
+ },
+ "Sy6ShBEOz": {
+ "id": "Sy6ShBEOz",
+ "input": {
+ "nodeId": "S17mnrE_G",
+ "pinKey": "rJJHNrVuM"
+ },
+ "output": {
+ "nodeId": "rycC4SEdz",
+ "pinKey": "__out__"
+ }
+ },
+ "rk7r3HEdf": {
+ "id": "rk7r3HEdf",
+ "input": {
+ "nodeId": "By9G2BNdf",
+ "pinKey": "HynENHNOz"
+ },
+ "output": {
+ "nodeId": "Hk72NH4Of",
+ "pinKey": "__out__"
+ }
+ },
+ "rkirnS4_M": {
+ "id": "rkirnS4_M",
+ "input": {
+ "nodeId": "rkMXnBNuf",
+ "pinKey": "HynENHNOz"
+ },
+ "output": {
+ "nodeId": "HkyX2r4_M",
+ "pinKey": "HJrBNr4dG"
+ }
+ },
+ "ryyB2rEOG": {
+ "id": "ryyB2rEOG",
+ "input": {
+ "nodeId": "HkyX2r4_M",
+ "pinKey": "HynENHNOz"
+ },
+ "output": {
+ "nodeId": "By9G2BNdf",
+ "pinKey": "HJrBNr4dG"
+ }
+ }
+ },
+ "nodes": {
+ "BJrJHSEOf": {
+ "id": "BJrJHSEOf",
+ "position": {
+ "x": 136,
+ "y": 510
+ },
+ "type": "xod/patch-nodes/output-string"
+ },
+ "By9G2BNdf": {
+ "id": "By9G2BNdf",
+ "position": {
+ "x": 136,
+ "y": 102
+ },
+ "type": "xod/core/join"
+ },
+ "Hk72NH4Of": {
+ "id": "Hk72NH4Of",
+ "label": "S1",
+ "position": {
+ "x": 170,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "HkyX2r4_M": {
+ "id": "HkyX2r4_M",
+ "position": {
+ "x": 136,
+ "y": 204
+ },
+ "type": "xod/core/join"
+ },
+ "S17mnrE_G": {
+ "id": "S17mnrE_G",
+ "position": {
+ "x": 136,
+ "y": 408
+ },
+ "type": "xod/core/join"
+ },
+ "SyanESVOf": {
+ "id": "SyanESVOf",
+ "label": "S4",
+ "position": {
+ "x": 374,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "rJeonVHV_f": {
+ "id": "rJeonVHV_f",
+ "label": "S3",
+ "position": {
+ "x": 306,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "rJonESV_M": {
+ "id": "rJonESV_M",
+ "label": "S2",
+ "position": {
+ "x": 238,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "rkMXnBNuf": {
+ "id": "rkMXnBNuf",
+ "position": {
+ "x": 136,
+ "y": 306
+ },
+ "type": "xod/core/join"
+ },
+ "rycC4SEdz": {
+ "id": "rycC4SEdz",
+ "label": "S5",
+ "position": {
+ "x": 442,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ },
+ "rywcVS4_f": {
+ "id": "rywcVS4_f",
+ "label": "D",
+ "position": {
+ "x": 0,
+ "y": 0
+ },
+ "type": "xod/patch-nodes/input-string"
+ }
+ },
+ "path": "@/05-join-expansion"
+ }
+ }
+}
diff --git a/docs/guide/variadics/select-a2-expansion.patch.png b/docs/guide/variadics/select-a2-expansion.patch.png
new file mode 100644
index 00000000..c2a9ab52
Binary files /dev/null and b/docs/guide/variadics/select-a2-expansion.patch.png differ
diff --git a/docs/guide/variadics/select-a2.patch.png b/docs/guide/variadics/select-a2.patch.png
new file mode 100644
index 00000000..4328f498
Binary files /dev/null and b/docs/guide/variadics/select-a2.patch.png differ
diff --git a/docs/tutorial/README.md b/docs/tutorial/README.md
index bdb29f88..33f678b4 100644
--- a/docs/tutorial/README.md
+++ b/docs/tutorial/README.md
@@ -38,15 +38,3 @@ Tutorials
28. [String concatenation](./28-string-concat/)
* [Complex projects?](./complex-projects/)
-
-### Contributed tutorials
-
-* [Découvrir et utiliser XOD](http://formations.open-elearning.fr/modules/electronique/xod/decouverte/) (French, by [@pepe](https://forum.xod.io/u/pepe/summary))
-
-### Obsolete tutorials
-
-The articles which are going to be superseeded by the crash course above.
-
-1. [Nodes and Links](./nodes-and-links/)
-1. [Data Types and Conversions](./data-types-and-conversions/)
-1. [Patch Nodes](./patch-nodes/)