Introduction to Scheme: Difference between revisions
Wikiservice (talk | contribs) (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 --> | |||
= 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 == | |||
= | <syntaxhighlight lang="scheme"> | ||
(+ 1 2) | |||
(concat "hello " "world") | |||
(map '(1 2 3) (lambda (x) (* x x))) | |||
</syntaxhighlight> | |||
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. | |||
<syntaxhighlight lang="scheme"> | |||
(set delayed '(+ 4 5)) | |||
(eval delayed) /* 9 */ | |||
(map '(1 2 3) (lambda (x) (* x x))) | |||
</syntaxhighlight> | |||
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: | |||
<syntaxhighlight lang="scheme"> | |||
(define greet (lambda (name) (begin | |||
(print "greeting " name) | |||
(concat "Hello, " name)))) | |||
(greet "Ada") | |||
</syntaxhighlight> | |||
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. | |||
<syntaxhighlight lang="scheme"> | |||
(match value | |||
'(x y) (+ x y) | |||
(regex "^/users/([0-9]+)$" path id) id | |||
false) | |||
</syntaxhighlight> | |||
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. | |||
<syntaxhighlight lang="scheme"> | |||
(set request_state (newsession)) | |||
(request_state "user_id" 42) | |||
(request_state "user_id") /* 42 */ | |||
</syntaxhighlight> | |||
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. | |||
Revision as of 11:59, 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
<syntaxhighlight lang="scheme"> (+ 1 2) (concat "hello " "world") (map '(1 2 3) (lambda (x) (* x x))) </syntaxhighlight>
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.
<syntaxhighlight lang="scheme"> (set delayed '(+ 4 5)) (eval delayed) /* 9 */ (map '(1 2 3) (lambda (x) (* x x))) </syntaxhighlight>
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:
<syntaxhighlight lang="scheme"> (define greet (lambda (name) (begin (print "greeting " name) (concat "Hello, " name))))
(greet "Ada") </syntaxhighlight>
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.
<syntaxhighlight lang="scheme"> (match value '(x y) (+ x y) (regex "^/users/([0-9]+)$" path id) id false) </syntaxhighlight>
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.
<syntaxhighlight lang="scheme"> (set request_state (newsession)) (request_state "user_id" 42) (request_state "user_id") /* 42 */ </syntaxhighlight>
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.