diff options
Diffstat (limited to 'devdocs/elisp/association-lists.html')
| -rw-r--r-- | devdocs/elisp/association-lists.html | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/devdocs/elisp/association-lists.html b/devdocs/elisp/association-lists.html new file mode 100644 index 00000000..1284aea2 --- /dev/null +++ b/devdocs/elisp/association-lists.html @@ -0,0 +1,148 @@ + <h3 class="section">Association Lists</h3> <p>An <em>association list</em>, or <em>alist</em> for short, records a mapping from keys to values. It is a list of cons cells called <em>associations</em>: the <small>CAR</small> of each cons cell is the <em>key</em>, and the <small>CDR</small> is the <em>associated value</em>.<a id="DOCF6" href="#FOOT6"><sup>6</sup></a> </p> <p>Here is an example of an alist. The key <code>pine</code> is associated with the value <code>cones</code>; the key <code>oak</code> is associated with <code>acorns</code>; and the key <code>maple</code> is associated with <code>seeds</code>. </p> <div class="example"> <pre class="example">((pine . cones) + (oak . acorns) + (maple . seeds)) +</pre> +</div> <p>Both the values and the keys in an alist may be any Lisp objects. For example, in the following alist, the symbol <code>a</code> is associated with the number <code>1</code>, and the string <code>"b"</code> is associated with the <em>list</em> <code>(2 3)</code>, which is the <small>CDR</small> of the alist element: </p> <div class="example"> <pre class="example">((a . 1) ("b" 2 3)) +</pre> +</div> <p>Sometimes it is better to design an alist to store the associated value in the <small>CAR</small> of the <small>CDR</small> of the element. Here is an example of such an alist: </p> <div class="example"> <pre class="example">((rose red) (lily white) (buttercup yellow)) +</pre> +</div> <p>Here we regard <code>red</code> as the value associated with <code>rose</code>. One advantage of this kind of alist is that you can store other related information—even a list of other items—in the <small>CDR</small> of the <small>CDR</small>. One disadvantage is that you cannot use <code>rassq</code> (see below) to find the element containing a given value. When neither of these considerations is important, the choice is a matter of taste, as long as you are consistent about it for any given alist. </p> <p>The same alist shown above could be regarded as having the associated value in the <small>CDR</small> of the element; the value associated with <code>rose</code> would be the list <code>(red)</code>. </p> <p>Association lists are often used to record information that you might otherwise keep on a stack, since new associations may be added easily to the front of the list. When searching an association list for an association with a given key, the first one found is returned, if there is more than one. </p> <p>In Emacs Lisp, it is <em>not</em> an error if an element of an association list is not a cons cell. The alist search functions simply ignore such elements. Many other versions of Lisp signal errors in such cases. </p> <p>Note that property lists are similar to association lists in several respects. A property list behaves like an association list in which each key can occur only once. See <a href="property-lists">Property Lists</a>, for a comparison of property lists and association lists. </p> <dl> <dt id="assoc">Function: <strong>assoc</strong> <em>key alist &optional testfn</em> +</dt> <dd> +<p>This function returns the first association for <var>key</var> in <var>alist</var>, comparing <var>key</var> against the alist elements using <var>testfn</var> if it is a function, and <code>equal</code> otherwise (see <a href="equality-predicates">Equality Predicates</a>). If <var>testfn</var> is a function, it is called with two arguments: the <small>CAR</small> of an element from <var>alist</var> and <var>key</var>. The function returns <code>nil</code> if no association in <var>alist</var> has a <small>CAR</small> equal to <var>key</var>, as tested by <var>testfn</var>. For example: </p> <div class="example"> <pre class="example">(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) + ⇒ ((pine . cones) (oak . acorns) (maple . seeds)) +(assoc 'oak trees) + ⇒ (oak . acorns) +(cdr (assoc 'oak trees)) + ⇒ acorns +(assoc 'birch trees) + ⇒ nil +</pre> +</div> <p>Here is another example, in which the keys and values are not symbols: </p> <div class="example"> <pre class="example">(setq needles-per-cluster + '((2 "Austrian Pine" "Red Pine") + (3 "Pitch Pine") + (5 "White Pine"))) + +(cdr (assoc 3 needles-per-cluster)) + ⇒ ("Pitch Pine") +(cdr (assoc 2 needles-per-cluster)) + ⇒ ("Austrian Pine" "Red Pine") +</pre> +</div> </dd> +</dl> <p>The function <code>assoc-string</code> is much like <code>assoc</code> except that it ignores certain differences between strings. See <a href="text-comparison">Text Comparison</a>. </p> <dl> <dt id="rassoc">Function: <strong>rassoc</strong> <em>value alist</em> +</dt> <dd> +<p>This function returns the first association with value <var>value</var> in <var>alist</var>. It returns <code>nil</code> if no association in <var>alist</var> has a <small>CDR</small> <code>equal</code> to <var>value</var>. </p> <p><code>rassoc</code> is like <code>assoc</code> except that it compares the <small>CDR</small> of each <var>alist</var> association instead of the <small>CAR</small>. You can think of this as reverse <code>assoc</code>, finding the key for a given value. </p> +</dd> +</dl> <dl> <dt id="assq">Function: <strong>assq</strong> <em>key alist</em> +</dt> <dd> +<p>This function is like <code>assoc</code> in that it returns the first association for <var>key</var> in <var>alist</var>, but it makes the comparison using <code>eq</code>. <code>assq</code> returns <code>nil</code> if no association in <var>alist</var> has a <small>CAR</small> <code>eq</code> to <var>key</var>. This function is used more often than <code>assoc</code>, since <code>eq</code> is faster than <code>equal</code> and most alists use symbols as keys. See <a href="equality-predicates">Equality Predicates</a>. </p> <div class="example"> <pre class="example">(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) + ⇒ ((pine . cones) (oak . acorns) (maple . seeds)) +(assq 'pine trees) + ⇒ (pine . cones) +</pre> +</div> <p>On the other hand, <code>assq</code> is not usually useful in alists where the keys may not be symbols: </p> <div class="example"> <pre class="example">(setq leaves + '(("simple leaves" . oak) + ("compound leaves" . horsechestnut))) + +(assq "simple leaves" leaves) + ⇒ <span class="roman">Unspecified; might be <code>nil</code> or <code>("simple leaves" . oak)</code>.</span> +(assoc "simple leaves" leaves) + ⇒ ("simple leaves" . oak) +</pre> +</div> </dd> +</dl> <dl> <dt id="alist-get">Function: <strong>alist-get</strong> <em>key alist &optional default remove testfn</em> +</dt> <dd> +<p>This function is similar to <code>assq</code>. It finds the first association <code>(<var>key</var> . <var>value</var>)</code> by comparing <var>key</var> with <var>alist</var> elements, and, if found, returns the <var>value</var> of that association. If no association is found, the function returns <var>default</var>. Comparison of <var>key</var> against <var>alist</var> elements uses the function specified by <var>testfn</var>, defaulting to <code>eq</code>. </p> <p>This is a generalized variable (see <a href="generalized-variables">Generalized Variables</a>) that can be used to change a value with <code>setf</code>. When using it to set a value, optional argument <var>remove</var> non-<code>nil</code> means to remove <var>key</var>’s association from <var>alist</var> if the new value is <code>eql</code> to <var>default</var>. </p> +</dd> +</dl> <dl> <dt id="rassq">Function: <strong>rassq</strong> <em>value alist</em> +</dt> <dd> +<p>This function returns the first association with value <var>value</var> in <var>alist</var>. It returns <code>nil</code> if no association in <var>alist</var> has a <small>CDR</small> <code>eq</code> to <var>value</var>. </p> <p><code>rassq</code> is like <code>assq</code> except that it compares the <small>CDR</small> of each <var>alist</var> association instead of the <small>CAR</small>. You can think of this as reverse <code>assq</code>, finding the key for a given value. </p> <p>For example: </p> <div class="example"> <pre class="example">(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) + +(rassq 'acorns trees) + ⇒ (oak . acorns) +(rassq 'spores trees) + ⇒ nil +</pre> +</div> <p><code>rassq</code> cannot search for a value stored in the <small>CAR</small> of the <small>CDR</small> of an element: </p> <div class="example"> <pre class="example">(setq colors '((rose red) (lily white) (buttercup yellow))) + +(rassq 'white colors) + ⇒ nil +</pre> +</div> <p>In this case, the <small>CDR</small> of the association <code>(lily white)</code> is not the symbol <code>white</code>, but rather the list <code>(white)</code>. This becomes clearer if the association is written in dotted pair notation: </p> <div class="example"> <pre class="example">(lily white) ≡ (lily . (white)) +</pre> +</div> </dd> +</dl> <dl> <dt id="assoc-default">Function: <strong>assoc-default</strong> <em>key alist &optional test default</em> +</dt> <dd> +<p>This function searches <var>alist</var> for a match for <var>key</var>. For each element of <var>alist</var>, it compares the element (if it is an atom) or the element’s <small>CAR</small> (if it is a cons) against <var>key</var>, by calling <var>test</var> with two arguments: the element or its <small>CAR</small>, and <var>key</var>. The arguments are passed in that order so that you can get useful results using <code>string-match</code> with an alist that contains regular expressions (see <a href="regexp-search">Regexp Search</a>). If <var>test</var> is omitted or <code>nil</code>, <code>equal</code> is used for comparison. </p> <p>If an alist element matches <var>key</var> by this criterion, then <code>assoc-default</code> returns a value based on this element. If the element is a cons, then the value is the element’s <small>CDR</small>. Otherwise, the return value is <var>default</var>. </p> <p>If no alist element matches <var>key</var>, <code>assoc-default</code> returns <code>nil</code>. </p> +</dd> +</dl> <dl> <dt id="copy-alist">Function: <strong>copy-alist</strong> <em>alist</em> +</dt> <dd> + <p>This function returns a two-level deep copy of <var>alist</var>: it creates a new copy of each association, so that you can alter the associations of the new alist without changing the old one. </p> <div class="example"> <pre class="example">(setq needles-per-cluster + '((2 . ("Austrian Pine" "Red Pine")) + (3 . ("Pitch Pine")) +</pre> +<pre class="example"> (5 . ("White Pine")))) +⇒ +((2 "Austrian Pine" "Red Pine") + (3 "Pitch Pine") + (5 "White Pine")) + +(setq copy (copy-alist needles-per-cluster)) +⇒ +((2 "Austrian Pine" "Red Pine") + (3 "Pitch Pine") + (5 "White Pine")) + +(eq needles-per-cluster copy) + ⇒ nil +(equal needles-per-cluster copy) + ⇒ t +(eq (car needles-per-cluster) (car copy)) + ⇒ nil +(cdr (car (cdr needles-per-cluster))) + ⇒ ("Pitch Pine") +</pre> +<pre class="example">(eq (cdr (car (cdr needles-per-cluster))) + (cdr (car (cdr copy)))) + ⇒ t +</pre> +</div> <p>This example shows how <code>copy-alist</code> makes it possible to change the associations of one copy without affecting the other: </p> <div class="example"> <pre class="example">(setcdr (assq 3 copy) '("Martian Vacuum Pine")) +(cdr (assq 3 needles-per-cluster)) + ⇒ ("Pitch Pine") +</pre> +</div> </dd> +</dl> <dl> <dt id="assq-delete-all">Function: <strong>assq-delete-all</strong> <em>key alist</em> +</dt> <dd> +<p>This function deletes from <var>alist</var> all the elements whose <small>CAR</small> is <code>eq</code> to <var>key</var>, much as if you used <code>delq</code> to delete each such element one by one. It returns the shortened alist, and often modifies the original list structure of <var>alist</var>. For correct results, use the return value of <code>assq-delete-all</code> rather than looking at the saved value of <var>alist</var>. </p> <div class="example"> <pre class="example">(setq alist (list '(foo 1) '(bar 2) '(foo 3) '(lose 4))) + ⇒ ((foo 1) (bar 2) (foo 3) (lose 4)) +(assq-delete-all 'foo alist) + ⇒ ((bar 2) (lose 4)) +alist + ⇒ ((foo 1) (bar 2) (lose 4)) +</pre> +</div> </dd> +</dl> <dl> <dt id="assoc-delete-all">Function: <strong>assoc-delete-all</strong> <em>key alist &optional test</em> +</dt> <dd><p>This function is like <code>assq-delete-all</code> except that it accepts an optional argument <var>test</var>, a predicate function to compare the keys in <var>alist</var>. If omitted or <code>nil</code>, <var>test</var> defaults to <code>equal</code>. As <code>assq-delete-all</code>, this function often modifies the original list structure of <var>alist</var>. </p></dd> +</dl> <dl> <dt id="rassq-delete-all">Function: <strong>rassq-delete-all</strong> <em>value alist</em> +</dt> <dd><p>This function deletes from <var>alist</var> all the elements whose <small>CDR</small> is <code>eq</code> to <var>value</var>. It returns the shortened alist, and often modifies the original list structure of <var>alist</var>. <code>rassq-delete-all</code> is like <code>assq-delete-all</code> except that it compares the <small>CDR</small> of each <var>alist</var> association instead of the <small>CAR</small>. </p></dd> +</dl> <dl> <dt id="let-alist">Macro: <strong>let-alist</strong> <em>alist body</em> +</dt> <dd> +<p>Creates a binding for each symbol used as keys the association list <var>alist</var>, prefixed with dot. This can be useful when accessing several items in the same association list, and it’s best understood through a simple example: </p> <div class="lisp"> <pre class="lisp">(setq colors '((rose . red) (lily . white) (buttercup . yellow))) +(let-alist colors + (if (eq .rose 'red) + .lily)) + ⇒ white +</pre> +</div> <p>The <var>body</var> is inspected at compilation time, and only the symbols that appear in <var>body</var> with a ‘<samp>.</samp>’ as the first character in the symbol name will be bound. Finding the keys is done with <code>assq</code>, and the <code>cdr</code> of the return value of this <code>assq</code> is assigned as the value for the binding. </p> <p>Nested association lists is supported: </p> <div class="lisp"> <pre class="lisp">(setq colors '((rose . red) (lily (belladonna . yellow) (brindisi . pink)))) +(let-alist colors + (if (eq .rose 'red) + .lily.belladonna)) + ⇒ yellow +</pre> +</div> <p>Nesting <code>let-alist</code> inside each other is allowed, but the code in the inner <code>let-alist</code> can’t access the variables bound by the outer <code>let-alist</code>. </p> +</dd> +</dl><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br> + <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html</a> + </p> +</div> |
