Introduction to Scheme: Difference between revisions
Wikiservice (talk | contribs) (Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference) |
|||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
<!-- Copyright (C) 2026 Carl-Philip Haensch --> | |||
<!-- SPDX-License-Identifier: GPL-3.0-or-later --> | |||
= Introduction to Scheme = | |||
Scheme | |||
MemCP embeds a small Scheme dialect used by the SQL parsers, query planner, modules, and application endpoints. Start the interactive console with <code>./memcp lib/main.scm</code>; background services use <code>--no-repl</code>. | |||
Scheme represents calls and code with the same list syntax. That makes the dialect well suited to MemCP's query compiler: the SQL planner constructs Scheme programs as data, optimizes them, and evaluates or compiles them. | |||
The console prints each expression result, which makes the evaluation model easy to explore: | |||
<pre>> 12 | |||
= 12 | |||
> (+ 1 2 3) | |||
= 6 | |||
> (+ 2 (* 2 4)) | |||
= 10 | |||
> (concat "Hello " "World") | |||
= "Hello World"</pre> | |||
Startup also loads the configured data directory and Scheme modules before opening the SQL/HTTP listeners. The exact banner and number of startup tests change between releases, so scripts should not parse that text. | |||
The | |||
== Values and calls == | |||
<pre> | |||
(+ 1 2) | |||
(concat "hello " "world") | |||
(map '(1 2 3) (lambda (x) (* x x))) | |||
</pre> | |||
Numbers, booleans, strings, symbols, lists, functions, sessions, and storage objects are ordinary values. A list in expression position is a call: its first item is the procedure and the rest are arguments. Whitespace separates forms; parentheses define nesting. | |||
* [[Full SCM API documentation]] | {| class="wikitable" | ||
* [[Lists and Objects]] | ! Form !! Meaning | ||
* [[ | |- | ||
* [[ | | <code>42</code>, <code>3.5</code>, <code>true</code>, <code>"text"</code> || Literal values | ||
|- | |||
| <code>(+ 1 2)</code> || Call <code>+</code> with two arguments | |||
|- | |||
| <code>'name</code> || The symbol <code>name</code>, not the value bound to it | |||
|- | |||
| <code>'(1 2 3)</code> || Construct a list value instead of calling <code>1</code> | |||
|- | |||
| <code>'("name" "Ada" "active" true)</code> || Flat key/value list used as an associative object | |||
|} | |||
== Quoting and generated code == | |||
Use quoting to build code or data: <code>'(+ 4 5)</code> constructs delayed code, while <code>(eval '(+ 4 5))</code> evaluates it. Values that should be computed now can be embedded into a quoted outer form; procedure symbols whose execution is delayed remain quoted. This distinction matters throughout the query planner. | |||
<pre> | |||
(set delayed '(+ 4 5)) | |||
(eval delayed) /* 9 */ | |||
(map '(1 2 3) (lambda (x) (* x x))) | |||
</pre> | |||
Do not add or remove parentheses by visual guesswork in large generated expressions. Repository Scheme files are formatted and checked with <code>python3 tools/lint_scm.py</code>. | |||
== Functions and scope == | |||
Lambdas have exactly a parameter list and one body. Use <code>begin</code> when that body needs several forms: | |||
<pre> | |||
(define greet (lambda (name) (begin | |||
(print "greeting " name) | |||
(concat "Hello, " name)))) | |||
(greet "Ada") | |||
</pre> | |||
Functions are closures and may be passed to <code>map</code>, reducers, scanners, parsers, and handlers. <code>define</code> and <code>set</code> create a binding in the current scope in this dialect; <code>set</code> is not an imperative mutation of an outer lexical variable. | |||
== Pattern matching and modules == | |||
<code>match</code> is the usual way to express alternatives and destructure lists, strings, or regular-expression results. Modules are loaded with <code>import</code>; application entrypoints typically import the required library files and then install handlers or start a server. | |||
<pre> | |||
(match value | |||
'(x y) (+ x y) | |||
(regex "^/users/([0-9]+)$" path id) id | |||
false) | |||
</pre> | |||
See [[Parsers]], [[Lists and Objects]], and the matching examples in the repository for the exact pattern forms. | |||
== State and concurrency == | |||
The dialect is functional by default. <code>set</code> defines a binding in the current scope; it does not imperatively mutate an outer binding. Use <code>(newsession)</code> when code intentionally needs a thread-safe mutable key/value context shared across parallel work. | |||
<pre> | |||
(set request_state (newsession)) | |||
(request_state "user_id" 42) | |||
(request_state "user_id") /* 42 */ | |||
</pre> | |||
Independent functional work may run in parallel. Supported hot procedures can be compiled by the native x86-64 JIT; unsupported shapes remain interpreted without changing language semantics. See [[Full SCM API documentation]], [[Parallel Computing]], and [[In-Database WebApps and REST Services]]. | |||
== Where to continue == | |||
* [[Full SCM API documentation]] lists generated chapters and signatures. | |||
* [[Lists and Objects]] explains lists, associative objects, mapping, and reduction. | |||
* [[IO]] covers files, HTTP request/response objects, and servers. | |||
* [[Storage]] documents the low-level table and scan interface; application code normally starts with SQL. | |||
* [[JIT Compilation]] and [[Parallel Computing]] explain runtime optimization boundaries. | |||
Latest revision as of 12:13, 28 August 2026
Introduction to Scheme
MemCP embeds a small Scheme dialect used by the SQL parsers, query planner, modules, and application endpoints. Start the interactive console with ./memcp lib/main.scm; background services use --no-repl.
Scheme represents calls and code with the same list syntax. That makes the dialect well suited to MemCP's query compiler: the SQL planner constructs Scheme programs as data, optimizes them, and evaluates or compiles them.
The console prints each expression result, which makes the evaluation model easy to explore:
> 12 = 12 > (+ 1 2 3) = 6 > (+ 2 (* 2 4)) = 10 > (concat "Hello " "World") = "Hello World"
Startup also loads the configured data directory and Scheme modules before opening the SQL/HTTP listeners. The exact banner and number of startup tests change between releases, so scripts should not parse that text.
Values and calls
(+ 1 2) (concat "hello " "world") (map '(1 2 3) (lambda (x) (* x x)))
Numbers, booleans, strings, symbols, lists, functions, sessions, and storage objects are ordinary values. A list in expression position is a call: its first item is the procedure and the rest are arguments. Whitespace separates forms; parentheses define nesting.
| Form | Meaning |
|---|---|
42, 3.5, true, "text" |
Literal values |
(+ 1 2) |
Call + with two arguments
|
'name |
The symbol name, not the value bound to it
|
'(1 2 3) |
Construct a list value instead of calling 1
|
'("name" "Ada" "active" true) |
Flat key/value list used as an associative object |
Quoting and generated code
Use quoting to build code or data: '(+ 4 5) constructs delayed code, while (eval '(+ 4 5)) evaluates it. Values that should be computed now can be embedded into a quoted outer form; procedure symbols whose execution is delayed remain quoted. This distinction matters throughout the query planner.
(set delayed '(+ 4 5)) (eval delayed) /* 9 */ (map '(1 2 3) (lambda (x) (* x x)))
Do not add or remove parentheses by visual guesswork in large generated expressions. Repository Scheme files are formatted and checked with python3 tools/lint_scm.py.
Functions and scope
Lambdas have exactly a parameter list and one body. Use begin when that body needs several forms:
(define greet (lambda (name) (begin (print "greeting " name) (concat "Hello, " name)))) (greet "Ada")
Functions are closures and may be passed to map, reducers, scanners, parsers, and handlers. define and set create a binding in the current scope in this dialect; set is not an imperative mutation of an outer lexical variable.
Pattern matching and modules
match is the usual way to express alternatives and destructure lists, strings, or regular-expression results. Modules are loaded with import; application entrypoints typically import the required library files and then install handlers or start a server.
(match value '(x y) (+ x y) (regex "^/users/([0-9]+)$" path id) id false)
See Parsers, Lists and Objects, and the matching examples in the repository for the exact pattern forms.
State and concurrency
The dialect is functional by default. set defines a binding in the current scope; it does not imperatively mutate an outer binding. Use (newsession) when code intentionally needs a thread-safe mutable key/value context shared across parallel work.
(set request_state (newsession)) (request_state "user_id" 42) (request_state "user_id") /* 42 */
Independent functional work may run in parallel. Supported hot procedures can be compiled by the native x86-64 JIT; unsupported shapes remain interpreted without changing language semantics. See Full SCM API documentation, Parallel Computing, and In-Database WebApps and REST Services.
Where to continue
- Full SCM API documentation lists generated chapters and signatures.
- Lists and Objects explains lists, associative objects, mapping, and reduction.
- IO covers files, HTTP request/response objects, and servers.
- Storage documents the low-level table and scan interface; application code normally starts with SQL.
- JIT Compilation and Parallel Computing explain runtime optimization boundaries.