Thread¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
Thread[f[args]]
"threads" f over any lists that appear in args.
Thread[f[args], h]
threads f over any objects with head h that appear in args.
Thread[f[args], h, n]
threads f over objects with head h that appear in the first n args.
Functions with attribute Listable are automatically threaded over
lists. All the elements in the specified args whose heads are h must
be of the same length. Arguments that do not have head h are copied
as many times as there are elements in the arguments that do have
head h.
Thread specifies argument positions using the standard sequence
specification:
All all elements
None no elements
n elements 1 through n
-n last n elements
{n} element n only
{m, n} elements m through n inclusive
{m, n, s} elements m through n in steps of s
Examples¶
All examples below are verified against the current Mathilda build.
In[1]:= Thread[f[{a, b, c}]]
Out[1]= {f[a], f[b], f[c]}
In[2]:= Thread[f[{a, b, c}, x]]
Out[2]= {f[a, x], f[b, x], f[c, x]}
In[3]:= Thread[f[{a, b, c}, {x, y, z}]]
Out[3]= {f[a, x], f[b, y], f[c, z]}
In[4]:= Thread[{a, b, c} == {x, y, z}]
Out[4]= {a == x, b == y, c == z}
In[5]:= Thread[Log[x == y], Equal]
Out[5]= Log[x] == Log[y]
In[6]:= Thread[f[{a, b}, {r, s}, {u, v}, {x, y}], List]
Out[6]= {f[a, r, u, x], f[b, s, v, y]}
In[7]:= Thread[f[{a, b}, {r, s}, {u, v}, {x, y}], List, None]
Out[7]= f[{a, b}, {r, s}, {u, v}, {x, y}]
In[8]:= Thread[f[{a, b}, {r, s}, {u, v}, {x, y}], List, 2]
Out[8]= {f[a, r, {u, v}, {x, y}], f[b, s, {u, v}, {x, y}]}
Implementation notes¶
Algorithm. builtin_thread distributes a function over equal-length lists:
Thread[f[{a,b},{c,d}]] → {f[a,c], f[b,d]}. Arguments are (expr, h, n): h
is the threading head (default List) and n is a position spec selecting which
of f's K arguments take part. thread_parse_spec turns the spec into a
boolean mask of length K, handling All/None, an integer (first/last |n|
positions), and {n} / {m,n} / {m,n,s} index ranges with negative-from-end
indexing.
It then scans the masked, h-headed arguments to determine the common threading
length L; if two such arguments have different lengths the expression is
returned unchanged (Mathematica issues a message here, which Mathilda elides).
For each k in 0..L-1 it builds f[...] taking element k from every masked
threadable argument and copying all other arguments verbatim, then wraps the L
calls under h[...] and runs evaluate() so f's attributes (Listable,
OneIdentity, ...) apply. Atoms and the no-threadable-argument case return a copy
of expr.
Data structures. Expr-tree only; a bool* mask of length K, plus a
wrap_args array of the L per-slice calls. The threading head uses the interned
List symbol (expr_ref) so expr_eq pointer comparisons work.
Protected.- Functions with attribute
Listableare automatically threaded over lists. - All the elements in the specified args whose heads are
hmust be of the same length; otherwise the expression is returned unchanged. - Arguments that do not have head
hare copied as many times as there are elements in the arguments that do have headh. - The position specifier
nuses the standard sequence specification:
Attributes: Protected.
Implementation status¶
Stable — documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
References¶
- Source:
src/funcprog.c - Specification:
docs/spec/builtins/functional-programming.md
Notes & additional examples¶
Worked examples¶
Notes¶
Thread[f[args]] distributes f over any lists in args, pairing them
positionally; non-list arguments are broadcast to every element. This is the
idiomatic way to build a rule list from parallel name/value lists
(Thread[vars -> vals]) or a system of equations from two vectors
(Thread[Equal[lhs, rhs]]). All list arguments must have the same length.
Thread[f[args], h] threads over a custom head h instead of List.