Associative Lists / Dictionaries: Difference between revisions

From MemCP
Jump to navigation Jump to search
No edit summary
(Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference)
 
Line 1: Line 1:
<!-- Copyright (C) 2026 Carl-Philip Haensch -->
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
<span id="associative-lists--dictionaries"></span>
= Associative Lists / Dictionaries =
= Associative Lists / Dictionaries =


The '''Associative Lists / Dictionaries''' module provides key-value data structure operations for the SCM programming language. This module includes:
<!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. -->
<div class="mw-message-box mw-message-box-notice">Generated from MemCP commit <code>c42e19eba</code> on 27 August 2026. See [[Full SCM API documentation]].</div>


* '''Dictionary filtering''': Functions to filter dictionaries based on key-value conditions (filter_assoc)
The '''Associative Lists / Dictionaries''' module works with functional key/value collections. It includes:
* '''Dictionary mapping''': Transform dictionary values while preserving keys (map_assoc)
* '''Dictionary reduction''': Aggregate dictionary data into single values (reduce_assoc)
* '''Dictionary queries''': Check for key existence and extract data (has_assoc?, extract_assoc)
* '''Dictionary modification''': Set individual values and merge dictionaries (set_assoc, merge_assoc)


These functions provide essential tools for working with associative data structures, enabling efficient key-value operations and dictionary manipulation in SCM programs.
* lookup and presence checks;
* extraction, filtering, and mapping by key and value;
* immutable updates and merges;
* reductions and sorting;
* structural indexes and catalogs for repeated lookups.


← Back to [[Full SCM API documentation]]
Ordinary operations return a new value instead of mutating an outer binding. This makes associative data safe to share through functional query code; use explicit sessions or synchronization primitives when mutable shared state is required.


== filter_assoc ==
== filter_assoc ==
Line 23: Line 28:


* '''dict''' (<code>list</code>): dictionary that has to be filtered
* '''dict''' (<code>list</code>): dictionary that has to be filtered
* '''condition''' (<code>func(key:string, value:any) -&gt; bool</code>): filter function func(string any)-&gt;bool where the first parameter is the key, the second is the value
* '''condition''' (<code>func</code>): returns whether a dictionary entry should be included
** '''Parameters'''
*** '''key''' (<code>string</code>): entry key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''included''' (<code>bool</code>): whether to include the entry


<span id="returns"></span>
<span id="returns"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== find_assoc ==
== find_assoc ==
Line 40: Line 50:


* '''dict''' (<code>list</code>): dictionary to search
* '''dict''' (<code>list</code>): dictionary to search
* '''condition''' (<code>func(key:string, value:any) -&gt; bool</code>): predicate func(string any)-&gt;bool that is applied until the first match
* '''condition''' (<code>func</code>): predicate applied until the first matching dictionary entry
** '''Parameters'''
*** '''key''' (<code>string</code>): entry key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''matches''' (<code>bool</code>): whether the entry matches
* '''default''' (<code>any</code>): optional default value if nothing matches ''(optional)''
* '''default''' (<code>any</code>): optional default value if nothing matches ''(optional)''


Line 46: Line 61:
=== Returns ===
=== Returns ===


<code>any</code>
* '''value''' (<code>any</code>)


== map_assoc ==
== map_assoc ==
Line 58: Line 73:


* '''dict''' (<code>list</code>): dictionary that has to be mapped
* '''dict''' (<code>list</code>): dictionary that has to be mapped
* '''map''' (<code>func(key:string, value:any) -&gt; any</code>): map function func(string any)-&gt;any where the first parameter is the key, the second is the value. It must return the new value.
* '''map''' (<code>func</code>): transforms each dictionary value
** '''Parameters'''
*** '''key''' (<code>string</code>): entry key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''mapped_value''' (<code>any</code>): replacement value


<span id="returns-2"></span>
<span id="returns-2"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== reduce_assoc ==
== reduce_assoc ==
Line 75: Line 95:


* '''dict''' (<code>list</code>): dictionary that has to be reduced
* '''dict''' (<code>list</code>): dictionary that has to be reduced
* '''reduce''' (<code>func(acc:any, key:any, value:any) -&gt; any</code>): reduce function func(any string any)-&gt;any where the first parameter is the accumulator, second is key, third is value. It must return the new accumulator.
* '''reduce''' (<code>func</code>): combines the accumulator with each dictionary entry
** '''Parameters'''
*** '''acc''' (<code>any</code>): current accumulator
*** '''key''' (<code>string</code>): entry key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''acc''' (<code>any</code>): next accumulator
* '''neutral''' (<code>any</code>): initial value for the accumulator
* '''neutral''' (<code>any</code>): initial value for the accumulator


