Lists and Objects: 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:
Lists are a powerful feature in Scheme. Lists can express both: Data and Programs.
<!-- Copyright (C) 2026 Carl-Philip Haensch -->
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
= Lists and Objects =


==List handling==
Lists are central to MemCP's Scheme dialect: they represent ordinary collections, associative objects and executable code. This tutorial explains the programming model; [[Lists]] and [[Associative Lists / Dictionaries]] provide the generated function reference.
The following list functions can be used:
> '(1 2 3) "list literal"
= (1 2 3)
> (cons 0 '(1 2 3)) "prepend item to list"
= (0 1 2 3)
> (append '(1 2 3) 4 5) "append items to list"
= (1 2 3 4 5)
> (has? '(1 2 3) 2) "check if item is in list"
= true
> (filter '(1 2 3) (lambda (x) (< x 2))) "filter items that are smaller than 2"
= (1)
> (map '(1 2 3) (lambda (x) (* x 2))) "double all numbers"
= (2 4 6)
> (reduce '(1 2 3) + 0) "build sum by starting with 0 and reducing them over (+ 0 value)"
= 6
==Associative Lists (Objects)==
The following functions can be used:
> (set obj '("a" 1 "b" 2 "c" 3)) /* construct object from a list with alternating key-value */
= ("a" 1 "b" 2 "c" 3)
> (obj "a") /* extract a value */
= 1
> (set_assoc obj "a" "5") /* construct a new object with another value */
= ("a" "5" "b" 2 "c" 3)
> (set obj (set_assoc obj "a" "5")) /* modify obj */
= ("a" "5" "b" 2 "c" 3)
> (filter_assoc obj (lambda (key value) (not (equal? key "c")))) /* filter an object by a condition */
= ("a" 1 "b" 2)
> (map_assoc obj (lambda (key value) (* value 2))) /* double all values */
= ("a" 2 "b" 4 "c" 6)
> (reduce_assoc obj (lambda (accumulator key value) (+ accumulator value)) 0) /* sum up all values */
= 6
As you see in <code>set_assoc</code>, we have a pure functional approach here. Objects are not modified in-place like in languages like Java, JavaScript, Python, C++ or such, but rather we have to construct a modified copy of that value and overwrite it to the original value. The Scheme optimizer will detect if an in-place operation would be safe, too and can optimize this corner case but the language itself prioritizes safety.


== Code JITing with List Literals ==
== List values ==
One can construct lists that themselves represent code. You need basically three primitives:


* List Literals
A quoted list is data. Mapping and filtering return new lists; reduction combines them into one value.
* Symbol Literals
* <code>(cons list [LIST])</code> to insert a list literal into the code


All other primitive values like strings, numbers etc. will just be passed through without interpretation.
<syntaxhighlight lang="scheme">
> (set my_program '('print "Hello World"))
'(1 2 3)
= (print "Hello World")
(cons 0 '(1 2 3))                        /* (0 1 2 3) */
(append '(1 2 3) 4 5)                    /* (1 2 3 4 5) */
> (eval my_program)
(has? '(1 2 3) 2)                        /* true */
Hello World
(filter '(1 2 3) (lambda (x) (< x 3)))    /* (1 2) */
(map '(1 2 3) (lambda (x) (* x 2)))      /* (2 4 6) */
(reduce '(1 2 3) + 0)                    /* 6 */
</syntaxhighlight>
 
Choose a correct neutral value and an associative reducer when work may run in parallel. Order-sensitive string concatenation, floating-point sums and callbacks with I/O require particular care.
 
== Associative lists as objects ==
 
An object is a flat list of alternating keys and values. Calling it with a key performs lookup. Updates are functional: <code>set_assoc</code> returns a new value instead of mutating the old list.
 
<syntaxhighlight lang="scheme">
(set obj '("a" 1 "b" 2 "c" 3))
(obj "a")
(set obj (set_assoc obj "a" 5))
(filter_assoc obj (lambda (key value) (not (equal? key "c"))))
(map_assoc obj (lambda (key value) (* value 2)))
(reduce_assoc obj (lambda (acc key value) (+ acc value)) 0)
</syntaxhighlight>
 
Use <code>has_assoc?</code> when absence differs from a stored <code>nil</code>. Request objects, JSON objects, SQL result rows and sessions may expose a similar callable lookup style, but they are not necessarily represented by the same physical type.
 
== Lists as generated code ==
 
Scheme code is list-shaped data. Quoting controls which computation happens while building a program and which is delayed until <code>eval</code>.
 
<syntaxhighlight lang="scheme">
(set program '('print "Hello World"))
(eval program)
(set add_expression '('+ 4 5))
(eval add_expression)                       /* 9 */
</syntaxhighlight>
 
Symbols naming delayed procedures remain quoted. Values that must be computed while building the outer expression are embedded without an extra quote. Generated lambdas need a quoted <code>lambda</code> symbol, a parameter list and exactly one body; use <code>begin</code> for several forms.
 
The optimizer may fuse safe list operations or JIT-compile supported hot procedures, but observable functional semantics remain unchanged. See [[Introduction to Scheme]], [[JIT Compilation]] and [[Parallel Computing]].

Revision as of 11:59, 28 August 2026

Lists and Objects

Lists are central to MemCP's Scheme dialect: they represent ordinary collections, associative objects and executable code. This tutorial explains the programming model; Lists and Associative Lists / Dictionaries provide the generated function reference.

List values

A quoted list is data. Mapping and filtering return new lists; reduction combines them into one value.

<syntaxhighlight lang="scheme"> '(1 2 3) (cons 0 '(1 2 3)) /* (0 1 2 3) */ (append '(1 2 3) 4 5) /* (1 2 3 4 5) */ (has? '(1 2 3) 2) /* true */ (filter '(1 2 3) (lambda (x) (< x 3))) /* (1 2) */ (map '(1 2 3) (lambda (x) (* x 2))) /* (2 4 6) */ (reduce '(1 2 3) + 0) /* 6 */ </syntaxhighlight>

Choose a correct neutral value and an associative reducer when work may run in parallel. Order-sensitive string concatenation, floating-point sums and callbacks with I/O require particular care.

Associative lists as objects

An object is a flat list of alternating keys and values. Calling it with a key performs lookup. Updates are functional: set_assoc returns a new value instead of mutating the old list.

<syntaxhighlight lang="scheme"> (set obj '("a" 1 "b" 2 "c" 3)) (obj "a") (set obj (set_assoc obj "a" 5)) (filter_assoc obj (lambda (key value) (not (equal? key "c")))) (map_assoc obj (lambda (key value) (* value 2))) (reduce_assoc obj (lambda (acc key value) (+ acc value)) 0) </syntaxhighlight>

Use has_assoc? when absence differs from a stored nil. Request objects, JSON objects, SQL result rows and sessions may expose a similar callable lookup style, but they are not necessarily represented by the same physical type.

Lists as generated code

Scheme code is list-shaped data. Quoting controls which computation happens while building a program and which is delayed until eval.

<syntaxhighlight lang="scheme"> (set program '('print "Hello World")) (eval program) (set add_expression '('+ 4 5)) (eval add_expression) /* 9 */ </syntaxhighlight>

Symbols naming delayed procedures remain quoted. Values that must be computed while building the outer expression are embedded without an extra quote. Generated lambdas need a quoted lambda symbol, a parameter list and exactly one body; use begin for several forms.

The optimizer may fuse safe list operations or JIT-compile supported hot procedures, but observable functional semantics remain unchanged. See Introduction to Scheme, JIT Compilation and Parallel Computing.