PageRenderTime 161ms CodeModel.GetById 65ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 0ms

/core/assocs/assocs-docs.factor

http://github.com/abeaumont/factor
Unknown | 516 lines | 441 code | 75 blank | 0 comment | 0 complexity | f030fef35e2e24bff7d79ac5852da64d MD5 | raw file
  1! Copyright (C) 2007, 2009 Daniel Ehrenberg, Slava Pestov, and Doug Coleman
  2! See http://factorcode.org/license.txt for BSD license.
  3USING: help.markup help.syntax kernel sequences
  4sequences.private namespaces math quotations assocs.private
  5sets ;
  6IN: assocs
  7
  8ARTICLE: "alists" "Association lists"
  9"An " { $emphasis "association list" } ", abbreviated " { $emphasis "alist" } ", is an association represented as a sequence where all elements are key/value pairs. The " { $link sequence } " mixin is an instance of the " { $link assoc } " mixin, hence all sequences support the " { $link "assocs-protocol" } " in this way."
 10$nl
 11"While not an association list, note that " { $link f } " also implements the associative mapping protocol in a trivial way; it is an immutable assoc with no entries."
 12$nl
 13"An alist is slower to search than a hashtable for a large set of associations. The main advantage of an association list is that the elements are ordered; also sometimes it is more convenient to construct an association list with sequence words than to construct a hashtable with association words. Much of the time, hashtables are more appropriate. See " { $link "hashtables" } "."
 14$nl
 15"There is no special syntax for literal alists since they are just sequences; in practice, literals look like so:"
 16{ $code "{" "    { key1 value1 }" "    { key2 value2 }" "}" }
 17"To make an assoc into an alist:"
 18{ $subsections >alist } ;
 19
 20ARTICLE: "enums" "Enumerations"
 21"An enumeration provides a view of a sequence as an assoc mapping integer indices to elements:"
 22{ $subsections
 23    enum
 24    <enum>
 25}
 26"Inverting a permutation using enumerations:"
 27{ $example "IN: scratchpad" ": invert ( perm -- perm' )" "    <enum> sort-values keys ;" "{ 2 0 4 1 3 } invert ." "{ 1 3 0 4 2 }" } ;
 28
 29HELP: enum
 30{ $class-description "An associative structure which wraps a sequence and maps integers to the corresponding elements of the sequence."
 31$nl
 32"Enumerations are mutable; note that deleting a key calls " { $link remove-nth! } ", which results in all subsequent elements being shifted down." } ;
 33
 34HELP: <enum>
 35{ $values { "seq" sequence } { "enum" enum } }
 36{ $description "Creates a new enumeration." } ;
 37
 38ARTICLE: "assocs-protocol" "Associative mapping protocol"
 39"All associative mappings must be instances of a mixin class:"
 40{ $subsections
 41    assoc
 42    assoc?
 43}
 44"All associative mappings must implement methods on the following generic words:"
 45{ $subsections
 46    at*
 47    assoc-size
 48    >alist
 49}
 50"Mutable assocs should implement the following additional words:"
 51{ $subsections
 52    set-at
 53    delete-at
 54    clear-assoc
 55}
 56"The following three words are optional:"
 57{ $subsections
 58    value-at*
 59    new-assoc
 60    assoc-like
 61}
 62"Assocs should also implement methods on the " { $link clone } ", " { $link equal? } " and " { $link hashcode* } " generic words. Two utility words will help with the implementation of the last two:"
 63{ $subsections
 64    assoc=
 65    assoc-hashcode
 66}
 67"Finally, assoc classes should define a word for converting other types of assocs; conventionally, such words are named " { $snippet ">" { $emphasis "class" } } " where " { $snippet { $emphasis "class" } } " is the class name. Such a word can be implemented using a utility:"
 68{ $subsections assoc-clone-like } ;
 69
 70ARTICLE: "assocs-lookup" "Lookup and querying of assocs"
 71"Utility operations built up from the " { $link "assocs-protocol" } ":"
 72{ $subsections
 73    key?
 74    at
 75    ?at
 76    assoc-empty?
 77    keys
 78    values
 79    assoc-stack
 80}
 81{ $see-also at* assoc-size } ;
 82
 83ARTICLE: "assocs-values" "Transposed assoc operations"
 84"Most assoc words take a key and find the corresponding value. The following words take a value and find the corresponding key:"
 85{ $subsections
 86    value-at
 87    value-at*
 88    value?
 89}
 90"With most assoc implementations, these words runs in linear time, proportional to the number of entries in the assoc. For fast value lookups, use " { $vocab-link "biassocs" } "." ;
 91
 92ARTICLE: "assocs-sets" "Set-theoretic operations on assocs"
 93"It is often useful to use the keys of an associative mapping as a set, exploiting the constant or logarithmic lookup time of most implementations (" { $link "alists" } " being a notable exception)."
 94$nl
 95"Set-theoretic operations:"
 96{ $subsections
 97    assoc-subset?
 98    assoc-intersect
 99    assoc-union
100    assoc-diff
101    substitute
102    extract-keys
103}
104"Adding elements to sets:"
105{ $subsections
106    conjoin
107    conjoin-at
108}
109"Destructive operations:"
110{ $subsections
111    assoc-union!
112    assoc-diff!
113}
114{ $see-also key? assoc-any? assoc-all? "sets" } ;
115
116ARTICLE: "assocs-mutation" "Storing keys and values in assocs"
117"Utility operations built up from the " { $link "assocs-protocol" } ":"
118{ $subsections
119    delete-at*
120    rename-at
121    change-at
122    at+
123    inc-at
124}
125{ $see-also set-at delete-at clear-assoc push-at } ;
126
127ARTICLE: "assocs-conversions" "Associative mapping conversions"
128"Converting to other assocs:"
129{ $subsections assoc-clone-like }
130"Combining a sequence of assocs into a single assoc:"
131{ $subsections assoc-combine }
132"Creating an assoc from key/value sequences:"
133{ $subsections zip }
134"Creating key/value sequences from an assoc:"
135{ $subsections unzip }
136;
137
138ARTICLE: "assocs-combinators" "Associative mapping combinators"
139"The following combinators can be used on any associative mapping."
140$nl
141"The " { $link assoc-find } " combinator is part of the " { $link "assocs-protocol" } " and must be implemented once for each class of assoc. All other combinators are implemented in terms of this combinator."
142$nl
143"The standard functional programming idioms:"
144{ $subsections
145    assoc-each
146    assoc-find
147    assoc-map
148    assoc-filter
149    assoc-filter-as
150    assoc-partition
151    assoc-any?
152    assoc-all?
153}
154"Removing empty keys or values:"
155{ $subsections
156    sift-keys
157    sift-values
158}
159"Mapping between assocs and sequences:"
160{ $subsections
161    map>assoc
162    assoc>map
163    assoc-map-as
164}
165"Destructive combinators:"
166{ $subsections
167    assoc-filter!
168    cache
169    2cache
170} ;
171
172ARTICLE: "assocs" "Associative mapping operations"
173"An " { $emphasis "associative mapping" } ", abbreviated " { $emphasis "assoc" } ", is a collection of key/value pairs which provides efficient lookup and storage indexed by key."
174$nl
175"Words used for working with assocs are in the " { $vocab-link "assocs" } " vocabulary."
176$nl
177"Associative mappings implement a protocol:"
178{ $subsections "assocs-protocol" }
179"A large set of utility words work on any object whose class implements the associative mapping protocol."
180{ $subsections
181    "assocs-lookup"
182    "assocs-values"
183    "assocs-mutation"
184    "assocs-combinators"
185    "assocs-sets"
186    "assocs-conversions"
187} ;
188
189ABOUT: "assocs"
190
191HELP: assoc
192{ $class-description "A mixin class whose instances are associative mappings. Custom implementations of the assoc protocol should be declared as instances of this mixin for all assoc functionality to work correctly:"
193    { $code "INSTANCE: avl-tree assoc" }
194} ;
195
196HELP: at*
197{ $values { "key" "an object to look up in the assoc" } { "assoc" assoc } { "value/f" "the value associated to the key, or " { $link f } " if the key is not present in the assoc" } { "?" "a " { $link boolean } " indicating if the key was present" } }
198{ $contract "Looks up the value associated with a key. The boolean flag can decide between the case of a missing value, and a value of " { $link f } "." } ;
199
200HELP: set-at
201{ $values { "value" "a value" } { "key" "a key to add" } { "assoc" assoc } }
202{ $contract "Stores the key/value pair into the assoc." }
203{ $side-effects "assoc" } ;
204
205HELP: new-assoc
206{ $values { "capacity" "a non-negative integer" } { "exemplar" assoc } { "newassoc" assoc } }
207{ $contract "Creates a new assoc of the same size as " { $snippet "exemplar" } " which can hold " { $snippet "capacity" } " entries before growing." } ;
208
209HELP: assoc-find
210{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } { "key" "the successful key, or f" } { "value" "the successful value, or f" } { "?" boolean } }
211{ $description "Applies a predicate quotation to each entry in the assoc. Returns the key and value that the quotation succeeds on, or " { $link f } " for both if the quotation fails. It also returns a boolean describing whether there was anything found; this can be used to distinguish between a key and a value equal to " { $link f } ", or nothing being found." } ;
212
213HELP: clear-assoc
214{ $values { "assoc" assoc } }
215{ $contract "Removes all entries from the assoc." }
216{ $side-effects "assoc" } ;
217
218HELP: delete-at
219{ $values { "key" "a key" } { "assoc" assoc } }
220{ $contract "Removes an entry from the assoc." }
221{ $side-effects "assoc" } ;
222
223HELP: assoc-size
224{ $values { "assoc" assoc } { "n" "a non-negative integer" } }
225{ $contract "Outputs the number of entries stored in the assoc." } ;
226
227HELP: assoc-like
228{ $values { "assoc" assoc } { "exemplar" assoc } { "newassoc" "a new assoc" } }
229{ $contract "Creates a new assoc having the same entries as " { $snippet "assoc" } " and the same type as " { $snippet "exemplar" } "." } ;
230
231HELP: assoc-empty?
232{ $values { "assoc" assoc } { "?" boolean } }
233{ $description "Tests if the assoc contains no entries." } ;
234
235HELP: key?
236{ $values { "key" object } { "assoc" assoc } { "?" boolean } }
237{ $description "Tests if an assoc contains a key." } ;
238
239{ at at* key? ?at } related-words
240
241HELP: at
242{ $values { "key" object } { "assoc" assoc } { "value/f" "the value associated to the key, or " { $link f } " if the key is not present in the assoc" } }
243{ $description "Looks up the value associated with a key. This word makes no distinction between a missing value and a value set to " { $link f } "; if the difference is important, use " { $link at* } "." } ;
244
245HELP: ?at
246{ $values { "key" object } { "assoc" assoc } { "value/key" "the value associated to the key, or the key if the key is not present in the assoc" } { "?" "a " { $link boolean } " indicating if the key was present" } }
247{ $description "Looks up the value associated with a key. If the key was not present, an error can be thrown without extra stack shuffling. This word handles assocs that store " { $link f } "." } ;
248
249HELP: assoc-each
250{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... )" } } }
251{ $description "Applies a quotation to each entry in the assoc." }
252{ $examples
253    { $example
254        "USING: assocs kernel math prettyprint ;"
255        "H{ { \"bananas\" 5 } { \"apples\" 42 } { \"pears\" 17 } }"
256        "0 swap [ nip + ] assoc-each ."
257        "64"
258    }
259} ;
260
261HELP: assoc-map
262{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... newkey newvalue )" } } { "newassoc" "a new assoc" } }
263{ $description "Applies the quotation to each entry in the input assoc and collects the results in a new assoc of the same type as the input." }
264{ $examples
265    { $unchecked-example
266        ": discount ( prices n -- newprices )"
267        "    [ - ] curry assoc-map ;"
268        "H{ { \"bananas\" 5 } { \"apples\" 42 } { \"pears\" 17 } }"
269        "2 discount ."
270        "H{ { \"bananas\" 3 } { \"apples\" 40 } { \"pears\" 15 } }"
271    }
272} ;
273
274{ assoc-map assoc-map-as } related-words
275
276HELP: assoc-filter
277{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } { "subassoc" "a new assoc" } }
278{ $description "Outputs an assoc of the same type as " { $snippet "assoc" } " consisting of all entries for which the predicate quotation yields true." } ;
279
280HELP: assoc-filter-as
281{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } { "exemplar" assoc } { "subassoc" "a new assoc" } }
282{ $description "Outputs an assoc of the same type as " { $snippet "exemplar" } " consisting of all entries for which the predicate quotation yields true." } ;
283
284HELP: assoc-filter!
285{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } }
286{ $description "Removes all entries for which the predicate quotation yields true." }
287{ $side-effects "assoc" } ;
288
289{ assoc-filter assoc-filter-as assoc-filter! } related-words
290
291HELP: assoc-partition
292{ $values
293    { "assoc" assoc } { "quot" quotation }
294    { "true-assoc" assoc } { "false-assoc" assoc }
295}
296{ $description "Calls a predicate quotation on each key of the input assoc. If the test yields true, the key/value pair is added to " { $snippet "true-assoc" } "; if false, it's added to " { $snippet "false-assoc" } "." } ;
297
298HELP: assoc-any?
299{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } { "?" boolean } }
300{ $description "Tests if the assoc contains an entry satisfying a predicate by applying the quotation to each entry in turn. Iteration stops if an entry is found for which the quotation outputs a true value." } ;
301
302HELP: assoc-all?
303{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... ? )" } } { "?" boolean } }
304{ $description "Tests if all entries in the assoc satisfy a predicate by applying the quotation to each entry in turn. a predicate quotation to entry in the assoc. Iteration stops if an entry is found for which the quotation outputs " { $link f } ". If the assoc is empty, always outputs " { $link t } "." } ;
305
306HELP: assoc-refine
307{ $values { "seq" sequence } { "assoc" assoc } }
308{ $description "Outputs the intersection of all the assocs of the assocs sequence " { $snippet "seq" } ", or " { $link f } " if " { $snippet "seq" } " is empty." } ;
309
310HELP: assoc-subset?
311{ $values { "assoc1" assoc } { "assoc2" assoc } { "?" boolean } }
312{ $description "Tests if " { $snippet "assoc2" } " contains all key/value pairs of " { $snippet "assoc1" } "." } ;
313
314HELP: sift-keys
315{ $values { "assoc" assoc } { "assoc'" "a new assoc" } }
316{ $description "Outputs an assoc removing keys that are " { $link f } "." } ;
317
318HELP: sift-values
319{ $values { "assoc" assoc } { "assoc'" "a new assoc" } }
320{ $description "Outputs an assoc removing values that are " { $link f } "." } ;
321
322HELP: assoc=
323{ $values { "assoc1" assoc } { "assoc2" assoc } { "?" boolean } }
324{ $description "Tests if two assocs contain the same entries. Unlike " { $link = } ", the two assocs may be of different types." }
325{ $notes "Assoc implementations should define a method for the " { $link equal? } " generic word which calls this word after checking that both inputs have the same type." } ;
326
327HELP: assoc-hashcode
328{ $values { "n" "a non-negative integer" } { "assoc" assoc } { "code" integer } }
329{ $description "Computes a hashcode for an assoc, such that equal assocs will have the same hashcode." }
330{ $notes "Custom assoc implementations should use this word to implement a method for the " { $link hashcode* } " generic word." } ;
331
332HELP: assoc-stack
333{ $values { "key" "a key" } { "seq" "a sequence of assocs" } { "value" "a value or " { $link f } } }
334{ $description "Searches for the key in successive elements of the sequence, starting from the end. If an assoc containing the key is found, the associated value is output. If no assoc contains the key, outputs " { $link f } "." }
335{ $notes "This word is used to implement abstractions such as nested scopes; if the sequence is a stack represented by a vector, then the most recently pushed assoc -- the innermost scope -- will be searched first." } ;
336
337HELP: value-at*
338{ $values { "value" object } { "assoc" assoc } { "key/f" "the key associated to the value, or " { $link f } } { "?" boolean } }
339{ $description "Looks up the key associated with a value. The boolean flag can decide between the case of a missing key, and a key of " { $link f } "." } ;
340
341HELP: value-at
342{ $values { "value" object } { "assoc" assoc } { "key/f" "the key associated to the value, or " { $link f } } }
343{ $description "Looks up the key associated with a value. No distinction is made between a missing key and a key set to " { $link f } "." } ;
344
345HELP: value?
346{ $values { "value" object } { "assoc" assoc } { "?" boolean } }
347{ $description "Tests if an assoc contains at least one key with the given value." } ;
348
349HELP: delete-at*
350{ $values { "key" "a key" } { "assoc" assoc } { "old" "the previous value or " { $link f } } { "?" boolean } }
351{ $description "Removes an entry from the assoc and outputs the previous value together with a boolean indicating whether it was present." }
352{ $side-effects "assoc" } ;
353
354HELP: rename-at
355{ $values { "newkey" object } { "key" object } { "assoc" assoc } }
356{ $description "Removes the values associated to " { $snippet "key" } " and re-adds it as " { $snippet "newkey" } ". Does nothing if the assoc does not contain " { $snippet "key" } "." }
357;
358
359HELP: keys
360{ $values { "assoc" assoc } { "keys" "an array of keys" } }
361{ $description "Outputs an array of all keys in the assoc." } ;
362
363HELP: values
364{ $values { "assoc" assoc } { "values" "an array of values" } }
365{ $description "Outputs an array of all values in the assoc." } ;
366
367{ keys values } related-words
368
369HELP: assoc-intersect
370{ $values { "assoc1" assoc } { "assoc2" assoc } { "intersection" "a new assoc" } }
371{ $description "Outputs an assoc consisting of all entries from " { $snippet "assoc2" } " such that the key is also present in " { $snippet "assoc1" } "." }
372{ $notes "The values of the keys in " { $snippet "assoc1" } " are disregarded, so this word is usually used for set-theoretic calculations where the assoc in question either has dummy sentinels as values, or the values equal the keys." } ;
373
374HELP: assoc-union!
375{ $values { "assoc1" assoc } { "assoc2" assoc } }
376{ $description "Adds all entries from " { $snippet "assoc2" } " to " { $snippet "assoc1" } "." }
377{ $side-effects "assoc1" } ;
378
379HELP: assoc-union
380{ $values { "assoc1" assoc } { "assoc2" assoc } { "union" "a new assoc" } }
381{ $description "Outputs a assoc consisting of all entries from " { $snippet "assoc1" } " and " { $snippet "assoc2" } ", with entries from " { $snippet "assoc2" } " taking precedence in case the corresponding values are not equal." } ;
382
383HELP: assoc-diff
384{ $values { "assoc1" assoc } { "assoc2" assoc } { "diff" "a new assoc" } }
385{ $description "Outputs an assoc consisting of all entries from " { $snippet "assoc1" } " whose key is not contained in " { $snippet "assoc2" } "." }
386;
387
388HELP: assoc-diff!
389{ $values { "assoc1" assoc } { "assoc2" assoc } }
390{ $description "Removes all entries from " { $snippet "assoc1" } " whose key is contained in " { $snippet "assoc2" } "." }
391{ $side-effects "assoc1" } ;
392
393HELP: substitute
394{ $values { "seq" sequence } { "assoc" assoc } { "newseq" sequence } }
395{ $description "Creates a new sequence where elements of " { $snippet "seq" } " which appear as keys in " { $snippet "assoc" } " are replaced by the corresponding values, and all other elements are unchanged." } ;
396
397HELP: cache
398{ $values { "key" "a key" } { "assoc" assoc } { "quot" { $quotation "( ... key -- ... value )" } } { "value" "a previously-retained or freshly-computed value" } }
399{ $description "If the key is present in the assoc, outputs the associated value, otherwise calls the quotation to produce a value and stores the key/value pair into the assoc. Returns a value either looked up or newly stored in the assoc." }
400{ $side-effects "assoc" } ;
401
402HELP: 2cache
403{ $values { "key1" "a key" } { "key2" "a key" } { "assoc" assoc } { "quot" { $quotation "( ... key1 key2 -- ... value )" } } { "value" "a previously-retained or freshly-computed value" } }
404{ $description "If a single key composed of the input keys is present in the assoc, outputs the associated value, otherwise calls the quotation to produce a value and stores the keys/value pair into the assoc. Returns the value stored in the assoc. Returns a value either looked up or newly stored in the assoc." }
405{ $side-effects "assoc" } ;
406
407HELP: map>assoc
408{ $values { "seq" sequence } { "quot" { $quotation "( ... elt -- ... key value )" } } { "exemplar" assoc } { "assoc" "a new assoc" } }
409{ $description "Applies the quotation to each element of the sequence, and collects the keys and values into a new assoc having the same type as " { $snippet "exemplar" } "." } ;
410
411HELP: assoc>map
412{ $values { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... elt )" } } { "exemplar" sequence } { "seq" "a new sequence" } }
413{ $description "Applies the quotation to each entry of the assoc and collects the results into a new sequence of the same type as the exemplar." } ;
414
415HELP: change-at
416{ $values { "key" object } { "assoc" assoc } { "quot" { $quotation "( ..a value -- ..b newvalue )" } } }
417{ $description "Applies the quotation to the value associated with " { $snippet "key" } ", storing the new value back in the assoc." }
418{ $side-effects "assoc" } ;
419
420{ change-at change-nth change } related-words
421
422HELP: at+
423{ $values { "n" number } { "key" object } { "assoc" assoc } }
424{ $description "Adds " { $snippet "n" } " to the value associated with " { $snippet "key" } "; if there is no value, stores " { $snippet "n" } ", thus behaving as if the value was 0." }
425{ $side-effects "assoc" } ;
426
427HELP: inc-at
428{ $values { "key" object } { "assoc" assoc } }
429{ $description "Adds 1 to the value associated with " { $snippet "key" } "; if there is no value, stores 1." }
430{ $side-effects "assoc" } ;
431
432HELP: >alist
433{ $values { "assoc" assoc } { "newassoc" "an array of key/value pairs" } }
434{ $contract "Converts an associative structure into an association list." } ;
435
436HELP: assoc-clone-like
437{ $values
438     { "assoc" assoc } { "exemplar" assoc }
439     { "newassoc" assoc } }
440{ $description "Outputs a newly-allocated assoc with the same elements as " { $snippet "assoc" } "." }
441{ $examples { $example "USING: prettyprint assocs hashtables ;" "H{ { 1 2 } { 3 4 } } { } assoc-clone-like ." "{ { 1 2 } { 3 4 } }" } } ;
442
443HELP: assoc-combine
444{ $values
445     { "seq" "a sequence of assocs" }
446     { "union" assoc } }
447{ $description "Takes the union of all of the " { $snippet "assocs" } " in " { $snippet "seq" } "." }
448{ $examples { $example "USING: prettyprint assocs ;" "{ H{ { 1 2 } } H{ { 3 4 } } } assoc-combine ." "H{ { 1 2 } { 3 4 } }" } } ;
449
450HELP: assoc-map-as
451{ $values
452     { "assoc" assoc } { "quot" { $quotation "( ... key value -- ... newkey newvalue )" } } { "exemplar" assoc }
453     { "newassoc" assoc } }
454{ $description "Applies the quotation to each entry in the input assoc and collects the results in a new assoc of the same type as the exemplar." }
455{ $examples { $example "USING: prettyprint assocs hashtables math ;" " H{ { 1 2 } { 3 4 } } [ sq ] { } assoc-map-as ." "{ { 1 4 } { 3 16 } }" } } ;
456
457HELP: extract-keys
458{ $values
459     { "seq" sequence } { "assoc" assoc }
460     { "subassoc" assoc } }
461{ $description "Outputs an new " { $snippet "assoc" } " with key/value pairs whose keys match the elements in the input " { $snippet "seq" } "." }
462{ $examples
463    { $example "USING: prettyprint assocs ;"
464               "{ 1 3 } { { 1 10 } { 2 20 } { 3 30 } } extract-keys ."
465               "{ { 1 10 } { 3 30 } }"
466    }
467} ;
468
469HELP: push-at
470{ $values
471     { "value" object } { "key" object } { "assoc" assoc } }
472{ $description "Pushes the " { $snippet "value" } " onto a " { $snippet "vector" } " stored at the " { $snippet "key" } " in the " { $snippet "assoc" } ". If the " { $snippet "key" } " does not yet exist, creates a new " { $snippet "vector" } " at that " { $snippet "key" } " and pushes the " { $snippet "value" } "." }
473{ $examples { $example "USING: prettyprint assocs kernel ;"
474"H{ { \"cats\" V{ \"Mittens\" } } } \"Mew\" \"cats\" pick push-at ."
475"H{ { \"cats\" V{ \"Mittens\" \"Mew\" } } }"
476} } ;
477
478HELP: search-alist
479{ $values
480     { "key" object } { "alist" "an array of key/value pairs" }
481     { "pair/f" "a key/value pair" } { "i/f" integer } }
482{ $description "Iterates over " { $snippet "alist" } " and stops when the key is matched or the end of the " { $snippet "alist" } " has been reached. If there is no match, both outputs are " { $link f } "." }
483{ $notes "This word is used to implement " { $link at* } " and " { $link set-at } " on sequences, and should not be called directly." }
484{ $examples { $example "USING: prettyprint assocs.private kernel ;"
485                        "3 { { 1 2 } { 3 4 } } search-alist [ . ] bi@"
486                       "{ 3 4 }\n1"
487            } { $example "USING: prettyprint assocs.private kernel ;"
488                       "6 { { 1 2 } { 3 4 } } search-alist [ . ] bi@"
489                       "f\nf"
490            }
491} ;
492
493HELP: unzip
494{ $values
495     { "assoc" assoc }
496     { "keys" sequence } { "values" sequence } }
497{ $description "Outputs an array of keys and an array of values of the input " { $snippet "assoc" } "." }
498{ $examples
499    { $example "USING: prettyprint assocs kernel ;"
500               "{ { 1 4 } { 2 5 } { 3 6 } } unzip [ . ] bi@"
501               "{ 1 2 3 }\n{ 4 5 6 }"
502    }
503} ;
504
505HELP: zip
506{ $values
507     { "keys" sequence } { "values" sequence }
508     { "alist" "an array of key/value pairs" } }
509{ $description "Combines two sequences pairwise into a single sequence of key/value pairs." }
510{ $examples
511    { $example "USING: prettyprint assocs ;"
512               "{ 1 2 3 } { 4 5 6 } zip ."
513               "{ { 1 4 } { 2 5 } { 3 6 } }"
514    }
515} ;
516{ unzip zip } related-words