Line 81: Line 107:
=== Returns ===
=== Returns ===


<code>any</code>
* '''value''' (<code>any</code>)


== make_structural_index ==
== make_structural_index ==
Line 98: Line 124:
=== Returns ===
=== Returns ===


<code>func(expression:any) -&gt; int|nil</code>
* '''lookup''' (<code>func</code>): looks up the indexed position of a structurally equal expression
** '''Parameters'''
*** '''expression''' (<code>any</code>): a key, root, descendant of a declared root, or scalar expression
** '''Returns'''
*** '''position''' (<code>int|nil</code>): zero-based key position, or nil when the expression is not indexed


== make_structural_catalog ==
== make_structural_catalog ==
Line 114: Line 144:
=== Returns ===
=== Returns ===


<code>func</code>
* '''catalog''' (<code>func</code>): atomic structural-expression lookup and update function
** '''Parameters'''
*** '''key''' (<code>any</code>): expression to look up; omit to freeze the catalog ''(optional)''
*** '''value''' (<code>any</code>): value to store for key ''(optional)''
** '''Returns'''
*** '''result''' (<code>any|func</code>): stored value, lookup result, or frozen lookup function
**** '''Parameters'''
***** '''key''' (<code>any</code>): expression to look up in the frozen catalog
**** '''Returns'''
***** '''value''' (<code>any</code>): value stored for a structurally equal expression, or nil


<span id="has_assoc"></span>
<span id="has_assoc"></span>
Line 132: Line 171:
=== Returns ===
=== Returns ===


<code>bool</code>
* '''value''' (<code>bool</code>)


== get_assoc ==
== get_assoc ==
Line 150: Line 189:
=== Returns ===
=== Returns ===


<code>any</code>
* '''value''' (<code>any</code>)


== get_assoc_pairlist ==
== get_assoc_pairlist ==
Line 168: Line 207:
=== Returns ===
=== Returns ===


<code>any</code>
* '''value''' (<code>any</code>)


== extract_assoc ==
== extract_assoc ==
Line 180: Line 219:


* '''dict''' (<code>list</code>): dictionary that has to be checked
* '''dict''' (<code>list</code>): dictionary that has to be checked
* '''map''' (<code>func(key:string, value:any) -&gt; any</code>): func(key, value)-&gt;any that extracts one element per key-value pair
* '''map''' (<code>func</code>): extracts one element per dictionary entry
** '''Parameters'''
*** '''key''' (<code>string</code>): entry key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''element''' (<code>any</code>): element extracted from the entry


<span id="returns-9"></span>
<span id="returns-9"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== set_assoc ==
== set_assoc ==
Line 199: Line 243:
* '''key''' (<code>string</code>): key that has to be set
* '''key''' (<code>string</code>): key that has to be set
* '''value''' (<code>any</code>): new value to set
* '''value''' (<code>any</code>): new value to set
* '''merge''' (<code>func(old:any, new:any) -&gt; any</code>): (optional) func(any any)-&gt;any that is called when a value is overwritten. The first parameter is the old value, the second is the new value. It must return the merged value that shall be physically stored in the new dictionary. ''(optional)''
* '''merge''' (<code>func</code>): combines values when an existing entry is overwritten ''(optional)''
** '''Parameters'''
*** '''old''' (<code>any</code>): existing value
*** '''new''' (<code>any</code>): replacement value
** '''Returns'''
*** '''merged''' (<code>any</code>): value stored in the new dictionary


<span id="returns-10"></span>
<span id="returns-10"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== merge_assoc ==
== merge_assoc ==
Line 217: Line 266:
* '''dict1''' (<code>list</code>): first input dictionary that has to be changed. You must not use this value again.
* '''dict1''' (<code>list</code>): first input dictionary that has to be changed. You must not use this value again.
* '''dict2''' (<code>list</code>): input dictionary that contains the new values that have to be added
* '''dict2''' (<code>list</code>): input dictionary that contains the new values that have to be added
* '''merge''' (<code>func(old:any, new:any) -&gt; any</code>): (optional) func(any any)-&gt;any that is called when a value is overwritten. The first parameter is the old value, the second is the new value from dict2. It must return the merged value that shall be pysically stored in the new dictionary. ''(optional)''
* '''merge''' (<code>func</code>): combines values when both dictionaries contain an entry ''(optional)''
** '''Parameters'''
*** '''old''' (<code>any</code>): value from the first dictionary
*** '''new''' (<code>any</code>): value from the second dictionary
** '''Returns'''
*** '''merged''' (<code>any</code>): value stored in the merged dictionary


<span id="returns-11"></span>
<span id="returns-11"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== sort ==
== sort ==
Line 233: Line 287:
=== Parameters ===
=== Parameters ===


* '''list''' (<code>list</code>):
* '''list''' (<code>list</code>)
* '''comparator''' (<code>func(any, any) -&gt; bool</code>):
* '''comparator''' (<code>func</code>)
** '''Parameters'''
*** '''parameter''' (<code>any</code>)
*** '''parameter''' (<code>any</code>)
** '''Returns'''
*** '''value''' (<code>bool</code>)


<span id="returns-12"></span>
<span id="returns-12"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== sort_mut ==
== sort_mut ==
Line 250: Line 309:
=== Parameters ===
=== Parameters ===


* '''list''' (<code>list</code>):
* '''list''' (<code>list</code>)
* '''comparator''' (<code>func(any, any) -&gt; bool</code>):
* '''comparator''' (<code>func</code>)
** '''Parameters'''
*** '''parameter''' (<code>any</code>)
*** '''parameter''' (<code>any</code>)
** '''Returns'''
*** '''value''' (<code>bool</code>)


<span id="returns-13"></span>
<span id="returns-13"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)


== mapkey_assoc ==
== mapkey_assoc ==
Line 268: Line 332:


* '''dict''' (<code>list</code>): dictionary whose keys have to be mapped
* '''dict''' (<code>list</code>): dictionary whose keys have to be mapped
* '''map''' (<code>func(key:string, value:any) -&gt; any</code>): map function func(key, value)-&gt;key where the first parameter is the old key, the second is the value. It must return the new key.
* '''map''' (<code>func</code>): computes a replacement key for each dictionary entry
** '''Parameters'''
*** '''key''' (<code>string</code>): existing key
*** '''value''' (<code>any</code>): entry value
** '''Returns'''
*** '''new_key''' (<code>any</code>): replacement key


<span id="returns-14"></span>
<span id="returns-14"></span>
=== Returns ===
=== Returns ===


<code>list</code>
* '''value''' (<code>list</code>)

Latest revision as of 11:59, 28 August 2026


Associative Lists / Dictionaries

Generated from MemCP commit c42e19eba on 27 August 2026. See Full SCM API documentation.

The Associative Lists / Dictionaries module works with functional key/value collections. It includes:

  • lookup and presence checks;
  • extraction, filtering, and mapping by key and value;
  • immutable updates and merges;
  • reductions and sorting;
  • structural indexes and catalogs for repeated lookups.

Ordinary operations return a new value instead of mutating an outer binding. This makes associative data safe to share through functional query code; use explicit sessions or synchronization primitives when mutable shared state is required.

filter_assoc

returns a filtered dictionary according to a filter function

Allowed number of parameters: 2–2

Parameters

  • dict (list): dictionary that has to be filtered
  • condition (func): returns whether a dictionary entry should be included
    • Parameters
      • key (string): entry key
      • value (any): entry value
    • Returns
      • included (bool): whether to include the entry

Returns

  • value (list)

find_assoc

returns the first key/value pair that passes the condition function, or nil/default if none matches

Allowed number of parameters: 2–3

Parameters

  • dict (list): dictionary to search
  • condition (func): predicate applied until the first matching dictionary entry
    • Parameters
      • key (string): entry key
      • value (any): entry value
    • Returns
      • matches (bool): whether the entry matches
  • default (any): optional default value if nothing matches (optional)

Returns

  • value (any)

map_assoc

returns a mapped dictionary according to a map function Keys will stay the same but values are mapped.

Allowed number of parameters: 2–2

Parameters

  • dict (list): dictionary that has to be mapped
  • map (func): transforms each dictionary value
    • Parameters
      • key (string): entry key
      • value (any): entry value
    • Returns
      • mapped_value (any): replacement value

Returns

  • value (list)

reduce_assoc

reduces a dictionary according to a reduce function

Allowed number of parameters: 3–3

Parameters

  • dict (list): dictionary that has to be reduced
  • reduce (func): combines the accumulator with each dictionary entry
    • Parameters
      • acc (any): current accumulator
      • key (string): entry key
      • value (any): entry value
    • Returns
      • acc (any): next accumulator
  • neutral (any): initial value for the accumulator

Returns

  • value (any)

make_structural_index

Builds an immutable structural-expression index. It eagerly hashes every key and every node under roots, then returns a parallel-safe lookup function that maps an equal expression to its zero-based key position or nil.

Allowed number of parameters: 2–2

Parameters

  • keys (list): immutable structural expressions to index
  • roots (list): immutable expression roots whose descendant hashes are precomputed

Returns

  • lookup (func): looks up the indexed position of a structurally equal expression
    • Parameters
      • expression (any): a key, root, descendant of a declared root, or scalar expression
    • Returns
      • position (int|nil): zero-based key position, or nil when the expression is not indexed

make_structural_catalog

Creates an atomic compile-local structural catalog. Look up with (catalog key), insert with (catalog key value), or freeze with (catalog) for parallel-safe read-only lookup.

Allowed number of parameters: 0–1

Parameters

  • mode (bool|symbol): true forces collisions for tests; ast selects type-stable compiler equality (optional)

Returns

  • catalog (func): atomic structural-expression lookup and update function
    • Parameters
      • key (any): expression to look up; omit to freeze the catalog (optional)
      • value (any): value to store for key (optional)
    • Returns
      • result (any|func): stored value, lookup result, or frozen lookup function
        • Parameters
          • key (any): expression to look up in the frozen catalog
        • Returns
          • value (any): value stored for a structurally equal expression, or nil

has_assoc?

checks if a dictionary has a key present

Allowed number of parameters: 2–2

Parameters

  • dict (list): dictionary that has to be checked
  • key (string): key to test

Returns

  • value (bool)

get_assoc

gets a value from a dictionary by key, returns nil if not found

Allowed number of parameters: 2–3

Parameters

  • dict (list): dictionary to look up
  • key (any): key to look up
  • default (any): optional default value if key not found (optional)

Returns

  • value (any)

get_assoc_pairlist

gets a value from a list of key/value rows without flattening the rows

Allowed number of parameters: 3–3

Parameters

  • rows (list): list whose rows contain a key followed by one or more values
  • key (any): key compared with the first item of each row
  • default (any): value returned when no row contains the key

Returns

  • value (any)

extract_assoc

applies a function (key value) on the dictionary and returns the results as a flat list

Allowed number of parameters: 2–2

Parameters

  • dict (list): dictionary that has to be checked
  • map (func): extracts one element per dictionary entry
    • Parameters
      • key (string): entry key
      • value (any): entry value
    • Returns
      • element (any): element extracted from the entry

Returns

  • value (list)

set_assoc

returns a new dictionary where a single value has been changed. The original dictionary is not modified.

Allowed number of parameters: 3–4

Parameters

  • dict (list): input dictionary
  • key (string): key that has to be set
  • value (any): new value to set
  • merge (func): combines values when an existing entry is overwritten (optional)
    • Parameters
      • old (any): existing value
      • new (any): replacement value
    • Returns
      • merged (any): value stored in the new dictionary

Returns

  • value (list)

merge_assoc

returns a dictionary where all keys from dict1 and all keys from dict2 are present. If a key is present in both inputs, the second one will be dominant so the first value will be overwritten unless you provide a merge function

Allowed number of parameters: 2–3

Parameters

  • dict1 (list): first input dictionary that has to be changed. You must not use this value again.
  • dict2 (list): input dictionary that contains the new values that have to be added
  • merge (func): combines values when both dictionaries contain an entry (optional)
    • Parameters
      • old (any): value from the first dictionary
      • new (any): value from the second dictionary
    • Returns
      • merged (any): value stored in the merged dictionary

Returns

  • value (list)

sort

returns a sorted copy of a list using a comparator (lambda (a b) truthy/falsy)

Allowed number of parameters: 2–2

Parameters

  • list (list)
  • comparator (func)
    • Parameters
      • parameter (any)
      • parameter (any)
    • Returns
      • value (bool)

Returns

  • value (list)

sort_mut

sorts a list in-place using a comparator (lambda (a b) truthy/falsy)

Allowed number of parameters: 2–2

Parameters

  • list (list)
  • comparator (func)
    • Parameters
      • parameter (any)
      • parameter (any)
    • Returns
      • value (bool)

Returns

  • value (list)

mapkey_assoc

returns a mapped dictionary according to a map function Values stay the same but keys are mapped.

Allowed number of parameters: 2–2

Parameters

  • dict (list): dictionary whose keys have to be mapped
  • map (func): computes a replacement key for each dictionary entry
    • Parameters
      • key (string): existing key
      • value (any): entry value
    • Returns
      • new_key (any): replacement key

Returns

  • value (list)