"@codemirror/lang-html": "^6.4.11",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/lang-xml": "^6.1.0",
+ "@mathjax/mathjax-stix2-font": "^4.1.0",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-icons": "^1.3.2",
"dotenv": "^17.2.3",
"express": "^5.2.1",
"jszip": "^3.10.1",
+ "mathjax": "^4.1.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"ua-parser-js": "^2.0.7"
"@lezer/generator": "^1.8.0",
"adm-zip": "^0.5.16",
"babel-loader": "^10.0.0",
+ "copy-webpack-plugin": "^13.0.1",
"css-loader": "^7.1.2",
"eslint": "^9.39.2",
"eslint-plugin-react-hooks": "^7.0.1",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"license": "MIT"
},
+ "node_modules/@mathjax/mathjax-newcm-font": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@mathjax/mathjax-newcm-font/-/mathjax-newcm-font-4.1.0.tgz",
+ "integrity": "sha512-n10AwYubUa2hyOzxSRzkwRrgCVns083zkentryXICMPKaWT/watfvK2sUk5D9Bow9mpDfoqb5EWApuUvqnlzaw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@mathjax/mathjax-stix2-font": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@mathjax/mathjax-stix2-font/-/mathjax-stix2-font-4.1.0.tgz",
+ "integrity": "sha512-uNRwwdyAJhdPwh7tFWrN0td+hT2lix8qDRELxNQWiH9ki1Z8Jb6NfTUzbMHyTiqZdNh2P+h1+QjPSnVlI6fsUw==",
+ "license": "Apache-2.0"
+ },
"node_modules/@nicolo-ribaudo/chokidar-2": {
"version": "2.1.8-no-fsevents.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
"node": ">=6.6.0"
}
},
+ "node_modules/copy-webpack-plugin": {
+ "version": "13.0.1",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz",
+ "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "glob-parent": "^6.0.1",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.2.0",
+ "serialize-javascript": "^6.0.2",
+ "tinyglobby": "^0.2.12"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ }
+ },
+ "node_modules/copy-webpack-plugin/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/core-js-compat": {
"version": "3.47.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz",
"node": ">= 0.4"
}
},
+ "node_modules/mathjax": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-4.1.0.tgz",
+ "integrity": "sha512-53eDXzxk40pS2sdI6KDCPoreY95ADaGygbi41ExKmn3FYQ+QIdpquIU90eppecelzQjf74kpScyeplVPccnIJw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@mathjax/mathjax-newcm-font": "^4.1.0"
+ }
+ },
"node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"dev": true,
"license": "MIT"
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"@codemirror/lang-html": "^6.4.11",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/lang-xml": "^6.1.0",
+ "@mathjax/mathjax-stix2-font": "^4.1.0",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-icons": "^1.3.2",
"dotenv": "^17.2.3",
"express": "^5.2.1",
"jszip": "^3.10.1",
+ "mathjax": "^4.1.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"ua-parser-js": "^2.0.7"
"@lezer/generator": "^1.8.0",
"adm-zip": "^0.5.16",
"babel-loader": "^10.0.0",
+ "copy-webpack-plugin": "^13.0.1",
"css-loader": "^7.1.2",
"eslint": "^9.39.2",
"eslint-plugin-react-hooks": "^7.0.1",
const jsURL = URL.createObjectURL(jsBlob);
const state = this.transaction.state;
const text = state.sliceDoc();
- const html = text.replaceAll('___cssURL___', cssURL).replaceAll('___jsURL___', jsURL).replaceAll('___windowId___', window.id);
+ let html = text;
+ html = html.replaceAll('___cssURL___', cssURL);
+ html = html.replaceAll('___jsURL___', jsURL);
+ html = html.replaceAll('___windowId___', window.id);
setTimeout(() => toggleHTMLModeCommand2(ide, window, html, cssURL, jsURL));
}
}
<p>This section introduces the global functions and macros that will be used in the tutorial. Some global functions and macros are included for the sake of completeness and will not actually be used in the tutorial.</p>
<p>In template function calls, argument names imply the following type restrictions:</p>
<ul>
- <li>Arguments named <i>object</i>, with or without a subscript, can be of any type.</li>
- <li>Arguments named <i>boolean</i>, with or without a subscript, must be of type <code>boolean</code>.</li>
- <li>Arguments named <i>number</i>, with or without a subscript, must be of type <code>number</code>.</li>
- <li>Arguments named <i>cons</i>, with or without a subscript, must be of type <code>cons</code>.</li>
+ <li>Arguments named $\object$, with or without a subscript, can be of any type.</li>
+ <li>Arguments named $\boolean$, with or without a subscript, must be of type <code>boolean</code>.</li>
+ <li>Arguments named $\number$, with or without a subscript, must be of type <code>number</code>.</li>
+ <li>Arguments named $\cons$, with or without a subscript, must be of type <code>cons</code>.</li>
</ul>
<p>In template macro calls, names enclosed in angle brackets have the following meanings:</p>
<ul>
- <li><code><test-forms></code> matches any sequence of zero or more objects</li>
- <li><code><variable></code> matches any variable</li>
- <li><code><value-form></code> matches any object</li>
- <li><code><parameter-list></code> matches any list of distinct variables</li>
- <li><code><body></code> matches any sequence of zero or more objects</li>
+ <li>$\metavar{test-forms}$ matches any sequence of zero or more objects</li>
+ <li>$\metavar{variable}$ matches any variable</li>
+ <li>$\metavar{value-form}$ matches any object</li>
+ <li>$\metavar{parameter-list}$ matches any list of distinct variables</li>
+ <li>$\metavar{body}$ matches any sequence of zero or more objects</li>
</ul>
<p>It is customary for a function or macro that tests a condition and returns a boolean to have a name ending with a question mark. This rule has some notable exceptions, though.</p>
<h3>Data Type <code>boolean</code></h3>
<dl>
- <dt><code>(not <i>boolean</i>)</code></dt>
+ <dt><code>(not $\boolean$)</code></dt>
<dd>The function returns <code>#t</code> if its argument is <code>#f</code> and <code>#f</code> if its argument is <code>#t</code>.</dd>
</dl>
<pre class="repl">> (not #t)<br>#f<br><br>> (not #f)<br>#t</pre>
<dl>
- <dt><code>(and <test-forms>)</code></dt>
+ <dt><code>(and $\metavar{test-forms}$)</code></dt>
<dd>The macro returns <code>#t</code> if all its arguments are <code>#t</code> and <code>#f</code> otherwise. The exact behavior of the macro is as follows: The macro evaluates the test-forms in sequence from left to right. If a test-form evaluates to an object that is not a boolean, then the following test-forms are not evaluated and the evaluation of the macro call completes abnormally. If a test-form evaluates to <code>#f</code>, then the following test-forms are not evaluated and the macro call evaluates to <code>#f</code>. If all test-forms evaluate to <code>#t</code>, then the macro call evaluates to <code>#t</code>. Note that the previous condition is automatically satisfied if there are no test-forms.</dd>
</dl>
<pre class="repl">> (and)<br>#t<br><br>> (and #t)<br>#t<br><br>> (and #f)<br>#f<br><br>> (and #t #t)<br>#t<br><br>> (and #t #f)<br>#f<br><br>> (and #f #t)<br>#f<br><br>> (and #f #f)<br>#f</pre>
<dl>
- <dt><code>(or <test-forms>)</code></dt>
+ <dt><code>(or $\metavar{test-forms}$)</code></dt>
<dd>The macro returns <code>#f</code> if all its arguments are <code>#f</code> and <code>#t</code> otherwise. The exact behavior of the macro is as follows: The macro evaluates the test-forms in sequence from left to right. If a test-form evaluates to an object that is not a boolean, then the following test-forms are not evaluated and the evaluation of the macro call completes abnormally. If a test-form evaluates to <code>#t</code>, then the following test-forms are not evaluated and the macro call evaluates to <code>#t</code>. If all test-forms evaluate to <code>#f</code>, then the macro call evaluates to <code>#f</code>. Note that the previous condition is automatically satisfied if there are no test-forms.</dd>
</dl>
<pre class="repl">> (or)<br>#f<br><br>> (or #t)<br>#t<br><br>> (or #f)<br>#f<br><br>> (or #t #t)<br>#t<br><br>> (or #t #f)<br>#t<br><br>> (or #f #t)<br>#t<br><br>> (or #f #f)<br>#f</pre>
<p>The macros <code>and</code> and <code>or</code> stop evaluating their operands as soon as they can determine that the result of the macro call is definitively true or definitively false. This short-circuiting behavior is possible only because <code>and</code> and <code>or</code> are macros. When a function call is evaluated, all the operands are always evaluated (unless the evaluation of the operator or the evaluation of one of the operands other than the last one completes abnormally or does not complete).</p>
<p>Here are two expansions illustrating the implementations of the macros <code>and</code> and <code>or</code>:</p>
<ul>
- <li><code>(and <test-form-1> <test-form-2> <test-form-3>)</code> expands into<br><code>(if <test-form-1> (if <test-form-2> (if <test-form-3> #t #f) #f) #f)</code></li>
- <li><code>(or <test-form-1> <test-form-2> <test-form-3>)</code> expands into<br><code>(if <test-form-1> #t (if <test-form-2> #t (if <test-form-3> #t #f)))</code></li>
+ <li><code>(and $\metavarn{test-form}{1}$ $\metavarn{test-form}{2}$ $\metavarn{test-form}{3}$)</code> expands into<br><code>(if $\metavarn{test-form}{1}$ (if $\metavarn{test-form}{2}$ (if $\metavarn{test-form}{3}$ #t #f) #f) #f)</code></li>
+ <li><code>(or $\metavarn{test-form}{1}$ $\metavarn{test-form}{2}$ $\metavarn{test-form}{3}$)</code> expands into<br><code>(if $\metavarn{test-form}{1}$ #t (if $\metavarn{test-form}{2}$ #t (if $\metavarn{test-form}{3}$ #t #f)))</code></li>
</ul>
<p>The name of the function <code>not</code> and the names of the macros <code>and</code> and <code>or</code> do not end with a question mark because the function and the macros do not really test a condition. Instead, they combine booleans (they are boolean operators).</p>
<h3>Data Type <code>number</code></h3>
<h4>Arithmetic Operators</h4>
<dl>
- <dt><code>(+ <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(+ $\number_1\ldots\number_n$)</code></dt>
<dd>If the function is invoked on zero numbers, then the number <code>0</code> is returned. If the function is invoked on one number, then that number is returned. If the function is invoked on more than one number, then the result of adding those numbers from left to right is returned: the second number is added to the first number, then the third number is added to the partial result just computed, … The function is a closure built on top of the primitive function <code>_+</code>, which must be invoked on exactly two numbers.</dd>
</dl>
<pre class="repl">> (+)<br>0<br><br>> (+ 1)<br>1<br><br>> (+ 1 2)<br>3<br><br>> (+ 1 2 3)<br>6</pre>
<dl>
- <dt><code>(- <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(- $\number_1\ldots\number_n$)</code></dt>
<dd>If the function is invoked on zero numbers, then the invocation completes abnormally. If the function is invoked on one number, then the opposite of that number is returned. If the function is invoked on more than one number, then the result of subtracting those numbers from left to right is returned: the second number is subtracted from the first number, then the third number is subtracted from the partial result just computed, … The function is a closure built on top of the primitive function <code>_-</code>, which must be invoked on exactly two numbers.</dd>
</dl>
<pre class="repl">> (-)<br>ERROR: Expecting at least one number.<br><br>> (- 1)<br>-1<br><br>> (- 0 1)<br>-1<br><br>> (- 0 1 2)<br>-3<br><br>> (- 0 1 2 3)<br>-6</pre>
<dl>
- <dt><code>(* <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(* $\number_1\ldots\number_n$)</code></dt>
<dd>If the function is invoked on zero numbers, then the number <code>1</code> is returned. If the function is invoked on one number, then that number is returned. If the function is invoked on more than one number, then the result of multiplying those numbers from left to right is returned: the first number is multiplied by the second number, then the partial result just computed is multiplied by the third number, … The function is a closure built on top of the primitive function <code>_*</code>, which must be invoked on exactly two numbers.</dd>
</dl>
<pre class="repl">> (*)<br>1<br><br>> (* 2)<br>2<br><br>> (* 2 4)<br>8<br><br>> (* 2 4 8)<br>64</pre>
<dl>
- <dt><code>(/ <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(/ $\number_1\ldots\number_n$)</code></dt>
<dd>If the function is invoked on zero numbers, then the invocation completes abnormally. If the function is invoked on one number, then the inverse of that number is returned. If the function is invoked on more than one number, then the result of dividing those numbers from left to right is returned: the first number is divided by the second number, then the partial result just computed is divided by the third number, … The function is a closure built on top of the primitive function <code>_/</code>, which must be invoked on exactly two numbers.</dd>
</dl>
<pre class="repl">> (/)<br>ERROR: Expecting at least one number.<br><br>> (/ 2)<br>0.5<br><br>> (/ 1 2)<br>0.5<br><br>> (/ 1 2 4)<br>0.125<br><br>> (/ 1 2 4 8)<br>0.015625</pre>
<h4>Comparison Operators</h4>
<dl>
- <dt><code>(= <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(= $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its two arguments are equal and <code>#f</code> otherwise.</dd>
- <dt><code>(/= <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(/= $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its two arguments are different and <code>#f</code> otherwise.</dd>
- <dt><code>(< <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(< $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its first argument is less than its second argument and <code>#f</code> otherwise.</dd>
- <dt><code>(<= <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(<= $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its first argument is less than or equal to its second argument and <code>#f</code> otherwise.</dd>
- <dt><code>(> <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(> $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its first argument is greater than its second argument and <code>#f</code> otherwise.</dd>
- <dt><code>(>= <i>number<sub>1</sub></i> <i>number<sub>2</sub></i>)</code></dt>
+ <dt><code>(>= $\number_1$ $\number_2$)</code></dt>
<dd>The function returns <code>#t</code> if its first argument is greater than or equal to its second argument and <code>#f</code> otherwise.</dd>
</dl>
<pre class="repl">> (list (= -1 0) (= 0 0) (= 1 0))<br>(#f #t #f)<br><br>> (list (/= -1 0) (/= 0 0) (/= 1 0))<br>(#t #f #t)<br><br>> (list (< -1 0) (< 0 0) (< 1 0))<br>(#t #f #f)<br><br>> (list (<= -1 0) (<= 0 0) (<= 1 0))<br>(#t #t #f)<br><br>> (list (> -1 0) (> 0 0) (> 1 0))<br>(#f #f #t)<br><br>> (list (>= -1 0) (>= 0 0) (>= 1 0))<br>(#f #t #t)</pre>
<p>The names of the comparison operators do not end with a question mark because they traditionally do not (in mathematics and other programming languages).</p>
<h3>Data Type <code>list</code></h3>
<dl>
- <dt><code>(list? <i>object</i>)</code></dt>
+ <dt><code>(list? $\object$)</code></dt>
<dd>The function returns <code>#t</code> if its argument is of type <code>list</code> and <code>#f</code> otherwise.</dd>
</dl>
<pre class="repl">> (list? '())<br>#t<br><br>> (list? '(1 2 3))<br>#t</pre>
<dl>
- <dt><code>(list <i>object<sub>1</sub></i> … <i>object<sub>n</sub></i>)</code></dt>
- <dd>The function collects its arguments into a list: when invoked on the arguments <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>, the function returns a list whose elements are <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>.</dd>
+ <dt><code>(list $\object_1\ldots\object_n$)</code></dt>
+ <dd>The function collects its arguments into a list: when invoked on the arguments $\object_1$, …, $\object_n$, the function returns a list whose elements are $\object_1$, …, $\object_n$.</dd>
</dl>
<pre class="repl">> (list)<br>()<br><br>> (list 1 2 3)<br>(1 2 3)</pre>
<h3>Data Type <code>empty-list</code></h3>
<dl>
- <dt><code>(empty-list? <i>object</i>)</code></dt>
+ <dt><code>(empty-list? $\object$)</code></dt>
<dd>The function returns <code>#t</code> if its argument is of type <code>empty-list</code> and <code>#f</code> otherwise.</dd>
</dl>
<pre class="repl">> (empty-list? '())<br>#t<br><br>> (empty-list? '(1 2 3))<br>#f</pre>
<h3>Data Type <code>cons</code></h3>
<dl>
- <dt><code>(cons? <i>object</i>)</code></dt>
+ <dt><code>(cons? $\object$)</code></dt>
<dd>The function returns <code>#t</code> if its argument is of type <code>cons</code> and <code>#f</code> otherwise.</dd>
</dl>
<pre class="repl">> (cons? '())<br>#f<br><br>> (cons? '(1 2 3))<br>#t</pre>
<dl>
- <dt><code>(cons <i>object<sub>1</sub></i> <i>object<sub>2</sub></i>)</code></dt>
- <dd>The function returns a new cons whose first element is <i>object<sub>1</sub></i> and whose second element is <i>object<sub>2</sub></i>.</dd>
+ <dt><code>(cons $\object_1$ $\object_2$)</code></dt>
+ <dd>The function returns a new cons whose first element is $\object_1$ and whose second element is $\object_2$.</dd>
</dl>
<pre class="repl">> (cons 3 '())<br>(3)<br><br>> (cons 2 (cons 3 '()))<br>(2 3)<br><br>> (cons 1 (cons 2 (cons 3 '())))<br>(1 2 3)</pre>
<dl>
- <dt><code>(car <i>cons</i>)</code></dt>
+ <dt><code>(car $\cons$)</code></dt>
<dd>The function returns the first element of its argument.</dd>
- <dt><code>(cdr <i>cons</i>)</code></dt>
+ <dt><code>(cdr $\cons$)</code></dt>
<dd>The function returns the second element of its argument.</dd>
</dl>
<pre class="repl">> (car '(1 2 3))<br>1<br><br>> (cdr '(1 2 3))<br>(2 3)<br><br>> (car (cdr '(1 2 3)))<br>2<br><br>> (cdr (cdr '(1 2 3)))<br>(3)<br><br>> (car (cdr (cdr '(1 2 3))))<br>3<br><br>> (cdr (cdr (cdr '(1 2 3))))<br>()</pre>
<h3>Equality Predicates</h3>
<p>The purpose of an equality predicate is to test the sameness of two objects. An equality predicate returns <code>#t</code> if the two objects are the same and <code>#f</code> otherwise. Because there are multiple notions of sameness, there are multiple equality predicates. The three main equality predicates are <code>eq?</code>, <code>eql?</code>, and <code>equal?</code>.</p>
<dl>
- <dt><code>(eq? <i>object<sub>1</sub></i> <i>object<sub>2</sub></i>)</code></dt>
+ <dt><code>(eq? $\object_1$ $\object_2$)</code></dt>
<dd>The function returns <code>#t</code> if and only if the two objects are one and the same. In other words, the function returns <code>#t</code> if and only if the two objects have the same address in the heap.</dd>
- <dt><code>(eql? <i>object<sub>1</sub></i> <i>object<sub>2</sub></i>)</code></dt>
+ <dt><code>(eql? $\object_1$ $\object_2$)</code></dt>
<dd>If both objects are of type <code>number</code>, then the function returns <code>#t</code> if and only if the two objects represent the same mathematical number. Otherwise, if both objects are of type <code>character</code>, then the function returns <code>#t</code> if and only if the two objects represent the same Unicode character. Otherwise, if both objects are of type <code>string</code>, then the function returns <code>#t</code> if and only if the two objects represent the same indexed sequence of Unicode characters. Otherwise, the function returns <code>#t</code> if and only if the two objects are <code>eq?</code>.</dd>
- <dt><code>(equal? <i>object<sub>1</sub></i> <i>object<sub>2</sub></i>)</code></dt>
+ <dt><code>(equal? $\object_1$ $\object_2$)</code></dt>
<dd>If both objects are of type <code>cons</code>, then the function returns <code>#t</code> if and only if the cars of the two objects are <code>equal?</code> and the cdrs of the two objects are <code>equal?</code>. Otherwise, if both objects are of type <code>vector</code>, then the function returns <code>#t</code> if and only if the two objects have the same length and their corresponding elements are <code>equal?</code>. Otherwise, the function returns <code>#t</code> if and only if the two objects are <code>eql?</code>.</dd>
</dl>
<p>The three main equality predicates are related as follows:</p>
<ul>
- <li>When testing the sameness of two objects of type <code>void</code>, <code>boolean</code>, <code>keyword</code>, <code>variable</code>, <code>empty-list</code>, <code>primitive-function</code>, or <code>closure</code>, equality under <code>eq?</code> is equivalent to equality under <code>eql?</code> and equality under <code>eql?</code> is equivalent to equality under <code>equal?</code>.</li>
- <li>When testing the sameness of two objects of type <code>number</code>, <code>character</code>, or <code>string</code>, equality under <code>eq?</code> implies equality under <code>eql?</code> (but the converse is not true) and equality under <code>eql?</code> is equivalent to equality under <code>equal?</code>.</li>
- <li>When testing the sameness of two objects of type <code>cons</code> or <code>vector</code>, equality under <code>eq?</code> is equivalent to equality under <code>eql?</code> and equality under <code>eql?</code> implies equality under <code>equal?</code> (but the converse is not true).</li>
+ <li>When testing the sameness of two objects of different leaf types, <code>eq?</code>, <code>eql?</code>, and <code>equal?</code> all return <code>#f</code>.</li>
+ <li>When testing the sameness of two objects of type <code>void</code>, two objects of type <code>boolean</code>, two objects of type <code>keyword</code>, two objects of type <code>variable</code>, two objects of type <code>empty-list</code>, two objects of type <code>primitive-function</code>, or two objects of type <code>closure</code>, equality under <code>eq?</code> is equivalent to equality under <code>eql?</code> and equality under <code>eql?</code> is equivalent to equality under <code>equal?</code>.</li>
+ <li>When testing the sameness of two objects of type <code>number</code>, two objects of type <code>character</code>, or two objects of type <code>string</code>, equality under <code>eq?</code> implies equality under <code>eql?</code> (but the converse is not true) and equality under <code>eql?</code> is equivalent to equality under <code>equal?</code>.</li>
+ <li>When testing the sameness of two objects of type <code>cons</code> or two objects of type <code>vector</code>, equality under <code>eq?</code> is equivalent to equality under <code>eql?</code> and equality under <code>eql?</code> implies equality under <code>equal?</code> (but the converse is not true).</li>
</ul>
<p>Of the three main equality predicates, <code>eq?</code> is the most discriminating and <code>equal?</code> is the least discriminating.</p>
<p>Because the three main equality predicates all return <code>#f</code> when testing the sameness of two objects of different leaf types, which one to use depends only on their behaviors when testing the sameness of two objects of the same leaf type.</p>
- <p>Because there exists in the heap exactly one object of type <code>void</code>, two objects of type <code>void</code> are necessarily one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>void</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>. (The fact that there exists in the heap exactly one object of type <code>void</code> means that the language cannot distinguish between two different missing objects, or two different undefined objects, or one missing object and one undefined object.)</p>
+ <p>By design, any two objects of type <code>void</code> are considered to be the same object. Because there exists in the heap exactly one object of type <code>void</code>, two objects of type <code>void</code> are necessarily one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>void</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>.</p>
<p>When testing the sameness of two objects of type <code>boolean</code>, we want to test if the two objects represent the same truth value. Because there exists in the heap exactly one object of type <code>boolean</code> representing true and exactly one object of type <code>boolean</code> representing false, representing the same truth value is equivalent to being one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>boolean</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>.</p>
<p>When testing the sameness of two objects of type <code>number</code>, we want to test if the two objects represent the same mathematical number. Because there can exist in the heap more than one object of type <code>number</code> representing the same mathematical number, representing the same mathematical number is not equivalent to being one and the same. Therefore, <code>eq?</code> is not an appropriate equality predicate to test the sameness of two objects of type <code>number</code>. The appropriate equality predicates are <code>eql?</code> and the equivalent <code>equal?</code>.</p>
<p>When testing the sameness of two objects of type <code>character</code>, we want to test if the two objects represent the same Unicode character. Because there can exist in the heap more than one object of type <code>character</code> representing the same Unicode character, representing the same Unicode character is not equivalent to being one and the same. Therefore, <code>eq?</code> is not an appropriate equality predicate to test the sameness of two objects of type <code>character</code>. The appropriate equality predicates are <code>eql?</code> and the equivalent <code>equal?</code>.</p>
<p>When testing the sameness of two objects of type <code>string</code>, we want to test if the two objects represent the same indexed sequence of Unicode characters. Because there can exist in the heap more than one object of type <code>string</code> representing the same indexed sequence of Unicode characters, representing the same indexed sequence of Unicode characters is not equivalent to being one and the same. Therefore, <code>eq?</code> is not an appropriate equality predicate to test the sameness of two objects of type <code>string</code>. The appropriate equality predicates are <code>eql?</code> and the equivalent <code>equal?</code>.</p>
- <p>Using <code>eq?</code> to test the sameness of two objects of type <code>number</code>, <code>character</code>, or <code>string</code> is never safe because the evaluator is free to make copies of objects of those types at any time. Let's illustrate the point by considering the form <code>((_vlambda (x) (eq? x x)) 0)</code>. It is not guaranteed that the object of type <code>number</code> created by the reader, the value of the variable <code>x</code>, the first argument passed to the function <code>eq?</code>, and the second argument passed to the function <code>eq?</code> are one and the same. If the two objects passed to the function <code>eq?</code> are one and the same, then the test evaluates to <code>#t</code>. If the two objects passed to the function <code>eq?</code> are not one and the same, then the test evaluates to <code>#f</code>. Even in this seemingly straightforward case, the result of the test is unpredictable. The same goes for objects of type <code>character</code> or <code>string</code>.</p>
- <p>The identity of an object of type <code>keyword</code> or <code>variable</code> is determined by its name. When testing the sameness of two objects of type <code>keyword</code> or <code>variable</code>, we want to test if the two objects have the same name. Because there cannot exist in the heap more than one object of type <code>keyword</code> or <code>variable</code> with the same name, having the same name is equivalent to being one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>keyword</code> or <code>variable</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>.</p>
- <p>Because there exists in the heap exactly one object of type <code>empty-list</code>, two objects of type <code>empty-list</code> are necessarily one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>empty-list</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>. (The fact that there exists in the heap exactly one object of type <code>empty-list</code> means that the language cannot distinguish between two different empty lists of objects.)</p>
- <p>When testing the sameness of two objects of type <code>cons</code> or two objects of type <code>vector</code>, we can use <code>eq?</code> or the equivalent <code>eql?</code> to test if the two objects are one and the same or we can use <code>equal?</code> to test if the two objects have the same elements.</p>
+ <p>Using <code>eq?</code> to test the sameness of two objects of type <code>number</code>, two objects of type <code>character</code>, or two objects of type <code>string</code> is never safe because the evaluator is free to make copies of objects of those types at any time. Let us illustrate the point by considering the form <code>((_vlambda (x) (eq? x x)) 0)</code>. It is not guaranteed that the object of type <code>number</code> created by the reader, the value of the variable <code>x</code>, the first argument passed to the function <code>eq?</code>, and the second argument passed to the function <code>eq?</code> are one and the same. If the two objects passed to the function <code>eq?</code> happen to be one and the same, then the test evaluates to <code>#t</code>. If the two objects passed to the function <code>eq?</code> happen not to be one and the same, then the test evaluates to <code>#f</code>. Even in this seemingly straightforward case, the result of the test is unpredictable. The same goes for objects of type <code>character</code> and <code>string</code>.</p>
+ <p>By design, any two objects of type <code>keyword</code>/<code>variable</code> sharing the same name are considered to be the same object. Because there cannot exist in the heap more than one object of type <code>keyword</code>/<code>variable</code> with the same name, having the same name is equivalent to being one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>keyword</code>/<code>variable</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>.</p>
+ <p>By design, any two objects of type <code>empty-list</code> are considered to be the same object. Because there exists in the heap exactly one object of type <code>empty-list</code>, two objects of type <code>empty-list</code> are necessarily one and the same. Therefore, the appropriate equality predicates to test the sameness of two objects of type <code>empty-list</code> are <code>eq?</code> and the equivalent <code>eql?</code> and <code>equal?</code>.</p>
+ <p>When testing the sameness of two objects of type <code>cons</code> or two objects of type <code>vector</code>, we can use <code>eq?</code> or the equivalent <code>eql?</code> to test if the two objects are one and the same or we can use <code>equal?</code> to test if the two objects have the same elements. Whether to use (1) <code>eq?</code> or the equivalent <code>eql?</code> or (2) <code>equal?</code> is usually obvious from the purpose of the test.</p>
<p>When testing the sameness of two objects of type <code>primitive-function</code> or two objects of type <code>closure</code>, we would like to test if the two objects have the same behavior (same input/output mapping and same side effects). In practice, we can only test if the two objects are one and the same by using <code>eq?</code> or the equivalent <code>eql?</code> and <code>equal?</code>. For objects of type <code>primitive-function</code>, being one and the same is equivalent to having the same behavior. For objects of type <code>closure</code>, being one and the same implies having the same behavior but the converse is not true.</p>
- <p>When testing the sameness of two objects that can each be of type <i>type<sub>1</sub></i>, <i>type<sub>2</sub></i>, …, we must use an equality predicate that is appropriate to test the sameness of two objects of type <i>type<sub>1</sub></i>, two objects of type <i>type<sub>2</sub></i>, ….</p>
- <p>As a matter of style, when more than one equality predicate is appropriate, we should use the most discriminating one. As a matter of style again, when testing the sameness of two objects that can only be of type <code>number</code>, we should use the comparison operator <code>=</code> instead of the equality predicate <code>eql?</code>.</p>
+ <p>When testing the sameness of two objects that can each be of type $type_1$, $type_2$, …, an equality predicate that is appropriate to test the sameness of two objects of type $type_1$, two objects of type $type_2$, … must be used.</p>
+ <p>As a matter of style, when more than one equality predicate is appropriate, the most discriminating one should be used. As a matter of style again, when testing the sameness of two objects that can only be of type <code>number</code>, the comparison operator <code>=</code> should be used instead of the equality predicate <code>eql?</code>.</p>
<h3>Global Definitions</h3>
<dl>
- <dt><code>(vdef <variable> <value-form>)</code></dt>
+ <dt><code>(vdef $\metavar{variable}$ $\metavar{value-form}$)</code></dt>
<dd>The purpose of the macro is to define a global variable by ensuring that the variable is bound in the value namespace of the global environment to the primary value of the value-form. The macro call evaluates to the variable.</dd>
- <dt><code>(fdef <variable> <parameter-list> <body>)</code></dt>
- <dd>The purpose of the macro is to define a global function by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the _vlambda-form <code>(_vlambda <parameter-list> <body>)</code>. The macro call evaluates to the variable.</dd>
- <dt><code>(mdef <variable> <parameter-list> <body>)</code></dt>
- <dd>The purpose of the macro is to define a global macro by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the _mlambda-form <code>(_mlambda <parameter-list> <body>)</code>. The macro call evaluates to the variable.</dd>
+ <dt><code>(fdef $\metavar{variable}$ $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dd>The purpose of the macro is to define a global function by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the <code>_vlambda</code>-form <code>(_vlambda $\metavar{parameter-list}$ $\metavar{body}$)</code>. The macro call evaluates to the variable.</dd>
+ <dt><code>(mdef $\metavar{variable}$ $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dd>The purpose of the macro is to define a global macro by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the <code>_mlambda</code>-form <code>(_mlambda $\metavar{parameter-list}$ $\metavar{body}$)</code>. The macro call evaluates to the variable.</dd>
</dl>
<h2>Evaluation and Invocation Traces</h2>
<p>An evaluation trace is a structured recording of some or all of the evaluations, invocations, and various steps performed by the evaluator to evaluate a form. It is assumed that the evaluation of the form completes normally, which implies that all evaluations and invocations entailed by the evaluation of the form also complete normally. Evaluation traces have the following format:</p>
<ul>
<li>An evaluation trace is a sequence of lines.</li>
<li>Times flows from top to bottom.</li>
- <li>Each recorded evaluation contributes two lines to the trace: an eval-in line of the form “The form <i>form</i> is evaluated with respect to <i>lexenv</i> and <i>dynenv</i>.” recording the start of the evaluation and a matching eval-out line of the form “The form <i>form</i> evaluates to <i>obj<sub>1</sub></i>, …, <i>obj<sub>n</sub></i>.” recording the normal completion of the evaluation.</li>
- <li>Each recorded invocation contributes two lines to the trace: an invoke-in line of the form “The function <i>fun</i> is invoked on <i>obj<sub>1</sub></i>, …, <i>obj<sub>n</sub></i>.” recording the start of the invocation and a matching invoke-out line of the form “The function <i>fun</i> returns <i>obj<sub>1</sub></i>, …, <i>obj<sub>n</sub></i>.” recording the normal completion of the invocation.</li>
+ <li>Each recorded evaluation contributes two lines to the trace: an eval-in line of the form “The form $\form$ is evaluated with respect to $\lexenv$ and $\dynenv$.” recording the start of the evaluation and a matching eval-out line of the form “The form $\form$ evaluates to $\obj_1$, …, $\obj_n$.” recording the normal completion of the evaluation.</li>
+ <li>Each recorded invocation contributes two lines to the trace: an invoke-in line of the form “The function $\fun$ is invoked on $\obj_1$, …, $\obj_n$.” recording the start of the invocation and a matching invoke-out line of the form “The function $\fun$ returns $\obj_1$, …, $\obj_n$.” recording the normal completion of the invocation.</li>
<li>A step line is a free-form line recording a step other than an evaluation or invocation.</li>
<li>A comment line is a free-form line in italic type containing a comment.</li>
- <li>Lexical and dynamic environments are represented as <code>[<i>binding<sub>1</sub></i>,…,<i>binding<sub>n</sub></i>]</code> where bindings in the value namespace are represented as <code><i>var</i>→<sub>v</sub><i>obj</i></code> and bindings in the function namespace are represented as <code><i>var</i>→<sub>f</sub><i>obj</i></code>.</li>
+ <li>Lexical and dynamic environments are represented as $[\binding_1,\ldots,\binding_n]$ where bindings in the value namespace are represented as $\var\vbind\obj$ and bindings in the function namespace are represented as $\var\fbind\obj$.</li>
</ul>
<p>An evaluation trace is a tool used to illustrate a point. Any evaluation, invocation, or step that is not necessary to illustrate the point can be omitted from the evaluation trace. The only constraint is that if an evaluation or invocation is included in the evaluation trace, then both the in line and the matching out line must be included.</p>
- <p>Let <i>X</i> be an evaluation or invocation and <i>Y</i> be another evaluation or invocation. A consequence of the evaluation rules is that <i>X</i> and <i>Y</i> cannot overlap. If we place <i>X</i>-in, <i>X</i>-out, <i>Y</i>-in, and <i>Y</i>-out on a line where time flows from left to right, there are four possible configurations and two impossible configurations:</p>
+ <p>Let $X$ be an evaluation or invocation and $Y$ be another evaluation or invocation. A consequence of the evaluation rules is that $X$ and $Y$ cannot overlap. If we place $X$-in, $X$-out, $Y$-in, and $Y$-out on a line where time flows from left to right, there are four possible configurations and two impossible configurations:</p>
<ul>
- <li>possible (<i>X</i> precedes <i>Y</i>): — <i>X</i>-in — <i>X</i>-out — <i>Y</i>-in — <i>Y</i>-out —</li>
- <li>possible (<i>Y</i> precedes <i>X</i>): — <i>Y</i>-in — <i>Y</i>-out — <i>X</i>-in — <i>X</i>-out —</li>
- <li>possible (<i>Y</i> is nested inside <i>X</i>): — <i>X</i>-in — <i>Y</i>-in — <i>Y</i>-out — <i>X</i>-out —</li>
- <li>possible (<i>X</i> is nested inside <i>Y</i>): — <i>Y</i>-in — <i>X</i>-in — <i>X</i>-out — <i>Y</i>-out —</li>
- <li>impossible (<i>X</i> and <i>Y</i> overlap): — <i>X</i>-in — <i>Y</i>-in — <i>X</i>-out — <i>Y</i>-out —</li>
- <li>impossible (<i>X</i> and <i>Y</i> overlap): — <i>Y</i>-in — <i>X</i>-in — <i>Y</i>-out — <i>X</i>-out —</li>
+ <li>possible ($X$ precedes $Y$): — $X$-in — $X$-out — $Y$-in — $Y$-out —</li>
+ <li>possible ($Y$ precedes $X$): — $Y$-in — $Y$-out — $X$-in — $X$-out —</li>
+ <li>possible ($Y$ is nested inside $X$): — $X$-in — $Y$-in — $Y$-out — $X$-out —</li>
+ <li>possible ($X$ is nested inside $Y$): — $Y$-in — $X$-in — $X$-out — $Y$-out —</li>
+ <li>impossible ($X$ and $Y$ overlap): — $X$-in — $Y$-in — $X$-out — $Y$-out —</li>
+ <li>impossible ($X$ and $Y$ overlap): — $Y$-in — $X$-in — $Y$-out — $X$-out —</li>
</ul>
- <p>To make nesting more obvious, the lines located between a pair of matching in and out lines are indented to the right with respect to the matching lines. To make the connection between an in line and the matching out line more obvious, non-adjacent matching lines are connected by a vertical line.</p>
+ <p>To make nesting more obvious, the lines located between a pair of matching in and out lines are indented to the right with respect to the matching lines. To make the connection between an in line and the matching out line more obvious, nonadjacent matching lines are connected by a vertical line.</p>
<p>An invocation trace is an evaluation trace that only records invocations. Macro invocations are almost always omitted from an invocation trace.</p>
- <p>Here is an evaluation trace of the evaluation of the form <code>(+ 1 2)</code>. It will be assumed, wrongly, that the definition of the global function <code>+</code> is <code>(fdef + (x y) (_+ x y))</code>:</p>
+ <p>Here is an evaluation trace of the evaluation of the top-level form <code>(+ 1 2)</code>. It will be assumed, wrongly, that the definition of the global function <code>+</code> is <code>(fdef + (x y) (_+ x y))</code>:</p>
<div class="trace">
<ul>
- <li>The form <code>(+ 1 2)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(+ 1 2)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(+ 1 2)</code> is classified as a function call.</li>
+ <li>The form <code>(+ 1 2)</code> is classified as a plain function call.</li>
<li>The variable <code>+</code> is treated as an abbreviation for <code>(fref +)</code>.</li>
- <li>The form <code>(fref +)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(fref +)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(fref +)</code> is classified as an fref-form.</li>
+ <li>The form <code>(fref +)</code> is classified as an <code>fref</code>-form.</li>
<li>The variable <code>+</code> is looked up.</li>
</ul>
</li>
<li>The form <code>(fref +)</code> evaluates to the global function <code>+</code>.</li>
- <li>The form <code>1</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>1</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>1</code> is classified as a self-evaluating form.</li>
+ <li>The form <code>1</code> is classified as a self-evaluating object.</li>
</ul>
</li>
<li>The form <code>1</code> evaluates to the number <code>1</code>.</li>
- <li>The form <code>2</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>2</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>2</code> is classified as a self-evaluating form.</li>
+ <li>The form <code>2</code> is classified as a self-evaluating object.</li>
</ul>
</li>
<li>The form <code>2</code> evaluates to the number <code>2</code>.</li>
<li>The global function <code>+</code> is invoked on the numbers <code>1</code> and <code>2</code>.</li>
<li>
<ul>
- <li><i>The global function <code>+</code> is a closure recording the following two pieces of information: the _vlambda-form <code>(_vlambda (x y) (_+ x y))</code> and the lexical environment <code>[]</code>.</i></li>
- <li>A new lexical environment is created that extends the lexical environment <code>[]</code> to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code> and the variable <code>y</code> to the number <code>2</code>.</li>
- <li>The form <code>(_+ x y)</code> is evaluated with respect to <code>[x→<sub>v</sub>1,y→<sub>v</sub>2]</code> and <code>[]</code>.</li>
+ <li><i>The global function <code>+</code> is a closure recording the following two pieces of information: the <code>_vlambda</code>-form <code>(_vlambda (x y) (_+ x y))</code> and the lexical environment $[]$.</i></li>
+ <li>A new lexical environment is created that extends the lexical environment $[]$ to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code> and the variable <code>y</code> to the number <code>2</code>.</li>
+ <li>The form <code>(_+ x y)</code> is evaluated with respect to $[\vbinding{x}{1},\vbinding{y}{2}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(_+ x y)</code> is classified as a function call.</li>
+ <li>The form <code>(_+ x y)</code> is classified as a plain function call.</li>
<li>The variable <code>_+</code> is treated as an abbreviation for <code>(fref _+)</code>.</li>
- <li>The form <code>(fref _+)</code> is evaluated with respect to <code>[x→<sub>v</sub>1,y→<sub>v</sub>2]</code> and <code>[]</code>.</li>
+ <li>The form <code>(fref _+)</code> is evaluated with respect to $[\vbinding{x}{1},\vbinding{y}{2}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(fref _+)</code> is classified as an fref-form.</li>
+ <li>The form <code>(fref _+)</code> is classified as an <code>fref</code>-form.</li>
<li>The variable <code>_+</code> is looked up.</li>
</ul>
</li>
<li>The form <code>(fref _+)</code> evaluates to the global function <code>_+</code>.</li>
<li>The form <code>x</code> is treated as an abbreviation for <code>(vref x)</code>.</li>
- <li>The form <code>(vref x)</code> is evaluated with respect to <code>[x→<sub>v</sub>1,y→<sub>v</sub>2]</code> and <code>[]</code>.</li>
+ <li>The form <code>(vref x)</code> is evaluated with respect to $[\vbinding{x}{1},\vbinding{y}{2}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(vref x)</code> is classified as a vref-form.</li>
+ <li>The form <code>(vref x)</code> is classified as a <code>vref</code>-form.</li>
<li>The variable <code>x</code> is looked up.</li>
</ul>
</li>
<li>The form <code>(vref x)</code> evaluates to the number <code>1</code>.</li>
<li>The form <code>y</code> is treated as an abbreviation for <code>(vref y)</code>.</li>
- <li>The form <code>(vref y)</code> is evaluated with respect to <code>[x→<sub>v</sub>1,y→<sub>v</sub>2]</code> and <code>[]</code>.</li>
+ <li>The form <code>(vref y)</code> is evaluated with respect to $[\vbinding{x}{1},\vbinding{y}{2}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(vref y)</code> is classified as a vref-form.</li>
+ <li>The form <code>(vref y)</code> is classified as a <code>vref</code>-form.</li>
<li>The variable <code>y</code> is looked up.</li>
</ul>
</li>
<li>The form <code>(+ 1 2)</code> evaluates to the number <code>3</code>.</li>
</ul>
</div>
- <p>Let's consider the following global macro, whose purpose is to evaluate the form with respect to a lexical environment extending the current lexical environment to bind, in the value namespace, the variable to the primary value of the value-form:</p>
+ <p>Let us consider the following global macro, whose purpose is to evaluate the form with respect to a lexical environment extending the current lexical environment to bind, in the value namespace, the variable to the primary value of the value-form:</p>
<pre class="repl">> (mdef simple-vlet (variable value-form form)<br> (list (list '_vlambda (list variable) form) value-form))<br>simple-vlet<br><br>> (simple-vlet x 1 (+ x 2))<br>3<br><br>> (simple-vlet x 1 (simple-vlet y 2 (+ x y)))<br>3</pre>
- <p>Here is an evaluation trace of the evaluation of the form <code>(simple-vlet x 1 (+ x 2))</code>:</p>
+ <p>Here is an evaluation trace of the evaluation of the top-level form <code>(simple-vlet x 1 (+ x 2))</code>:</p>
<div class="trace">
<ul>
- <li>The form <code>(simple-vlet x 1 (+ x 2))</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(simple-vlet x 1 (+ x 2))</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
<li>Because the variable <code>simple-vlet</code> names a macro according to the lookup rule used by <code>fref</code>, the form <code>(simple-vlet x 1 (+ x 2))</code> is classified as a macro call.</li>
<li>The global macro <code>simple-vlet</code> is invoked on the variable <code>x</code>, the number <code>1</code>, and the list <code>(+ x 2)</code>.</li>
<li>The global macro <code>simple-vlet</code> returns the list <code>((_vlambda (x) (+ x 2)) 1)</code>.</li>
- <li>The form <code>((_vlambda (x) (+ x 2)) 1)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (x) (+ x 2)) 1)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>((_vlambda (x) (+ x 2)) 1)</code> is classified as a function call.</li>
- <li>The form <code>(_vlambda (x) (+ x 2))</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
- <li>The form <code>(_vlambda (x) (+ x 2))</code> evaluates to a closure recording the following two pieces of information: the _vlambda-form <code>(_vlambda (x) (+ x 2))</code> and the lexical environment <code>[]</code>.</li>
- <li>The form <code>1</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (x) (+ x 2)) 1)</code> is classified as a plain function call.</li>
+ <li>The form <code>(_vlambda (x) (+ x 2))</code> is evaluated with respect to $[]$ and $[]$.</li>
+ <li>The form <code>(_vlambda (x) (+ x 2))</code> evaluates to a closure recording the following two pieces of information: the <code>_vlambda</code>-form <code>(_vlambda (x) (+ x 2))</code> and the lexical environment $[]$.</li>
+ <li>The form <code>1</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>The form <code>1</code> evaluates to the number <code>1</code>.</li>
<li>The closure is invoked on the number <code>1</code>.</li>
<li>
<ul>
- <li>A new lexical environment is created that extends the lexical environment <code>[]</code> to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code>.</li>
- <li>The form <code>(+ x 2)</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>A new lexical environment is created that extends the lexical environment $[]$ to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code>.</li>
+ <li>The form <code>(+ x 2)</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>The form <code>(+ x 2)</code> evaluates to the number <code>3</code>.</li>
</ul>
</li>
<li>The form <code>(simple-vlet x 1 (+ x 2))</code> evaluates to the number <code>3</code>.</li>
</ul>
</div>
- <p>Here is an evaluation trace of the evaluation of the form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code>:</p>
+ <p>Here is an evaluation trace of the evaluation of the top-level form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code>:</p>
<div class="trace">
<ul>
- <li>The form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
<li>Because the variable <code>simple-vlet</code> names a macro according to the lookup rule used by <code>fref</code>, the form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code> is classified as a macro call.</li>
<li>The global macro <code>simple-vlet</code> is invoked on the variable <code>x</code>, the number <code>1</code>, and the list <code>(simple-vlet y 2 (+ x y))</code>.</li>
<li>The global macro <code>simple-vlet</code> returns the list <code>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)</code>.</li>
- <li>The form <code>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)</code> is classified as a function call.</li>
- <li>The form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
- <li>The form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> evaluates to a closure recording the following two pieces of information: the _vlambda-form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> and the lexical environment <code>[]</code>.</li>
- <li>The form <code>1</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)</code> is classified as a plain function call.</li>
+ <li>The form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> is evaluated with respect to $[]$ and $[]$.</li>
+ <li>The form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> evaluates to a closure recording the following two pieces of information: the <code>_vlambda</code>-form <code>(_vlambda (x) (simple-vlet y 2 (+ x y)))</code> and the lexical environment $[]$.</li>
+ <li>The form <code>1</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>The form <code>1</code> evaluates to the number <code>1</code>.</li>
<li>The closure is invoked on the number <code>1</code>.</li>
<li>
<ul>
- <li>A new lexical environment is created that extends the lexical environment <code>[]</code> to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code>.</li>
- <li>The form <code>(simple-vlet y 2 (+ x y))</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>A new lexical environment is created that extends the lexical environment $[]$ to bind, in the value namespace, the variable <code>x</code> to the number <code>1</code>.</li>
+ <li>The form <code>(simple-vlet y 2 (+ x y))</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>
<ul>
<li>Because the variable <code>simple-vlet</code> names a macro according to the lookup rule used by <code>fref</code>, the form <code>(simple-vlet y 2 (+ x y))</code> is classified as a macro call.</li>
<li>The global macro <code>simple-vlet</code> is invoked on the variable <code>y</code>, the number <code>2</code>, and the list <code>(+ x y)</code>.</li>
<li>The global macro <code>simple-vlet</code> returns the list <code>((_vlambda (y) (+ x y)) 2)</code>.</li>
- <li>The form <code>((_vlambda (y) (+ x y)) 2)</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (y) (+ x y)) 2)</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>((_vlambda (y) (+ x y)) 2)</code> is classified as a function call.</li>
- <li>The form <code>(_vlambda (y) (+ x y))</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
- <li>The form <code>(_vlambda (y) (+ x y))</code> evaluates to a closure recording the following two pieces of information: the _vlambda-form <code>(_vlambda (y) (+ x y))</code> and the lexical environment <code>[x→<sub>v</sub>1]</code>.</li>
- <li>The form <code>2</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>The form <code>((_vlambda (y) (+ x y)) 2)</code> is classified as a plain function call.</li>
+ <li>The form <code>(_vlambda (y) (+ x y))</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
+ <li>The form <code>(_vlambda (y) (+ x y))</code> evaluates to a closure recording the following two pieces of information: the <code>_vlambda</code>-form <code>(_vlambda (y) (+ x y))</code> and the lexical environment $[\vbinding{x}{1}]$.</li>
+ <li>The form <code>2</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>The form <code>2</code> evaluates to the number <code>2</code>.</li>
<li>The closure is invoked on the number <code>2</code>.</li>
<li>
<ul>
- <li>A new lexical environment is created that extends the lexical environment <code>[x→<sub>v</sub>1]</code> to bind, in the value namespace, the variable <code>y</code> to the number <code>2</code>.</li>
- <li>The form <code>(+ x y)</code> is evaluated with respect to <code>[x→<sub>v</sub>1,y→<sub>v</sub>2]</code> and <code>[]</code>.</li>
+ <li>A new lexical environment is created that extends the lexical environment $[\vbinding{x}{1}]$ to bind, in the value namespace, the variable <code>y</code> to the number <code>2</code>.</li>
+ <li>The form <code>(+ x y)</code> is evaluated with respect to $[\vbinding{x}{1},\vbinding{y}{2}]$ and $[]$.</li>
<li>The form <code>(+ x y)</code> evaluates to the number <code>3</code>.</li>
</ul>
</li>
<li>The form <code>(simple-vlet x 1 (simple-vlet y 2 (+ x y)))</code> evaluates to the number <code>3</code>.</li>
</ul>
</div>
- <p>When debugging a macro, it is often useful to examine some expansions generated by the macro. The expansion of the macro call <code>(<macro-name> <operand-1> … <operand-n>)</code> can easily be obtained by evaluating the function call <code>((fref <macro-name>) '<operand-1> … '<operand-n>)</code>:</p>
+ <p>When debugging a macro, it is often useful to examine some expansions generated by the macro. The expansion of the macro call <code>($\metavar{macro-operator}$ $\metavarn{macro-operand}{1}\ldots\metavarn{macro-operand}{n}$)</code> can easily be obtained by evaluating the plain function call <code>((fref $\metavar{macro-operator}$) $\code{'}\metavarn{macro-operand}{1}\ldots\code{'}\metavarn{macro-operand}{n}$)</code>:</p>
<pre class="repl">> ((fref simple-vlet) 'x '1 '(+ x 2))<br>((_vlambda (x) (+ x 2)) 1)<br><br>> ((fref simple-vlet) 'x '1 '(simple-vlet y 2 (+ x y)))<br>((_vlambda (x) (simple-vlet y 2 (+ x y))) 1)<br><br>> ((fref simple-vlet) 'y '2 '(+ x y))<br>((_vlambda (y) (+ x y)) 2)<br><br>> ((fref simple-vlet) 'x '1 ((fref simple-vlet) 'y '2 '(+ x y)))<br>((_vlambda (x) ((_vlambda (y) (+ x y)) 2)) 1)</pre>
- <p>Let's consider the following global function, which returns the absolute value of its argument:</p>
+ <p>Let us consider the following global function, which returns the absolute value of its argument:</p>
<pre class="repl">> (fdef abs (x)<br> (if (>= x 0) x (- x)))<br>abs<br><br>> (abs 1)<br>1<br><br>> (abs -1)<br>1</pre>
- <p>Here is an evaluation trace of the evaluation of the form <code>(abs 1)</code>:</p>
+ <p>Here is an evaluation trace of the evaluation of the top-level form <code>(abs 1)</code>:</p>
<div class="trace">
<ul>
- <li>The form <code>(abs 1)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(abs 1)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
<li>The global function <code>abs</code> is invoked on the number <code>1</code>.</li>
<li>
<ul>
- <li>The form <code>(if (>= x 0) x (- x)))</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>The form <code>(if (>= x 0) x (- x)))</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(if (>= x 0) x (- x)))</code> is classified as an if-form.</li>
- <li>The form <code>(>= x 0)</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>The form <code>(if (>= x 0) x (- x)))</code> is classified as an <code>if</code>-form.</li>
+ <li>The form <code>(>= x 0)</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>
<ul>
<li>The global function <code>>=</code> is invoked on the numbers <code>1</code> and <code>0</code>.</li>
</li>
<li>The form <code>(>= x 0)</code> evaluates to the boolean <code>#t</code>.</li>
<li>Because the test-form evaluates to the boolean <code>#t</code>, the then-form is selected for evaluation.</li>
- <li>The form <code>x</code> is evaluated with respect to <code>[x→<sub>v</sub>1]</code> and <code>[]</code>.</li>
+ <li>The form <code>x</code> is evaluated with respect to $[\vbinding{x}{1}]$ and $[]$.</li>
<li>The form <code>x</code> evaluates to the number <code>1</code>.</li>
</ul>
</li>
<li>The form <code>(abs 1)</code> evaluates to the number <code>1</code>.</li>
</ul>
</div>
- <p>Here is an evaluation trace of the evaluation of the form <code>(abs -1)</code>:</p>
+ <p>Here is an evaluation trace of the evaluation of the top-level form <code>(abs -1)</code>:</p>
<div class="trace">
<ul>
- <li>The form <code>(abs -1)</code> is evaluated with respect to <code>[]</code> and <code>[]</code>.</li>
+ <li>The form <code>(abs -1)</code> is evaluated with respect to $[]$ and $[]$.</li>
<li>
<ul>
<li>The global function <code>abs</code> is invoked on the number <code>-1</code>.</li>
<li>
<ul>
- <li>The form <code>(if (>= x 0) x (- x)))</code> is evaluated with respect to <code>[x→<sub>v</sub>-1]</code> and <code>[]</code>.</li>
+ <li>The form <code>(if (>= x 0) x (- x)))</code> is evaluated with respect to $[\vbinding{x}{-1}]$ and $[]$.</li>
<li>
<ul>
- <li>The form <code>(if (>= x 0) x (- x)))</code> is classified as an if-form.</li>
- <li>The form <code>(>= x 0)</code> is evaluated with respect to <code>[x→<sub>v</sub>-1]</code> and <code>[]</code>.</li>
+ <li>The form <code>(if (>= x 0) x (- x)))</code> is classified as an <code>if</code>-form.</li>
+ <li>The form <code>(>= x 0)</code> is evaluated with respect to $[\vbinding{x}{-1}]$ and $[]$.</li>
<li>
<ul>
<li>The global function <code>>=</code> is invoked on the numbers <code>-1</code> and <code>0</code>.</li>
</li>
<li>The form <code>(>= x 0)</code> evaluates to the boolean <code>#f</code>.</li>
<li>Because the test-form evaluates to the boolean <code>#f</code>, the else-form is selected for evaluation.</li>
- <li>The form <code>(- x)</code> is evaluated with respect to <code>[x→<sub>v</sub>-1]</code> and <code>[]</code>.</li>
+ <li>The form <code>(- x)</code> is evaluated with respect to $[\vbinding{x}{-1}]$ and $[]$.</li>
<li>
<ul>
<li>The global function <code>-</code> is invoked on the number <code>-1</code>.</li>
<li>The form <code>(abs -1)</code> evaluates to the number <code>1</code>.</li>
</ul>
</div>
- <p>Let's consider the following global functions:</p>
+ <p>Let us consider the following global functions:</p>
<pre class="repl">> (fdef sum-of-squares (x y)<br> (+ (square x) (square y)))<br>sum-of-squares<br><br>> (fdef square (x)<br> (* x x))<br>square<br><br>> (sum-of-squares 3 4)<br>25</pre>
<p>Here is an invocation trace of the evaluation of the form <code>(sum-of-squares 3 4)</code>:</p>
<div class="trace">
</ul>
</div>
<h2>Recursive Functions</h2>
- <p>A recursive function is a function that invokes itself directly (<i>f</i>→<i>f</i>) or indirectly (<i>f</i>→<i>g</i>→…→<i>f</i>).</p>
+ <p>A recursive function is a function that invokes itself directly ($f\rightarrow f$) or indirectly ($f\rightarrow g\rightarrow\cdots\rightarrow f$).</p>
<p>A recursive function call is a function call through which a recursive function invokes itself directly or indirectly.</p>
- <p>A form is said to be in tail position with respect to a lambda-form if and only if one of the following mutually exclusive conditions is satisfied:</p>
+ <p>A form is said to be in tail position with respect to a lambda abstraction if and only if one of the following mutually exclusive conditions is satisfied:</p>
<ul>
- <li>The form is the last form of the body of the lambda-form.</li>
- <li>The form is the last form of a progn-form in tail position with respect to the lambda-form.</li>
- <li>The form is the then-form or the else-form of an if-form in tail position with respect to the lambda-form.</li>
+ <li>The form is the last form of the body of the lambda abstraction.</li>
+ <li>The form is the last form of a <code>progn</code>-form in tail position with respect to the lambda abstraction.</li>
+ <li>The form is the then-form or the else-form of an <code>if</code>-form in tail position with respect to the lambda abstraction.</li>
</ul>
- <p>A form in tail position with respect to a lambda-form has the following property: If (1) a closure resulting from the evaluation of the lambda-form is invoked and (2) the form happens to be evaluated during the invocation of the closure, then the result of the evaluation of the form becomes the result of the invocation of the closure without any further processing. (The values of the form are returned as is and not used otherwise.)</p>
+ <p>A form in tail position with respect to a lambda abstraction has the following property: If (1) a closure resulting from the evaluation of the lambda abstraction is invoked and (2) the form happens to be evaluated during the invocation of the closure, then the result of the evaluation of the form becomes the result of the invocation of the closure without any further processing. (The values of the form are returned as is and not used otherwise.)</p>
<h3>Factorial Function</h3>
- <p>The factorial function is defined by the following recurrence relation, where n is a non-negative integer:</p>
+ <p>The factorial function is defined by the following recurrence relation, where $n$ is a nonnegative integer:</p>
<ul>
- <li>0! = 1</li>
- <li>n! = n (n-1)! for n > 0</li>
+ <li>$0!=1$</li>
+ <li>$n!=n(n-1)!$ for $n\gt0$</li>
</ul>
- <p>It follows from the definition that the factorial of n is equal to the product of the first n strictly positive integers:</p>
- <blockquote>n! = 1 × 2 × 3 × ⋯ × n</blockquote>
- <p>The equality still holds for n = 0 because the product is then empty and an empty product is, by convention, equal to 1.</p>
- <p>Here are the values of the factorial function for n varying from 0 to 10:</p>
- <table>
- <tr><td>0!</td><td>1!</td><td>2!</td><td>3!</td><td>4!</td><td>5!</td><td>6!</td><td>7!</td><td>8!</td><td>9!</td><td>10!</td></tr>
- <tr><td>1</td><td>1</td><td>2</td><td>6</td><td>24</td><td>120</td><td>720</td><td>5040</td><td>40320</td><td>362880</td><td>3628800</td></tr>
+ <p>It follows from the definition that the factorial of $n$ is equal to the product of the first $n$ strictly positive integers:</p>
+ $$n!=1\times2\times3\times\cdots\times n$$
+ <p>The equality still holds for $n=0$ because the product is then empty and an empty product is, by convention, equal to $1$.</p>
+ <p>Here are the values of the factorial function for $n$ varying from $0$ to $10$:</p>
+ <table class="plain">
+ <tr><td>$0!$</td><td>$1!$</td><td>$2!$</td><td>$3!$</td><td>$4!$</td><td>$5!$</td><td>$6!$</td><td>$7!$</td><td>$8!$</td><td>$9!$</td><td>$10!$</td></tr>
+ <tr><td>$1$</td><td>$1$</td><td>$2$</td><td>$6$</td><td>$24$</td><td>$120$</td><td>$720$</td><td>$5040$</td><td>$40320$</td><td>$362880$</td><td>$3628800$</td></tr>
</table>
<p>The values of the factorial function can be computed by the global function <code>fact</code>, which is a direct translation of the recurrence relation:</p>
<pre class="repl">> (fdef fact (n)<br> (if (= n 0) 1 (* n (fact (- n 1)))))<br>fact<br><br>> (fact 10)<br>3628800</pre>
<li>The global function <code>fact</code> returns the number <code>720</code>.</li>
</ul>
</div>
- <p>There are two phases in the evaluation of the form <code>(fact 6)</code>: (1) an expansion phase during which the number of active invocations of <code>fact</code> increases and (2) a contraction phase during which the number of active invocations of <code>fact</code> decreases. When the evaluator is processing the invocation of <code>fact</code> on the number <code>0</code>, there are 7 active invocations of <code>fact</code>:</p>
+ <p>There are two phases in the evaluation of the form <code>(fact 6)</code>: (1) an expansion phase during which the number of active invocations of <code>fact</code> increases and (2) a contraction phase during which the number of active invocations of <code>fact</code> decreases. When the evaluator is processing the invocation of <code>fact</code> on the number <code>0</code>, there are $7$ active invocations of <code>fact</code>:</p>
<ol>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the recursive invocation of <code>fact</code> on the number <code>(- n 1)</code> = <code>5</code>. When that value is eventually available, it will be multiplied by the number <code>n</code> = <code>6</code> and the result of the multiplication will be returned as the value of the invocation.</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fact</code> on the number <code>(- n 1)</code> = <code>0</code>. When that value is eventually available, it will be multiplied by the number <code>n</code> = <code>1</code> and the result of the multiplication will be returned as the value of the invocation.</li>
- <li>One evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code>. That invocation directly returns the number <code>1</code> as its value without any further recursive invocation of <code>fact</code>.</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the recursive invocation of <code>fact</code> on the number <code>(- n 1)</code> = <code>5</code>. When that value is eventually available, it will be multiplied by the number <code>n</code> = <code>6</code> and the result of the multiplication will be returned as the value of the invocation.</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fact</code> on the number <code>(- n 1)</code> = <code>0</code>. When that value is eventually available, it will be multiplied by the number <code>n</code> = <code>1</code> and the result of the multiplication will be returned as the value of the invocation.</li>
+ <li>One invocation evaluating the body of <code>fact</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code>. That invocation directly returns the number <code>1</code> as its value without any further recursive invocation of <code>fact</code>.</li>
</ol>
- <p>The factorial is computed during the contraction phase by adding factors to a running product. The running product is initialized to the number <code>1</code> by the innermost invocation and the whole product is equal to 6 × (5 × (4 × (3 × (2 × (1 × 1))))).</p>
+ <p>The factorial is computed during the contraction phase by adding factors to a running product. The running product is initialized to the number <code>1</code> by the innermost invocation and the whole product is equal to $6\times(5\times(4\times(3\times(2\times(1\times1)))))$.</p>
<p>The values of the factorial function can also be computed by the global function <code>fact-iter</code>:</p>
<pre class="repl">> (fdef fact-iter (n)<br> (fact-iter-internal n 1))<br>fact-iter<br><br>> (fdef fact-iter-internal (n acc)<br> (if (= n 0) acc (fact-iter-internal (- n 1) (* n acc))))<br>fact-iter-internal<br><br>> (fact-iter 10)<br>3628800</pre>
<p>The bulk of the work is done by the auxiliary global function <code>fact-iter-internal</code>, which contains one recursive function call. The call to <code>fact-iter-internal</code> in <code>fact-iter</code> and the recursive function call in <code>fact-iter-internal</code> are both in tail position.</p>
<li>The global function <code>fact-iter</code> returns the number <code>720</code>.</li>
</ul>
</div>
- <p>There are two phases in the evaluation of the form <code>(fact-iter 6)</code>: (1) an expansion phase during which the number of active invocations increases and (2) a contraction phase during which the number of active invocations decreases. When the evaluator is processing the invocation of <code>fact-iter-internal</code> on the numbers <code>0</code> and <code>720</code>, there are 8 active invocations (1 of <code>fact-iter</code> and 7 of <code>fact-iter-internal</code>):</p>
+ <p>There are two phases in the evaluation of the form <code>(fact-iter 6)</code>: (1) an expansion phase during which the number of active invocations increases and (2) a contraction phase during which the number of active invocations decreases. When the evaluator is processing the invocation of <code>fact-iter-internal</code> on the numbers <code>0</code> and <code>720</code>, there are $8$ active invocations ($1$ of <code>fact-iter</code> and $7$ of <code>fact-iter-internal</code>):</p>
<ol>
- <li>One evaluating the body of <code>fact-iter</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the invocation of <code>fact-iter-internal</code> on the numbers <code>n</code> = <code>6</code> and <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code> and the variable <code>acc</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fact-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>5</code> and <code>(* n acc)</code> = <code>6</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code> and the variable <code>acc</code> to the number <code>6</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code> and the variable <code>acc</code> to the number <code>30</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code> and the variable <code>acc</code> to the number <code>120</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code> and the variable <code>acc</code> to the number <code>360</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code> and the variable <code>acc</code> to the number <code>720</code>. That invocation is waiting for the value of the recursive invocation of <code>fact-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>0</code> and <code>(* n acc)</code> = <code>720</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code> and the variable <code>acc</code> to the number <code>720</code>. That invocation directly returns the number <code>acc</code> = <code>720</code> as its value without any further invocation of <code>fact-iter-internal</code>.</li>
+ <li>One invocation evaluating the body of <code>fact-iter</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the invocation of <code>fact-iter-internal</code> on the numbers <code>n</code> = <code>6</code> and <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code> and the variable <code>acc</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fact-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>5</code> and <code>(* n acc)</code> = <code>6</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code> and the variable <code>acc</code> to the number <code>6</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code> and the variable <code>acc</code> to the number <code>30</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code> and the variable <code>acc</code> to the number <code>120</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code> and the variable <code>acc</code> to the number <code>360</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code> and the variable <code>acc</code> to the number <code>720</code>. That invocation is waiting for the value of the recursive invocation of <code>fact-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>0</code> and <code>(* n acc)</code> = <code>720</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fact-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code> and the variable <code>acc</code> to the number <code>720</code>. That invocation directly returns the number <code>acc</code> = <code>720</code> as its value without any further recursive invocation of <code>fact-iter-internal</code>.</li>
</ol>
- <p>The factorial is computed during the expansion phase by adding factors to a running product. The running product, which is initialized to the number <code>1</code> by <code>fact-iter</code>, is propagated up the invocation chain through the variable <code>acc</code>. The whole product, which is equal to 1 × (2 × (3 × (4 × (5 × (6 × 1))))), is propagated down the invocation chain without any further processing.</p>
+ <p>The factorial is computed during the expansion phase by adding factors to a running product. The running product, which is initialized to the number <code>1</code> by <code>fact-iter</code>, is propagated up the invocation chain through the variable <code>acc</code>. The whole product, which is equal to $1\times(2\times(3\times(4\times(5\times(6\times1)))))$, is propagated down the invocation chain without any further processing.</p>
<h3>Fibonacci Sequence</h3>
- <p>The Fibonacci sequence is defined by the following recurrence relation, where n is a non-negative integer:</p>
+ <p>The Fibonacci sequence is defined by the following recurrence relation, where $n$ is a nonnegative integer:</p>
<ul>
- <li>F<sub>0</sub> = 0</li>
- <li>F<sub>1</sub> = 1</li>
- <li>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub> for n > 1</li>
+ <li>$F_0=0$</li>
+ <li>$F_1=1$</li>
+ <li>$F_n=F_{n-1}+F_{n-2}$ for $n\gt1$</li>
</ul>
- <p>Here are the values of the Fibonacci sequence for n varying from 0 to 10:</p>
- <table>
- <tr><td>F<sub>0</sub><td>F<sub>1</sub><td>F<sub>2</sub><td>F<sub>3</sub><td>F<sub>4</sub><td>F<sub>5</sub><td>F<sub>6</sub><td>F<sub>7</sub><td>F<sub>8</sub><td>F<sub>9</sub><td>F<sub>10</sub></td></tr>
- <tr><td>0</td><td>1</td><td>1</td><td>2</td><td>3</td><td>5</td><td>8</td><td>13</td><td>21</td><td>34</td><td>55</td></tr>
+ <p>Here are the values of the Fibonacci sequence for $n$ varying from $0$ to $10$:</p>
+ <table class="plain">
+ <tr><td>$F_0$<td>$F_1$<td>$F_2$<td>$F_3$<td>$F_4$<td>$F_5$<td>$F_6$<td>$F_7$<td>$F_8$<td>$F_9$<td>$F_{10}$</td></tr>
+ <tr><td>$0$</td><td>$1$</td><td>$1$</td><td>$2$</td><td>$3$</td><td>$5$</td><td>$8$</td><td>$13$</td><td>$21$</td><td>$34$</td><td>$55$</td></tr>
</table>
<p>The values of the Fibonacci sequence can be computed by the global function <code>fib</code>, which is a direct translation of the recurrence relation:</p>
<pre class="repl">> (fdef fib (n)<br> (if (= n 0)<br> 0<br> (if (= n 1)<br> 1<br> (+ (fib (- n 1)) (fib (- n 2))))))<br>fib<br><br>> (fib 10)<br>55</pre>
<li>The global function <code>fib</code> returns the number <code>8</code>.</li>
</ul>
</div>
- <p>During the evaluation of the form <code>(fib 6)</code>, the global function <code>fib</code> is invoked 1 time on the number <code>6</code>, 1 time on the number <code>5</code>, 2 times on the number <code>4</code>, 3 times on the number <code>3</code>, 5 times on the number <code>2</code>, 8 times on the number <code>1</code>, and 5 times on the number <code>0</code>.</p>
- <p>When the evaluator is processing the first invocation of <code>fib</code> on the number <code>0</code> (that invocation has a gray background in the invocation trace), there are 6 active invocations of <code>fib</code>:</p>
+ <p>During the evaluation of the form <code>(fib 6)</code>, the global function <code>fib</code> is invoked $1$ time on the number <code>6</code>, $1$ time on the number <code>5</code>, $2$ times on the number <code>4</code>, $3$ times on the number <code>3</code>, $5$ times on the number <code>2</code>, $8$ times on the number <code>1</code>, and $5$ times on the number <code>0</code>.</p>
+ <p>When the evaluator is processing the first invocation of <code>fib</code> on the number <code>0</code> (that invocation has a gray background in the invocation trace), there are $6$ active invocations of <code>fib</code>:</p>
<ol>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>5</code>. When that value is eventually available, it will be stored in a temporary location and <code>fib</code> will be invoked recursively on the number <code>(- n 2)</code> = <code>4</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>. That invocation is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>2</code>. When that value is eventually available, it will be stored in a temporary location and <code>fib</code> will be invoked recursively on the number <code>(- n 2)</code> = <code>1</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>. That invocation has already stored in a temporary location the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>1</code> and is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 2)</code> = <code>0</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
- <li>One evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code>. That invocation directly returns the number <code>0</code> as its value without any further invocation of <code>fib</code>.</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>5</code>. When that value is eventually available, it will be stored in a temporary location and <code>fib</code> will be invoked recursively on the number <code>(- n 2)</code> = <code>4</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>. That invocation is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>2</code>. When that value is eventually available, it will be stored in a temporary location and <code>fib</code> will be invoked recursively on the number <code>(- n 2)</code> = <code>1</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>. That invocation has already stored in a temporary location the value of the recursive invocation of <code>fib</code> on the number <code>(- n 1)</code> = <code>1</code> and is waiting for the value of the recursive invocation of <code>fib</code> on the number <code>(- n 2)</code> = <code>0</code>. When the value of the second recursive invocation of <code>fib</code> is eventually available, it will be added to the stored value of the first recursive invocation of <code>fib</code> and the result of the addition will be returned as the value of the invocation.</li>
+ <li>One invocation evaluating the body of <code>fib</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>0</code>. That invocation directly returns the number <code>0</code> as its value without any further recursive invocation of <code>fib</code>.</li>
</ol>
<p>The values of the Fibonacci sequence can also be computed by the global function <code>fib-iter</code>:</p>
<pre class="repl">> (fdef fib-iter (n)<br> (fib-iter-internal n 0 1))<br>fib-iter<br><br>> (fdef fib-iter-internal (n a b)<br> (if (= n 0)<br> a<br> (if (= n 1)<br> b<br> (fib-iter-internal (- n 1) b (+ a b)))))<br>fib-iter-internal<br><br>> (fib-iter 10)<br>55</pre>
<p>The bulk of the work is done by the auxiliary global function <code>fib-iter-internal</code>, which contains one recursive function call. The call to <code>fib-iter-internal</code> in <code>fib-iter</code> and the recursive function call in <code>fib-iter-internal</code> are both in tail position.</p>
<p>Whereas the global function <code>fib</code> computes the Fibonacci sequence top-down in a branching process that repeats the computation of some Fibonacci numbers, the global function <code>fib-iter</code> computes the Fibonacci sequence bottom-up in a linear process that do not repeat the computation of any Fibonacci numbers:</p>
<ul>
- <li>F<sub>2</sub> is computed from F<sub>1</sub> and F<sub>0</sub></li>
- <li>F<sub>3</sub> is computed from F<sub>2</sub> and F<sub>1</sub></li>
+ <li>$F_2$ is computed from $F_1$ and $F_0$</li>
+ <li>$F_3$ is computed from $F_2$ and $F_1$</li>
<li>…</li>
</ul>
- <p>Let n<sub>init</sub> be the the argument of <code>fib-iter</code> and n, a, and b be the arguments of the invocation of <code>fib-iter-internal</code> under consideration. When processing the non-recursive invocation of <code>fib-iter-internal</code>, n = n<sub>init</sub>, a = F<sub>0</sub>, and b = F<sub>1</sub>. If n<sub>init</sub> = 0, then <code>fib-iter-internal</code> returns a = F<sub>0</sub>. Otherwise, if n<sub>init</sub> = 1, then <code>fib-iter-internal</code> returns b = F<sub>1</sub>. Otherwise, <code>fib-iter-internal</code> invokes itself recursively. On each recursive invocation of <code>fib-iter-internal</code>, n is decremented by 1, a is replaced by the next Fibonacci number in the sequence F<sub>0</sub>, F<sub>1</sub>, F<sub>2</sub>, …, and b is replaced by the next Fibonacci number in the sequence F<sub>1</sub>, F<sub>2</sub>, F<sub>3</sub>, …. When processing the (n<sub>init</sub> - 1)-th recursive invocation of <code>fib-iter-internal</code>, n = n<sub>init</sub> - (n<sub>init</sub> - 1) = 1, a = F<sub>n<sub>init</sub> - 1</sub>, and b = F<sub>n<sub>init</sub></sub> and <code>fib-iter-internal</code> returns b = F<sub>n<sub>init</sub></sub>.</p>
+ <p>Let $n_\mathrm{init}$ be the the argument of <code>fib-iter</code> and $n$, $a$, and $b$ be the arguments of the invocation of <code>fib-iter-internal</code> under consideration. When processing the invocation of <code>fib-iter-internal</code> from <code>fib-iter</code>, $n=n_\mathrm{init}$, $a=F_0$, and $b=F_1$. If $n_\mathrm{init}=0$, then <code>fib-iter-internal</code> returns $a=F_0$. Otherwise, if $n_\mathrm{init}=1$, then <code>fib-iter-internal</code> returns $b=F_1$. Otherwise, <code>fib-iter-internal</code> invokes itself recursively. On each recursive invocation of <code>fib-iter-internal</code>, $n$ is decremented by $1$, $a$ is replaced by the next Fibonacci number in the sequence $F_0$, $F_1$, $F_2$, …, and $b$ is replaced by the next Fibonacci number in the sequence $F_1$, $F_2$, $F_3$, … When processing the $(n_\mathrm{init}-1)$-th recursive invocation of <code>fib-iter-internal</code>, $n=n_\mathrm{init}-(n_\mathrm{init}-1)=1$, $a=F_{0+n_\mathrm{init}-1}=F_{n_\mathrm{init}-1}$, and $b=F_{1+n_\mathrm{init}-1}=F_{n_\mathrm{init}}$ and <code>fib-iter-internal</code> returns $b=F_{n_\mathrm{init}}$.</p>
<p>Here is an invocation trace of the evaluation of the form <code>(fib-iter 6)</code>:</p>
<div class="trace">
<ul>
<li>The global function <code>fib-iter</code> returns the number <code>8</code>.</li>
</ul>
</div>
- <p>When the evaluator is processing the invocation of <code>fib-iter-internal</code> on the numbers <code>1</code>, <code>5</code>, and <code>8</code>, there are 7 active invocations (1 of <code>fib-iter</code> and 6 <code>fib-iter-internal</code>):</p>
+ <p>When the evaluator is processing the invocation of <code>fib-iter-internal</code> on the numbers <code>1</code>, <code>5</code>, and <code>8</code>, there are $7$ active invocations ($1$ of <code>fib-iter</code> and $6$ of <code>fib-iter-internal</code>):</p>
<ol>
- <li>One evaluating the body of <code>fib-iter</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the invocation of <code>fib-iter-internal</code> on the numbers <code>n</code> = <code>6</code>, <code>0</code> and <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>, the variable <code>a</code> to the number <code>0</code>, and the variable <code>b</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fib-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>5</code>, <code>b</code> = <code>1</code>, and <code>(+ a b)</code> = <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>, the variable <code>a</code> to the number <code>1</code>, and the variable <code>b</code> to the number <code>1</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>, the variable <code>a</code> to the number <code>1</code>, and the variable <code>b</code> to the number <code>2</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>, the variable <code>a</code> to the number <code>2</code>, and the variable <code>b</code> to the number <code>3</code>. That invocation is waiting…</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>, the variable <code>a</code> to the number <code>3</code>, and the variable <code>b</code> to the number <code>5</code>. That invocation is waiting for the value of the recursive invocation of <code>fib-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>1</code>, <code>b</code> = <code>5</code>, and <code>(+ a b)</code> = <code>8</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
- <li>One evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code>, the variable <code>a</code> to the number <code>5</code>, and the variable <code>8</code> to the number <code>5</code>. That invocation directly returns the number <code>b</code> = <code>8</code> as its value without any further invocation of <code>fib-iter-internal</code>.</li>
+ <li>One invocation evaluating the body of <code>fib-iter</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>. That invocation is waiting for the value of the invocation of <code>fib-iter-internal</code> on the numbers <code>n</code> = <code>6</code>, <code>0</code> and <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>6</code>, the variable <code>a</code> to the number <code>0</code>, and the variable <code>b</code> to the number <code>1</code>. That invocation is waiting for the value of the recursive invocation of <code>fib-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>5</code>, <code>b</code> = <code>1</code>, and <code>(+ a b)</code> = <code>1</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>5</code>, the variable <code>a</code> to the number <code>1</code>, and the variable <code>b</code> to the number <code>1</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>4</code>, the variable <code>a</code> to the number <code>1</code>, and the variable <code>b</code> to the number <code>2</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>3</code>, the variable <code>a</code> to the number <code>2</code>, and the variable <code>b</code> to the number <code>3</code>. That invocation is waiting…</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>2</code>, the variable <code>a</code> to the number <code>3</code>, and the variable <code>b</code> to the number <code>5</code>. That invocation is waiting for the value of the recursive invocation of <code>fib-iter-internal</code> on the numbers <code>(- n 1)</code> = <code>1</code>, <code>b</code> = <code>5</code>, and <code>(+ a b)</code> = <code>8</code>. When that value is eventually available, it will be returned as the value of the invocation without any further processing.</li>
+ <li>One invocation evaluating the body of <code>fib-iter-internal</code> with respect to a lexical environment binding, in the value namespace, the variable <code>n</code> to the number <code>1</code>, the variable <code>a</code> to the number <code>5</code>, and the variable <code>8</code> to the number <code>5</code>. That invocation directly returns the number <code>b</code> = <code>8</code> as its value without any further recursive invocation of <code>fib-iter-internal</code>.</li>
</ol>
</body>
</html>
<p>This section provides an overview of the programming language. Some of the concepts introduced in this section will be illustrated in the section <a href="#listener-buffers">Listener Buffers</a>. An introduction to writing programs can be found in the tutorial. A detailed account of the programming language can be found in the reference manual.</p>
<p>The programming language, which is called EVLambda like the project, is heavily inspired by the programming languages <a href="https://en.wikipedia.org/wiki/Scheme_(programming_language)" target="_blank">Scheme</a> and <a href="https://en.wikipedia.org/wiki/Common_Lisp" target="_blank">Common Lisp</a>. The bibliography contains many references covering and/or using those two programming languages.</p>
<p>In EVLambda, there is no difference of nature between code and data. Both code and data are represented by objects and it is the context of its occurrence that determines if an object must be treated as code or as data. The word “object” is used here in the broad sense of data structure without any reference to object-oriented programming.</p>
- <p>As we will see below, objects are patterns of bits inside the computer's memory. To facilitate communicating about objects, reading and writing code and data, etc., objects have associated sequences of characters that can be used to represent them.</p>
+ <p>As we will see later in this section, objects are patterns of bits inside the computer's memory. To facilitate communicating about objects, reading and writing code and data, etc., objects have associated sequences of characters that can be used to represent them.</p>
<p>Most objects have at least one readable representation. A readable representation of an object is a sequence of characters that can be used to represent the object in input operations. The reader is the component of the programming language responsible for converting a readable representation into the corresponding object.</p>
<p>All objects have exactly one printable representation. The printable representation of an object is a sequence of characters that can be used to represent the object in output operations. When an object has exactly one readable representation, its printable representation is identical to its readable representation. When an object has more than one readable representation, its printable representation is identical to one of its readable representations chosen to be the standard way to represent the object. When an object has no readable representations, its printable representation is a sequence of characters revealing its type. The printer is the component of the programming language responsible for converting an object into its printable representation.</p>
- <p>Objects are organized into classes called types and types are organized into a hierarchy of types. The type at the top of the hierarchy is called the root type. The types at the bottom of the hierarchy are called the leaf types. If type <i>A</i> is located below type <i>B</i> in the hierarchy, then type <i>A</i> is called a subtype of type <i>B</i> and any object that belongs to type <i>A</i> also belongs to type <i>B</i>. The term “data type” is sometimes used in place of the term “type” even though a (data) type is a class of objects and an object can be a piece of code or a piece of data.</p>
+ <p>Objects are organized into classes called types and types are organized into a hierarchy of types. The type at the top of the hierarchy is called the root type. The types at the bottom of the hierarchy are called the leaf types. Any object belongs to exactly one leaf type. If type $A$ is located below type $B$ in the hierarchy, then type $A$ is called a subtype of type $B$ and any object that belongs to type $A$ also belongs to type $B$. The term “data type” is sometimes used in place of the term “type” even though a (data) type is a class of objects and an object can be a piece of code or a piece of data.</p>
<p>Here is a tree-view representation of the hierarchy of types:</p>
<pre>object<br> |-void<br> |-boolean<br> |-number<br> |-character<br> |-string<br> |-symbol<br> | |-keyword<br> | |-variable<br> |-list<br> | |-empty-list<br> | |-cons<br> |-vector<br> |-function<br> | |-primitive-function<br> | |-closure</pre>
- <p>And here is a brief description of the leaf types (readable and printable representations have a gray background):</p>
+ <p>Here is a brief description of the leaf types (readable and printable representations have a gray background):</p>
<dl>
<dt><code>void</code></dt>
<dd>There is exactly one object of type <code>void</code>. Its readable representation is <code class="bg">#v</code> and its purpose is to represent missing or undefined objects.</dd>
<dt><code>number</code></dt>
<dd>Numbers represent mathematical numbers: <code class="bg">123</code>, <code class="bg">-123</code>, <code class="bg">123.456</code>, <code class="bg">-123.456</code>, … The representation of a mathematical number by an object of type <code>number</code> can be exact or approximate.</dd>
<dt><code>character</code></dt>
- <dd>Characters represent Unicode characters: <code class="bg">#\a</code>, <code class="bg">#\b</code>, <code class="bg">#\c</code>, … Most of the characters used in the world have a corresponding <a href="https://home.unicode.org/" target="_blank">Unicode</a> character.</dd>
+ <dd>Characters represent Unicode characters: <code class="bg">#"a"</code>, <code class="bg">#"b"</code>, <code class="bg">#"c"</code>, <code class="bg">#"你"</code>, <code class="bg">#"好"</code>, … Most of the characters used in the world have a corresponding <a href="https://home.unicode.org/" target="_blank">Unicode</a> character.</dd>
<dt><code>string</code></dt>
- <dd>Strings represent indexed sequences of Unicode characters: <code class="bg">"abc"</code>, …</dd>
+ <dd>Strings represent indexed sequences of Unicode characters: <code class="bg">"abc"</code>, <code class="bg">"你好"</code>, …</dd>
<dt><code>keyword</code></dt>
<dd>Keywords can, among other uses, represent named values: <code class="bg">:red</code>, <code class="bg">:green</code>, <code class="bg">:blue</code>, …</dd>
<dt><code>variable</code></dt>
<dt><code>empty-list</code></dt>
<dd>There is exactly one object of type <code>empty-list</code>. Its readable representation is <code class="bg">()</code> and its purpose is to represent empty lists of objects.</dd>
<dt><code>cons</code></dt>
- <dd>A cons is a pair of objects. The first element is called the car of the cons and the second element is called the cdr of the cons. Conses are the building blocks of many data structures. In particular, conses can be chained together to represent non-empty lists of objects. A non-empty list of objects is represented by a cons whose car is the first element of the list and whose cdr is the sublist of the list obtained by omitting its first element. For example, the list <code class="bg">(1 2 3)</code> is represented by a chain of three conses: a first cons whose car is the number <code class="bg">1</code> and whose cdr is the second cons, a second cons whose car is the number <code class="bg">2</code> and whose cdr is the third cons, and a third cons whose car is the number <code class="bg">3</code> and whose cdr is the empty list.</dd>
+ <dd>A cons is an ordered pair of objects. The first element is called the car of the cons and the second element is called the cdr of the cons. Conses are the building blocks of many data structures. In particular, conses can be chained together to represent nonempty lists of objects. A nonempty list of objects is represented by a cons whose car is the first element of the list and whose cdr is the sublist of the list obtained by omitting its first element. For example, the list <code class="bg">(1 2 3)</code> is represented by a chain of three conses: a first cons whose car is the number <code class="bg">1</code> and whose cdr is the second cons, a second cons whose car is the number <code class="bg">2</code> and whose cdr is the third cons, and a third cons whose car is the number <code class="bg">3</code> and whose cdr is the empty list.</dd>
<dt><code>vector</code></dt>
<dd>Vectors represent indexed sequences of objects: <code class="bg">#()</code>, <code class="bg">#(1 2 3)</code>, …</dd>
<dt><code>primitive-function</code></dt>
<dt><code>closure</code></dt>
<dd>Closures are input/output mappings implemented in EVLambda. Some closures are tagged as being a macro. Macros are code to code mappings used to create new language constructs. Closures have no readable representations and their printable representation is <code class="bg">#<closure></code>.</dd>
</dl>
- <p>Each symbol has an associated sequence of characters (called the name of the symbol) that serves as its readable representation. If the name of a symbol starts with a colon, then the symbol is a keyword. Otherwise, the symbol is a variable. The reader always converts the same name into the same symbol.</p>
+ <p>Each symbol has an associated sequence of characters (called the name of the symbol) that serves as its readable representation. If the name of a symbol starts with a colon, then the symbol is a keyword. Otherwise, the symbol is a variable. The reader always converts the same name into the same symbol. To that end, the reader maintains two mappings from names to symbols called packages: one package mapping the names of the previously encountered variables to the corresponding variables and one package mapping the names of the previously encountered keywords to the corresponding keywords.</p>
<p>The printable representation of a list consists of a left parenthesis followed by the printable representations of the elements of the list separated by a single space followed by a right parenthesis. The printable representation of a list is just one of its infinitely many readable representations. In particular, other readable representations can be obtained by using sequences of at least one whitespace character instead of single spaces to separate the elements of the list.</p>
- <p>Although a macro is technically a function (because a macro is an object of type <code>closure</code> and type <code>closure</code> is a subtype of type <code>function</code>), the word “function” is sometimes used to denote specifically a function other than a macro (that is, a primitive function or a closure not tagged as being a macro).</p>
+ <p>Although a macro is technically a function (because a macro is an object of type <code>closure</code> and type <code>closure</code> is a subtype of type <code>function</code>), the word “function” is often used to denote specifically a function other than a macro (that is, a primitive function or a closure not tagged as being a macro).</p>
<p>Variables name objects through the use of namespaces, bindings, environments, and lookup rules:</p>
<ul>
- <li>Namespaces are a general mechanism allowing the same name to have different meanings in different contexts. EVLambda uses namespaces to allow the same variable to name one object in contexts requiring an object of type <code>function</code> and another object in all other contexts.</li>
- <li>A binding is an association between a variable (called the name of the binding) and an object (called the value of the binding). Each binding is labeled with a namespace name: “value” or “function”. Bindings labeled with the namespace name “function” are used in contexts requiring an object of type <code>function</code> and bindings labeled with the namespace name “value” are used in all other contexts. Although the constraint is not enforced by the programming language, the value of a binding labeled with the namespace name “function” should be of type <code>function</code>.</li>
- <li>An environment is a set of bindings. By grouping together the bindings labeled with the same namespace name, an environment can be partitioned into two possibly empty subsets called the value namespace and the function namespace. The purpose of a namespace is to implement a non-ambiguous partial mapping from variables to objects. For that reason, there cannot exist more than one binding for the same variable in the same namespace.</li>
- <li>Lookup rules are needed because, as we will see below, three environments are always active at any given time. The lookup rules determine which environments to consult and in which order.</li>
+ <li>Namespaces are a general mechanism allowing the same name to have different meanings in different contexts. EVLambda uses namespaces to allow the same variable to name two objects: one object that is used by default in contexts requiring an object of type <code>function</code> and another object that is used by default in all other contexts.</li>
+ <li>A binding is an association between a variable (called the name of the binding) and an object (called the value of the binding). Each binding is labeled with a namespace name: “value” or “function”. By default, bindings labeled with the namespace name “function” are used in contexts requiring an object of type <code>function</code> and bindings labeled with the namespace name “value” are used in all other contexts. Although the constraint is not enforced by the programming language, the value of a binding labeled with the namespace name “function” should be of type <code>function</code>.</li>
+ <li>An environment is a set of bindings. By grouping together the bindings labeled with the same namespace name, an environment can be partitioned into two possibly empty subsets called the value namespace and the function namespace. The purpose of a namespace is to implement a nonambiguous partial mapping from variables to objects. A consequence of the nonambiguity requirement is that a namespace cannot contain more than one binding for the same variable.</li>
+ <li>Lookup rules are needed because, as we will see later in this section, three environments are always active at any given time. The lookup rules determine which environments to consult and in which order.</li>
</ul>
- <p>A variable that is associated with an object through a binding belonging to namespace <i>X</i> of environment <i>Y</i> is said to be bound to the object in namespace <i>X</i> of environment <i>Y</i>. A variable that is not associated with an object through a binding belonging to namespace <i>X</i> of environment <i>Y</i> is said to be unbound in namespace <i>X</i> of environment <i>Y</i>.</p>
- <p>Objects, bindings, and environments are represented by non-overlapping patterns of bits located inside a region of the computer's memory called the heap. Each object, binding, and environment is uniquely identified by the address of the pattern of bits that represents it. Like objects, bindings, and environments, addresses are also represented by patterns of bits. A reference to an object, binding, or environment is an instance of the pattern of bits that represents the address of the pattern of bits that represents the object, binding, or environment. By abuse of language, we often confuse a reference to an object, binding, or environment with the referenced object, binding, or environment itself.</p>
- <p>The pattern of bits representing an object has two parts: one part specifying the type of the object and one part specifying which member of the type is represented by the object.</p>
+ <p>A variable that is associated with an object through a binding belonging to namespace $X$ of environment $Y$ is said to be bound to the object in namespace $X$ of environment $Y$. A variable that is not associated with an object through a binding belonging to namespace $X$ of environment $Y$ is said to be unbound in namespace $X$ of environment $Y$.</p>
+ <p>Objects, bindings, and environments are represented by nonoverlapping patterns of bits located inside a region of the computer's memory called the heap. Each object, binding, or environment is uniquely identified by the address of the pattern of bits that represents it. Like objects, bindings, and environments, addresses are also represented by patterns of bits. A reference to an object, binding, or environment is an instance of the pattern of bits that represents the address of the pattern of bits that represents the object, binding, or environment. By abuse of language, we often confuse a reference to an object, binding, or environment with the object, binding, or environment being referenced.</p>
+ <p>The pattern of bits representing an object has two parts: one part specifying the type of the object and one part specifying which member of the type the object is.</p>
<p>An object, binding, or environment references another object, binding, or environment by embedding into its representation a reference to that other object, binding, or environment:</p>
<ul>
<li>A cons references two objects of arbitrary types (the car and the cdr of the cons).</li>
- <li>A vector of length <i>n</i> references <i>n</i> objects of arbitrary types (the elements of the vector).</li>
- <li>A closure references a lambda-form (a list specifying an input/output mapping) and an environment.</li>
+ <li>A vector of length $n$ references $n$ objects of arbitrary types (the elements of the vector).</li>
+ <li>A closure references a lambda abstraction (a list specifying an input/output mapping) and an environment.</li>
<li>A binding references a variable (the name of the binding) and an object of arbitrary type (the value of the binding).</li>
<li>An environment references its bindings.</li>
</ul>
- <p>The references embedded into the representation of an object, binding, or environment can be thought of as occupying memory locations denoted by the object, binding, or environment. By abuse of language, we often say that a memory location contains an object, binding, or environment when in reality the memory location contains a reference to the object, binding, or environment.</p>
- <p>Multiple objects, bindings, or environments can reference a common object, binding, or environment, leading to the sharing of the common object, binding, or environment. An object, binding, or environment can reference itself directly (<i>X</i>→<i>X</i>) or indirectly (<i>X</i>→<i>Y</i>→…→<i>X</i>), leading to the existence of a cycle.</p>
- <p>Objects of type <code>void</code>, <code>boolean</code>, <code>keyword</code>, <code>symbol</code>, or <code>empty-list</code> have the following uniqueness properties:</p>
+ <p>The references embedded into the representation of an object, binding, or environment can be thought of as occupying memory locations denoted by the object, binding, or environment. For example, a cons can be thought of as denoting two memory locations: one containing a reference to the car of the cons and one containing a reference to the cdr of the cons. By abuse of language, we often say that a memory location contains an object, binding, or environment when in reality the memory location contains a reference to the object, binding, or environment.</p>
+ <p>Multiple objects, bindings, and environments can reference a common object, binding, or environment, leading to the sharing of the common object, binding, or environment. An object, binding, or environment can reference itself directly ($X\rightarrow X$) or indirectly ($X\rightarrow Y\rightarrow\cdots\rightarrow X$), leading to the existence of a cycle.</p>
+ <p>Objects of type <code>void</code>, <code>boolean</code>, <code>keyword</code>, <code>symbol</code>, and <code>empty-list</code> have the following uniqueness properties:</p>
<ul>
<li>There exists in the heap exactly one object of type <code>void</code>.</li>
<li>There exists in the heap exactly one object of type <code>boolean</code> representing true.</li>
<li>There cannot exist in the heap more than one object of type <code>variable</code> with the same name. (This property is enforced by the reader.)</li>
<li>There exists in the heap exactly one object of type <code>empty-list</code>.</li>
</ul>
- <p>Objects of type <code>integer</code>, <code>character</code>, or <code>string</code> do not have similar uniqueness properties:</p>
+ <p>Objects of type <code>integer</code>, <code>character</code>, and <code>string</code> do not have similar uniqueness properties:</p>
<ul>
<li>There can exist in the heap more than one object of type <code>number</code> representing the same mathematical number.</li>
<li>There can exist in the heap more than one object of type <code>character</code> representing the same Unicode character.</li>
<li>There can exist in the heap more than one object of type <code>string</code> representing the same indexed sequence of Unicode characters.</li>
</ul>
- <p>Objects of type <code>void</code>, <code>boolean</code>, <code>number</code>, <code>character</code>, <code>string</code>, <code>keyword</code>, <code>symbol</code>, <code>empty-list</code>, <code>primitive-function</code>, or <code>closure</code> are immutable and cannot be altered. Objects of type <code>cons</code> or <code>vector</code>, bindings, and environments are mutable and can be altered in the following ways:</p>
+ <p>Objects of type <code>void</code>, <code>boolean</code>, <code>number</code>, <code>character</code>, <code>string</code>, <code>keyword</code>, <code>symbol</code>, <code>empty-list</code>, <code>primitive-function</code>, and <code>closure</code> are immutable and cannot be altered. Objects of type <code>cons</code> and <code>vector</code>, bindings, and environments are mutable and can be altered in the following ways:</p>
<ul>
<li>The car and the cdr of a cons can be replaced by another object.</li>
<li>Any element of a vector can be replaced by another object.</li>
<li>The value of a binding can be replaced by another object.</li>
<li>A binding can be added to or deleted from an environment.</li>
</ul>
- <p>Replacing an object by another object can be thought of as replacing the object reference contained in a memory location by another object reference.</p>
+ <p>(As explained above, what replacing an object by another object really means is replacing a reference to an object by a reference to another object.)</p>
<p>The life cycle of an object, binding, or environment consists of the following events: a creation (which consists of an allocation followed by an initialization) followed by any number of alterations followed by a destruction (which consists of a deallocation). Alterations are possible only if the object, binding, or environment is mutable.</p>
<p>The destruction of an object, binding, or environment occurs automatically if and when the object, binding, or environment becomes unreachable. The rules used to determine if an object, binding, or environment is reachable are as follows (the concepts of global environment and control stack will be introduced later in this section):</p>
<ul>
+ <li>The symbols referenced from the packages are reachable.</li>
<li>The global environment is reachable.</li>
<li>An object, binding, or environment referenced from the currently active control stack is reachable.</li>
<li>An object, binding, or environment referenced from a reachable object, binding, or environment is reachable.</li>
<p>The primary value of a form whose evaluation completed normally is defined as follows: If the result consists of one or more objects, then the primary value of the form is the first object. Otherwise, the primary value of the form is <code>#v</code>.</p>
<p>Forms submitted to the evaluator through a <a href="#listener-buffers">listener buffer</a>, through the <a href="#evaluate-form">Evaluate Form</a> command, or through the <a href="#load-buffer">Load Buffer</a> command are called top-level forms. A consequence of the evaluation rules stated later in this section is that the evaluation of a top-level form usually entails the evaluation of other non-top-level forms.</p>
<p>Execution of EVLambda code is achieved through interpretation or compilation.</p>
- <p>An interpreter for a language <i>X</i> is a program capable of directly executing code written in language <i>X</i>. Language <i>X</i> is called the source language of the interpreter. A compiler for a language <i>X</i> is a program capable of translating code written in language <i>X</i> into code written in a language <i>Y</i>. Language <i>X</i> is called the source language of the compiler and language <i>Y</i> is called the target language of the compiler. Code handed to an interpreter or compiler is called source code. A file containing source code is called a source file. Code produced by a compiler is called compiled code. A file containing compiled code is called a compiled file.</p>
+ <p>An interpreter for a language $X$ is a program capable of directly executing code written in language $X$. Language $X$ is called the source language of the interpreter. A compiler for a language $X$ is a program capable of translating code written in language $X$ into code written in a language $Y$. Language $X$ is called the source language of the compiler and language $Y$ is called the target language of the compiler. Code handed to an interpreter or compiler is called source code. A file containing source code is called a source file. Code produced by a compiler is called compiled code. A file containing compiled code is called a compiled file.</p>
<p>An interpreter-based EVLambda evaluator executes EVLambda code by submitting the EVLambda code to its embedded EVLambda interpreter. A compiler-based EVLambda evaluator executes EVLambda code by first submitting the EVLambda code to its embedded EVLambda compiler and then arranging for the compiled code to be executed. Interpretation of EVLambda code and execution of compiled code occur at a time called run time. Compilation of EVLambda code occurs at a time called compile time.</p>
<p>EVLambda source files contain not only EVLambda source code but also documentation in XML format. Documentation is ignored by interpreters and compilers but can be converted to HTML, together with the EVLambda source code, by a component of the programming language called the documentation generator.</p>
<p>Each evaluation is done with respect to three environments: a global environment, a lexical environment, and a dynamic environment. The reference manual will introduce the concepts of scope and extent. The different environments draw their names from the scope and extent of their bindings:</p>
<li>A lexical environment contains bindings with lexical scope and indefinite extent.</li>
<li>A dynamic environment contains bindings with indefinite scope and dynamic extent.</li>
</ul>
- <p>The fact that a global/lexical/dynamic environment contains bindings with such scope and such extent is a consequence of the evaluation rules stated later in this section. It is thus not necessary to know the concepts of scope and extent to start writing programs in EVLambda. Knowing the evaluation rules should be enough.</p>
+ <p>The fact that a global/lexical/dynamic environment contains bindings with such scope and such extent is a direct consequence of the evaluation rules stated later in this section. It is thus not necessary to know the concepts of scope and extent to start writing programs in EVLambda. Knowing the evaluation rules should be enough.</p>
<p>Evaluations are all done with respect to the same global environment. That environment, referred to as “the global environment”, is created when the evaluator starts and continues to exist until the evaluator stops. The global environment of an evaluator that has just started contains a set of predefined bindings, most of which providing access to a primitive function. As forms are evaluated, the global environment can change in the following ways:</p>
<ul>
<li>Bindings can be added.</li>
<p>Evaluations are not all done with respect to the same lexical and dynamic environments. The lexical environment and the dynamic environments with respect to which a form is evaluated are referred to as “the current lexical environment” and “the current dynamic environment”, respectively.</p>
<p>Top-level forms are evaluated with respect to an initial lexical environment and an initial dynamic environment that are both empty.</p>
<p>A consequence of the evaluation rules stated later in this section is that non-top-level forms are evaluated with respect to (1) a lexical environment that is either the initial empty lexical environment or the result of extending, once or multiple times in sequence, the initial empty lexical environment and (2) a dynamic environment that is either the initial empty dynamic environment or the result of extending, once or multiple times in sequence, the initial empty dynamic environment.</p>
- <p>Let <i>env</i> be an environment, <i>ns</i> be a namespace of the environment, <i>n</i> be a non-negative integer, <i>var<sub>1</sub></i>, …, <i>var<sub>n</sub></i> be a sequence of <i>n</i> distinct variables, and <i>obj<sub>1</sub></i>, …, <i>obj<sub>n</sub></i> be a sequence of <i>n</i> objects. The environment extending the environment <i>env</i> to bind, in the namespace <i>ns</i>, the variable <i>var<sub>i</sub></i> to the object <i>obj<sub>i</sub></i> (for all <i>i</i> from 1 to <i>n</i>) is the environment obtained as follows:</p>
+ <p>Let $\env$ be an environment, $\ns$ be a namespace of the environment, $n$ be a nonnegative integer, $\var_1$, …, $\var_n$ be a sequence of $n$ distinct variables, and $\obj_1$, …, $\obj_n$ be a sequence of $n$ objects. The environment extending the environment $\env$ to bind, in the namespace $\ns$, the variable $\var_i$ to the object $\obj_i$ (for all $i$ from $1$ to $n$) is the environment obtained as follows:</p>
<ol>
- <li>Copy the environment <i>env</i> in such a way that (1) the environment <i>env</i> and its copy are distinct (steps 2 and 3 below must have no effect on the environment <i>env</i>) and (2) the environment <i>env</i> and its copy contain the exact same bindings (the bindings are not copied but shared between the two environments).</li>
- <li>For all <i>i</i> from 1 to <i>n</i>, delete from the copy of the namespace <i>ns</i> the binding for the variable <i>var<sub>i</sub></i>, if it exists.</li>
- <li>For all <i>i</i> from 1 to <i>n</i>, add to the copy of the namespace <i>ns</i> a new binding between the variable <i>var<sub>i</sub></i> and the object <i>obj<sub>i</sub></i>.</li>
+ <li>Copy the environment $\env$ in such a way that (1) the environment $\env$ and its copy are distinct (steps 2 and 3 below must have no effect on the environment $\env$) and (2) the environment $\env$ and its copy contain the exact same bindings (the bindings are not copied but shared between the two environments).</li>
+ <li>For all $i$ from $1$ to $n$, delete from the copy of the namespace $\ns$ the binding for the variable $\var_i$, if it exists.</li>
+ <li>For all $i$ from $1$ to $n$, add to the copy of the namespace $\ns$ a new binding between the variable $\var_i$ and the object $\obj_i$.</li>
</ol>
- <p>A binding deleted from the environment in step 2 is said to be shadowed by the binding for the same variable added to the environment in step 3. The extended environment is non-empty unless the environment being extended is empty and <i>n</i> is equal to zero.</p>
+ <p>A binding deleted from the environment in step 2 is said to be shadowed by the binding for the same variable added to the environment in step 3. The extended environment is nonempty unless the environment being extended is empty and $n$ is equal to zero.</p>
<p>Two additional consequences of the evaluation rules stated later in this section are that (1) the function namespace of a dynamic environment is always empty and (2) bindings are never added to or deleted from a lexical or dynamic environment after the environment has been created (that is, after the three steps mentioned above).</p>
<p>Together, the global environment, the current lexical environment, and the current dynamic environment can contain up to five bindings for any given variable:</p>
<ul>
<p>A consequence of the lookup rules is that a binding in the value/function namespace of the current lexical/dynamic environment will effectively shadow a binding for the same variable in the value/function namespace of the global environment.</p>
<p>A global variable is a binding between a variable and an object (of any type) in the value namespace of the global environment, or the name or value of such binding. A global function is a binding between a variable and a function other than a macro in the function namespace of the global environment, or the name or value of such binding. A global macro is a binding between a variable and a macro in the function namespace of the global environment, or the name or value of such binding. Global variables, global functions, and global macros are created and altered using language constructs called global definitions.</p>
<p>A local variable is a binding between a variable and an object (of any type) in the value namespace of a lexical environment, or the name or value of such binding. A local function is a binding between a variable and a function other than a macro in the function namespace of a lexical environment, or the name or value of such binding. A local macro is a binding between a variable and a macro in the function namespace of a lexical environment, or the name or value of such binding. A dynamic variable is a binding between a variable and an object (of any type) in the value namespace of a dynamic environment, or the name or value of such binding. Local variables, local functions, local macros, and dynamic variables are created (but not altered) using language constructs called binding constructs.</p>
- <p>When a form is submitted to the evaluator, the evaluator analyzes the form to determine how to evaluate it. If the form is the empty list, then the evaluation completes abnormally. Otherwise, if the form is neither a variable nor a cons, then the result of the evaluation is the form itself. (Objects that are neither the empty list, nor a variable, nor a cons are said to be self-evaluating.) Otherwise, if the form is a variable <i>var</i>, then the variable is treated as an abbreviation for either <code>(vref <i>var</i>)</code> or <code>(fref <i>var</i>)</code>, depending on the context of its occurrence. Otherwise, the form is necessarily a cons and the evaluation completes abnormally unless the form matches one of the following patterns:</p>
+ <p>When a form is submitted to the evaluator, the evaluator analyzes the form to determine how to evaluate it. If the form is the empty list, then the evaluation completes abnormally. Otherwise, if the form is neither a variable nor a cons, then the result of the evaluation is the form itself. (Objects that are neither the empty list, nor a variable, nor a cons are said to be self-evaluating.) Otherwise, if the form is a variable $\var$, then the variable is treated as an abbreviation for either <code>(vref $\var$)</code> or <code>(fref $\var$)</code>, depending on the context of its occurrence. Otherwise, the form is necessarily a cons and the evaluation completes abnormally unless the form matches one of the following patterns:</p>
<ol>
- <li><code>(quote <literal>)</code></li>
- <li><code>(progn <forms>)</code></li>
- <li><code>(if <test-form> <then-form> <else-form>)</code></li>
- <li><code>(_vlambda <parameter-list> <body>)</code></li>
- <li><code>(_mlambda <parameter-list> <body>)</code></li>
- <li><code>(_flambda <parameter-list> <body>)</code></li>
- <li><code>(_dlambda <parameter-list> <body>)</code></li>
- <li><code>(vref <variable>)</code></li>
- <li><code>(vset! <variable> <value-form>)</code></li>
- <li><code>(fref <variable>)</code></li>
- <li><code>(fset! <variable> <value-form>)</code></li>
- <li><code>(dref <variable>)</code></li>
- <li><code>(dset! <variable> <value-form>)</code></li>
- <li><code>(apply <operator> <operands>)</code></li>
- <li><code>(multiple-value-call <operator> <operands>)</code></li>
- <li><code>(multiple-value-apply <operator> <operands>)</code></li>
- <li><code>(<operator> <operands>)</code></li>
+ <li><code>(quote $\metavar{literal}$)</code></li>
+ <li><code>(progn $\metavar{serial-forms}$)</code></li>
+ <li><code>(if $\metavar{test-form}$ $\metavar{then-form}$ $\metavar{else-form}$)</code></li>
+ <li><code>(_vlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></li>
+ <li><code>(_mlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></li>
+ <li><code>(_flambda $\metavar{parameter-list}$ $\metavar{body}$)</code></li>
+ <li><code>(_dlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></li>
+ <li><code>(vref $\metavar{variable}$)</code></li>
+ <li><code>(vset! $\metavar{variable}$ $\metavar{value-form}$)</code></li>
+ <li><code>(fref $\metavar{variable}$)</code></li>
+ <li><code>(fset! $\metavar{variable}$ $\metavar{value-form}$)</code></li>
+ <li><code>(dref $\metavar{variable}$)</code></li>
+ <li><code>(dset! $\metavar{variable}$ $\metavar{value-form}$)</code></li>
+ <li><code>(apply $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></li>
+ <li><code>(multiple-value-call $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></li>
+ <li><code>(multiple-value-apply $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></li>
+ <li><code>($\metavar{macro-operator}$ $\metavar{macro-operands}$)</code></li>
+ <li><code>($\metavar{operator-form}$ $\metavar{operand-forms}$)</code></li>
</ol>
<p>Names enclosed in angle brackets have the following meanings:</p>
<ul>
- <li><code><literal></code> matches any object</li>
- <li><code><forms></code> matches any sequence of zero or more objects</li>
- <li><code><test-form></code> matches any object</li>
- <li><code><then-form></code> matches any object</li>
- <li><code><else-form></code> matches any object</li>
- <li><code><parameter-list></code> matches any list of distinct variables (as we will see in the reference manual, a parameter list can actually take two other forms)</li>
- <li><code><body></code> matches any sequence of zero or more objects</li>
- <li><code><variable></code> matches any variable</li>
- <li><code><value-form></code> matches any object</li>
- <li><code><operator></code> matches any object</li>
- <li><code><operands></code> matches any sequence of zero or more objects</li>
+ <li>$\metavar{literal}$ matches any object</li>
+ <li>$\metavar{serial-forms}$ matches any sequence of zero or more objects</li>
+ <li>$\metavar{test-form}$ matches any object</li>
+ <li>$\metavar{then-form}$ matches any object</li>
+ <li>$\metavar{else-form}$ matches any object</li>
+ <li>$\metavar{parameter-list}$ matches any list of distinct variables (as we will see in the reference manual, a parameter list can actually take two other forms)</li>
+ <li>$\metavar{body}$ matches any sequence of zero or more objects</li>
+ <li>$\metavar{variable}$ matches any variable</li>
+ <li>$\metavar{value-form}$ matches any object</li>
+ <li>$\metavar{operator-form}$ matches any object</li>
+ <li>$\metavar{operand-forms}$ matches any sequence of zero or more objects</li>
+ <li>$\metavar{macro-operator}$ matches any variable naming a macro according to the lookup rule used by <code>fref</code></li>
+ <li>$\metavar{macro-operands}$ matches any sequence of zero or more objects</li>
</ul>
<p>By way of example, a form matches the first pattern if and only if it is a list of two elements whose first element is the variable <code>quote</code>.</p>
- <p>The first sixteen patterns are mutually exclusive and have priority over pattern 17: If a form matches one of the first sixteen patterns, then pattern 17 is ignored.</p>
- <p>A form matching one of the first sixteen patterns is called a special form and the variables <code>quote</code>, <code>progn</code>, <code>if</code>, <code>_vlambda</code>, <code>_mlambda</code>, <code>_flambda</code>, <code>_dlambda</code>, <code>vref</code>, <code>vset!</code>, <code>fref</code>, <code>fset!</code>, <code>dref</code>, <code>dset!</code>, <code>apply</code>, <code>multiple-value-call</code>, and <code>multiple-value-apply</code> are called special operators. A form matching pattern 17 is either a macro call or a function call. If <code><operator></code> matches a variable naming a macro according to the lookup rule used by <code>fref</code>, then the form is a macro call. Otherwise, the form is a function call.</p>
- <p>Special forms matching patterns 4 (<code>_vlambda</code>), 5 (<code>_mlambda</code>), 6 (<code>_flambda</code>), or 7 (<code>_dlambda</code>) are the fundamental binding constructs from which all other binding constructs are built. Forms consisting of a variable and special forms matching pattern 8 (<code>vref</code>), 10 (<code>fref</code>), or 12 (<code>dref</code>) are called variable references. Special forms matching pattern 9 (<code>vset!</code>), 11 (<code>fset!</code>), or 13 (<code>dset!</code>) are called variable assignments.</p>
- <p>The rule regarding forms consisting of a variable is the following: If a variable <i>var</i> occurs in operator position, then the variable is treated as an abbreviation for <code>(fref <i>var</i>)</code> and the function namespace is used. Otherwise, the variable is treated as an abbreviation for <code>(vref <i>var</i>)</code> and the value namespace is used. For example, the function call <code>(f x)</code> would be treated as an abbreviation for <code>((fref f) (vref x))</code>. The full forms <code>(fref <i>var</i>)</code> and <code>(vref <i>var</i>)</code> can always be used to force the use of a specific namespace.</p>
- <p>As we will see momentarily, the evaluation of a form containing subforms entails the evaluation of some or all of the subforms. When a subform is evaluated, the following rules apply:</p>
+ <p>The patterns are tried in sequence and the first matching pattern wins.</p>
+ <p>A form matching one of the first sixteen patterns is called a special form and the variables <code>quote</code>, <code>progn</code>, <code>if</code>, <code>_vlambda</code>, <code>_mlambda</code>, <code>_flambda</code>, <code>_dlambda</code>, <code>vref</code>, <code>vset!</code>, <code>fref</code>, <code>fset!</code>, <code>dref</code>, <code>dset!</code>, <code>apply</code>, <code>multiple-value-call</code>, and <code>multiple-value-apply</code> are called special operators.</p>
+ <p>Special forms matching patterns 4 (<code>_vlambda</code>), 5 (<code>_mlambda</code>), 6 (<code>_flambda</code>), and 7 (<code>_dlambda</code>) are called lambda abstractions. Lambda abstractions are the fundamental binding constructs from which all other binding constructs are built. Forms consisting of a variable and special forms matching patterns 8 (<code>vref</code>), 10 (<code>fref</code>), and 12 (<code>dref</code>) are called variable references. Special forms matching patterns 9 (<code>vset!</code>), 11 (<code>fset!</code>), and 13 (<code>dset!</code>) are called variable assignments. Forms matching pattern 17 are called macro calls. Forms matching pattern 18 are called plain function calls.</p>
+ <p>The rule regarding forms consisting of a variable is the following: If a variable $\var$ occurs in operator position, then the variable is treated as an abbreviation for <code>(fref $\var$)</code> and the function namespace is used. Otherwise, the variable is treated as an abbreviation for <code>(vref $\var$)</code> and the value namespace is used. For example, the plain function call <code>(f x)</code> would be treated as an abbreviation for <code>((fref f) (vref x))</code>. The full forms <code>(fref $\var$)</code> and <code>(vref $\var$)</code> can always be used to force the use of a specific namespace.</p>
+ <p>As we will see below, the evaluation of a form containing subforms entails the evaluation of some or all of the subforms. When a subform is evaluated, the following rules apply:</p>
<ul>
<li>The subform is evaluated with respect to the same lexical and dynamic environments as the containing form. (But see below how closures are invoked.)</li>
<li>If the evaluation of the subform completes abnormally, then the evaluation of the containing form also completes abnormally.</li>
<li>If the evaluation of the subform does not complete, then the evaluation of the containing form does not complete either.</li>
</ul>
- <p>Special forms and calls are evaluated as follows:</p>
+ <p>Special forms, macro calls, and plain function calls are evaluated as follows:</p>
<dl>
- <dt><code>(quote <literal>)</code></dt>
- <dd>The quote-form evaluates to the unevaluated literal. Using a quote-form, any object can be treated as data. For any object <i>obj</i>, <code>(quote <i>obj</i>)</code> can be abbreviated to <code>'<i>obj</i></code>.</dd>
- <dt><code>(progn <forms>)</code></dt>
- <dd>The forms are evaluated in sequence from left to right. If there is at least one form, then the progn-form evaluates to the values of the last form. Otherwise, the progn-form evaluates to <code>#v</code>.</dd>
- <dt><code>(if <test-form> <then-form> <else-form>)</code></dt>
- <dd>The test-form is evaluated. Let <i>primval</i> be the primary value of the test-form. If <i>primval</i> is not a boolean, then the evaluation of the if-form completes abnormally. If <i>primval</i> is the boolean <code>#t</code>, then the then-form is evaluated and the if-form evaluates to the values of the then-form. If <i>primval</i> is the boolean <code>#f</code>, then the else-form is evaluated and the if-form evaluates to the values of the else-form.</dd>
- <dt><code>(_vlambda <parameter-list> <body>)</code></dt>
- <dt><code>(_mlambda <parameter-list> <body>)</code></dt>
- <dt><code>(_flambda <parameter-list> <body>)</code></dt>
- <dt><code>(_dlambda <parameter-list> <body>)</code></dt>
- <dd>A lambda-form evaluates to a closure recording the following two pieces of information: the lambda-form and the current lexical environment (which is said to be captured by the closure). A closure resulting from the evaluation of an _mlambda-form is tagged as being a macro.</dd>
- <dt><code>(vref <variable>)</code></dt>
- <dd>If there exists a binding for the variable in the value namespace of the current lexical environment, then the vref-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the vref-form evaluates to the value of that binding. Otherwise, the evaluation of the vref-form completes abnormally.</dd>
- <dt><code>(vset! <variable> <value-form>)</code></dt>
- <dd>The value-form is evaluated. Let <i>primval</i> be the primary value of the value-form. If there exists a binding for the variable in the value namespace of the current lexical environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, a new binding between the variable and <i>primval</i> is added to the value namespace of the global environment. In all three cases, the vset-form evaluates to <i>primval</i>.</dd>
- <dt><code>(fref <variable>)</code></dt>
- <dd>If there exists a binding for the variable in the function namespace of the current lexical environment, then the fref-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the function namespace of the global environment, then the fref-form evaluates to the value of that binding. Otherwise, the evaluation of the fref-form completes abnormally.</dd>
- <dt><code>(fset! <variable> <value-form>)</code></dt>
- <dd>The value-form is evaluated. Let <i>primval</i> be the primary value of the value-form. If there exists a binding for the variable in the function namespace of the current lexical environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, if there exists a binding for the variable in the function namespace of the global environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, a new binding between the variable and <i>primval</i> is added to the function namespace of the global environment. In all three cases, the fset-form evaluates to <i>primval</i>.</dd>
- <dt><code>(dref <variable>)</code></dt>
- <dd>If there exists a binding for the variable in the value namespace of the current dynamic environment, then the dref-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the dref-form evaluates to the value of that binding. Otherwise, the evaluation of the dref-form completes abnormally.</dd>
- <dt><code>(dset! <variable> <value-form>)</code></dt>
- <dd>The value-form is evaluated. Let <i>primval</i> be the primary value of the value-form. If there exists a binding for the variable in the value namespace of the current dynamic environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the value of that binding is replaced by <i>primval</i>. Otherwise, a new binding between the variable and <i>primval</i> is added to the value namespace of the global environment. In all three cases, the dset-form evaluates to <i>primval</i>.</dd>
- <dt><code>(apply <operator> <operands>)</code></dt>
- <dt><code>(multiple-value-call <operator> <operands>)</code></dt>
- <dt><code>(multiple-value-apply <operator> <operands>)</code></dt>
+ <dt><code>(quote $\metavar{literal}$)</code></dt>
+ <dd>The <code>quote</code>-form evaluates to the unevaluated literal. Using a <code>quote</code>-form, any object can be treated as data. For any object $\obj$, <code>(quote $\obj$)</code> can be abbreviated to <code>'$\obj$</code>.</dd>
+ <dt><code>(progn $\metavar{serial-forms}$)</code></dt>
+ <dd>The serial-forms are evaluated in sequence from left to right. If there is at least one serial-form, then the <code>progn</code>-form evaluates to the values of the last serial-form. Otherwise, the <code>progn</code>-form evaluates to <code>#v</code>.</dd>
+ <dt><code>(if $\metavar{test-form}$ $\metavar{then-form}$ $\metavar{else-form}$)</code></dt>
+ <dd>The test-form is evaluated. Let $\primval$ be the primary value of the test-form. If $\primval$ is not a boolean, then the evaluation of the <code>if</code>-form completes abnormally. If $\primval$ is the boolean <code>#t</code>, then the then-form is evaluated and the <code>if</code>-form evaluates to the values of the then-form. If $\primval$ is the boolean <code>#f</code>, then the else-form is evaluated and the <code>if</code>-form evaluates to the values of the else-form.</dd>
+ <dt><code>(_vlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dt><code>(_mlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dt><code>(_flambda $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dt><code>(_dlambda $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dd>A lambda abstraction evaluates to a closure recording the following two pieces of information: the lambda abstraction and the current lexical environment (which is said to be captured by the closure). A closure resulting from the evaluation of an <code>_mlambda</code>-form is tagged as being a macro.</dd>
+ <dt><code>(vref $\metavar{variable}$)</code></dt>
+ <dd>If there exists a binding for the variable in the value namespace of the current lexical environment, then the <code>vref</code>-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the <code>vref</code>-form evaluates to the value of that binding. Otherwise, the evaluation of the <code>vref</code>-form completes abnormally.</dd>
+ <dt><code>(vset! $\metavar{variable}$ $\metavar{value-form}$)</code></dt>
+ <dd>The value-form is evaluated. Let $\primval$ be the primary value of the value-form. If there exists a binding for the variable in the value namespace of the current lexical environment, then the value of that binding is replaced by $\primval$. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the value of that binding is replaced by $\primval$. Otherwise, a new binding between the variable and $\primval$ is added to the value namespace of the global environment. In all three cases, the <code>vset!</code>-form evaluates to $\primval$.</dd>
+ <dt><code>(fref $\metavar{variable}$)</code></dt>
+ <dd>If there exists a binding for the variable in the function namespace of the current lexical environment, then the <code>fref</code>-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the function namespace of the global environment, then the <code>fref</code>-form evaluates to the value of that binding. Otherwise, the evaluation of the <code>fref</code>-form completes abnormally.</dd>
+ <dt><code>(fset! $\metavar{variable}$ $\metavar{value-form}$)</code></dt>
+ <dd>The value-form is evaluated. Let $\primval$ be the primary value of the value-form. If there exists a binding for the variable in the function namespace of the current lexical environment, then the value of that binding is replaced by $\primval$. Otherwise, if there exists a binding for the variable in the function namespace of the global environment, then the value of that binding is replaced by $\primval$. Otherwise, a new binding between the variable and $\primval$ is added to the function namespace of the global environment. In all three cases, the <code>fset!</code>-form evaluates to $\primval$.</dd>
+ <dt><code>(dref $\metavar{variable}$)</code></dt>
+ <dd>If there exists a binding for the variable in the value namespace of the current dynamic environment, then the <code>dref</code>-form evaluates to the value of that binding. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the <code>dref</code>-form evaluates to the value of that binding. Otherwise, the evaluation of the <code>dref</code>-form completes abnormally.</dd>
+ <dt><code>(dset! $\metavar{variable}$ $\metavar{value-form}$)</code></dt>
+ <dd>The value-form is evaluated. Let $\primval$ be the primary value of the value-form. If there exists a binding for the variable in the value namespace of the current dynamic environment, then the value of that binding is replaced by $\primval$. Otherwise, if there exists a binding for the variable in the value namespace of the global environment, then the value of that binding is replaced by $\primval$. Otherwise, a new binding between the variable and $\primval$ is added to the value namespace of the global environment. In all three cases, the <code>dset!</code>-form evaluates to $\primval$.</dd>
+ <dt><code>(apply $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></dt>
+ <dt><code>(multiple-value-call $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></dt>
+ <dt><code>(multiple-value-apply $\metavar{operator-form}$ $\metavar{operand-forms}$)</code></dt>
<dd>Variants of the plain function call described below. Those variants are described in the reference manual.</dd>
- <dt><code>(<operator> <operands>)</code> classified as a macro call</dt>
- <dd>Following the definition of a macro call, <code><operator></code> matches a variable naming a macro according to the lookup rule used by <code>fref</code>. The macro is invoked on the unevaluated operands. If the invocation completes abnormally, then the evaluation of the macro call also completes abnormally. Otherwise, if the invocation does not complete, then the evaluation of the macro call does not complete either. Otherwise, the primary value of the invocation, which is called the expansion of the macro call, is evaluated with respect to the current lexical and dynamic environments. If the evaluation of the expansion completes abnormally, then the evaluation of the macro call also completes abnormally. Otherwise, if the evaluation of the expansion does not complete, then the evaluation of the macro call does not complete either. Otherwise, the macro call evaluates to the values of the expansion.</dd>
- <dt><code>(<operator> <operands>)</code> classified as a function call</dt>
- <dd>The operator and the operands are evaluated in sequence from left to right. If the primary value of the operator is not a function, then the evaluation of the function call completes abnormally. Otherwise, the primary value of the operator is invoked on the primary values of the operands. If the invocation completes abnormally, then the evaluation of the function call also completes abnormally. Otherwise, if the invocation does not complete, then the evaluation of the function call does not complete either. Otherwise, the function call evaluates to the values of the invocation.</dd>
+ <dt><code>($\metavar{macro-operator}$ $\metavar{macro-operands}$)</code></dt>
+ <dd>Following the definition of a macro call, the macro-operator matches a variable naming a macro according to the lookup rule used by <code>fref</code>. That macro is invoked on the unevaluated macro-operands. If the invocation completes abnormally, then the evaluation of the macro call also completes abnormally. Otherwise, if the invocation does not complete, then the evaluation of the macro call does not complete either. Otherwise, the primary value of the invocation, which is called the expansion of the macro call, is evaluated with respect to the current lexical and dynamic environments. If the evaluation of the expansion completes abnormally, then the evaluation of the macro call also completes abnormally. Otherwise, if the evaluation of the expansion does not complete, then the evaluation of the macro call does not complete either. Otherwise, the macro call evaluates to the values of the expansion.</dd>
+ <dt><code>($\metavar{operator-form}$ $\metavar{operand-forms}$)</code></dt>
+ <dd>The operator-form and the operand-forms are evaluated in sequence from left to right. If the primary value of the operator-form is not a function, then the evaluation of the plain function call completes abnormally. Otherwise, the primary value of the operator-form is invoked on the primary values of the operand-forms. If the invocation completes abnormally, then the evaluation of the plain function call also completes abnormally. Otherwise, if the invocation does not complete, then the evaluation of the plain function call does not complete either. Otherwise, the plain function call evaluates to the values of the invocation.</dd>
</dl>
<p>Invoking a function is what causes the function to compute the output corresponding to an input. The input of an invocation consists of zero or more objects—object references actually—called the arguments of the invocation. (The function is said to be invoked on the arguments and the arguments are said to be passed to the function.) The invocation of a function has three possible outcomes:</p>
<ul>
<blockquote>Let's assume that, as is the case with all the evaluators currently available, the primitive function is implemented by a JavaScript function accepting (an encoding of) the arguments of the invocation of the primitive function and returning (an encoding of) the values of the invocation of the primitive function. The JavaScript function is invoked on the arguments. If the invocation of the JavaScript function completes abnormally, then the invocation of the primitive function also completes abnormally. Otherwise, if the invocation of the JavaScript function does not complete, then the invocation of the primitive function does not complete either. Otherwise, the primitive function returns the values returned by the JavaScript function.</blockquote>
<p>A closure is invoked as follows:</p>
<blockquote>
- <p>If the number of variables in the parameter list of the lambda-form recorded by the closure and the number of arguments are different, then the invocation completes abnormally. (As we will see in the reference manual, it is actually possible to create closures accepting a variable number of arguments.) Otherwise, let <i>var<sub>1</sub></i>, …, <i>var<sub>n</sub></i> be the variables composing the parameter list of the lambda-form recorded by the closure, <i>arg<sub>1</sub></i>, …, <i>arg<sub>n</sub></i> be the arguments, and <i>lexenv</i> and <i>dynenv</i> be the following environments:</p>
+ <p>If the number of variables in the parameter list of the lambda abstraction recorded by the closure and the number of arguments are different, then the invocation completes abnormally. (As we will see in the reference manual, it is actually possible to create closures accepting a variable number of arguments.) Otherwise, let $\var_1$, …, $\var_n$ be the variables composing the parameter list of the lambda abstraction recorded by the closure, $\arg_1$, …, $\arg_n$ be the arguments, and $\lexenv$ and $\dynenv$ be the following environments:</p>
<ul>
- <li>If the closure results from the evaluation of a _vlambda-form or an _mlambda-form, then <i>lexenv</i> is the environment extending the lexical environment recorded by the closure to bind, in the value namespace, the variable <i>var<sub>i</sub></i> to the argument <i>arg<sub>i</sub></i> (for all <i>i</i> from 1 to <i>n</i>) and <i>dynenv</i> is the current dynamic environment.</li>
- <li>If the closure results from the evaluation of an _flambda-form, then <i>lexenv</i> is the environment extending the lexical environment recorded by the closure to bind, in the function namespace, the variable <i>var<sub>i</sub></i> to the argument <i>arg<sub>i</sub></i> (for all <i>i</i> from 1 to <i>n</i>) and <i>dynenv</i> is the current dynamic environment.</li>
- <li>If the closure results from the evaluation of a _dlambda-form, then <i>lexenv</i> is the lexical environment recorded by the closure and <i>dynenv</i> is the environment extending the current dynamic environment to bind, in the value namespace, the variable <i>var<sub>i</sub></i> to the argument <i>arg<sub>i</sub></i> (for all <i>i</i> from 1 to <i>n</i>).</li>
+ <li>If the closure results from the evaluation of a <code>_vlambda</code>-form or an <code>_mlambda</code>-form, then $\lexenv$ is the environment extending the lexical environment recorded by the closure to bind, in the value namespace, the variable $\var_i$ to the argument $\arg_i$ (for all $i$ from $1$ to $n$) and $\dynenv$ is the current dynamic environment.</li>
+ <li>If the closure results from the evaluation of an <code>_flambda</code>-form, then $\lexenv$ is the environment extending the lexical environment recorded by the closure to bind, in the function namespace, the variable $\var_i$ to the argument $\arg_i$ (for all $i$ from $1$ to $n$) and $\dynenv$ is the current dynamic environment.</li>
+ <li>If the closure results from the evaluation of a <code>_dlambda</code>-form, then $\lexenv$ is the lexical environment recorded by the closure and $\dynenv$ is the environment extending the current dynamic environment to bind, in the value namespace, the variable $\var_i$ to the argument $\arg_i$ (for all $i$ from $1$ to $n$).</li>
</ul>
- <p>The objects composing the body of the lambda-form recorded by the closure are evaluated with respect to <i>lexenv</i> and <i>dynenv</i> as if they were part of a progn-form. If the evaluation of the progn-form completes abnormally, then the invocation also completes abnormally. Otherwise, if the evaluation of the progn-form does not complete, then the invocation does not complete either. Otherwise, the closure returns the values of the progn-form.</p>
+ <p>The objects composing the body of the lambda abstraction recorded by the closure are evaluated with respect to $\lexenv$ and $\dynenv$ as if they were the serial-forms of a <code>progn</code>-form. If the evaluation of the <code>progn</code>-form completes abnormally, then the invocation also completes abnormally. Otherwise, if the evaluation of the <code>progn</code>-form does not complete, then the invocation does not complete either. Otherwise, the closure returns the values of the <code>progn</code>-form.</p>
</blockquote>
- <p>The special operators <code>_vlambda</code>, <code>_mlambda</code>, <code>_flambda</code>, and <code>_dlambda</code> have an underscore at the beginning of their names to distinguish them from the similarly named macros <code>vlambda</code>, <code>mlambda</code>, <code>flambda</code>, and <code>dlambda</code>. As we will see in the reference manual, the purpose of those macros is to facilitate the creation of closures accepting a variable number of arguments.</p>
- <p>The evaluator uses a data structure called a control stack to coordinate its activities. Each time a top-level form is submitted to the evaluator, a new control stack is created that will be used throughout the evaluation of the form. The same control stack is used to evaluate the top-level form and all non-top-level forms whose evaluations are entailed by the evaluation of the top-level form.</p>
+ <p>The special operators <code>_vlambda</code>, <code>_mlambda</code>, <code>_flambda</code>, and <code>_dlambda</code> have an underscore at the beginning of their names to distinguish them from the similarly named macros <code>vlambda</code>, <code>mlambda</code>, <code>flambda</code>, and <code>dlambda</code>. The purpose of those macros is to facilitate the creation of closures accepting a variable number of arguments.</p>
+ <p>The evaluator uses a data structure called the control stack to coordinate its activities. Each time a top-level form is submitted to the evaluator, a new control stack is created that will be used throughout the evaluation of the form. The same control stack is used to evaluate the top-level form and all non-top-level forms whose evaluations are entailed by the evaluation of the top-level form.</p>
<p>An evaluation/invocation that completes normally produces a result/output consisting of zero or more objects. The production of that result/output, which only occurs if the evaluation/invocation completes normally, is the primary effect of the evaluation/invocation. In addition to or in place of its primary effect, an evaluation/invocation can also have secondary effects called side effects. Examples of side effects are:</p>
<ul>
<li>The abnormal completion of the evaluation/invocation.</li>
<p>It is customary for a special operator, function, or macro that can alter an object, binding, or environment to have a name ending with an exclamation mark. This explains the exclamation mark in the names of the special operators <code>vset!</code>, <code>fset!</code>, and <code>dset!</code>.</p>
<h2>Integrated Development Environment</h2>
<p>The integrated development environment (IDE) is a web application that can run either from the EVLambda web server (online mode) or from a web server running on your machine (offline mode). The code running in the web browser is exactly the same in both modes but the behavior of the IDE is slightly different because the backends have different capabilities.</p>
- <p>The IDE's graphical user interface consists of a menu bar at the top left, an info bar at the top right, a minibuffer at the bottom, and a set of windows in the main area. Each window consists of a contents area and a status bar. At any given time, a window displays the contents of a buffer, of which there are two types: the file buffers and the listener buffers.</p>
+ <p>The IDE's graphical user interface consists of a menu bar at the top left, an info bar at the top right, a minibuffer at the bottom, and a set of windows in the main area. Each window consists of a contents area and a status bar. At any given time, a window displays the contents of a buffer, of which there are two types: the file buffers and the listener buffers. A given buffer can be displayed in any number of windows (including zero) and any buffer can be displayed in any window. This organization around buffers and windows is borrowed from the <a href="https://www.gnu.org/software/emacs/" target="_blank">Emacs</a> text editor.</p>
<p>A file buffer is a buffer whose contents reflects the contents of a file. The contents of the buffer is read from the file through open and revert operations and written into the file through save operations. When a window displays the contents of a file buffer, its status bar displays the name of the file, followed by a star when the current contents of the buffer differs from the contents that was last read from or written into the file.</p>
<p>When the IDE starts, it automatically opens a predefined set of files. In online mode, the files are located in a directory on the machine hosting the EVLambda web server. In offline mode, the files are located in the directory <code><EVLAMBDA_HOME>/system-files</code> on your machine.</p>
<p>A listener buffer is a buffer that allows you to evaluate forms interactively. When a window displays the contents of a listener buffer, its status bar displays the name of the buffer. Currently, the IDE has exactly one listener buffer whose name is “Listener 1”.</p>
- <p>At any given time, there is exactly one selected window and, by extension, exactly one selected buffer. The status bar of the selected window is darker than the status bar of the non-selected windows. A window becomes the selected window when it receives the focus, which happens for instance when it receives a click event.</p>
+ <p>At any given time, there is exactly one selected window and, by extension, exactly one selected buffer. The status bar of the selected window is darker than the status bar of the nonselected windows. A window becomes the selected window when it receives the focus, which happens for instance when it receives a click event.</p>
<p>Currently, the only function of the minibuffer is to display messages and evaluation results.</p>
- <p>The organization of the IDE around buffers is borrowed from the <a href="https://www.gnu.org/software/emacs/" target="_blank">Emacs</a> text editor.</p>
<h2>File Buffers</h2>
- <p>A window can display the contents of a file buffer in one of two modes: raw mode or HTML mode. In raw mode, the contents of the buffer is displayed in an instance of the <a href="https://codemirror.net/" target="_blank">CodeMirror</a> text editor. In HTML mode, the contents of the buffer, or an HTML document derived from the contents of the buffer, is displayed in rendered form.</p>
+ <p>A window can display the contents of a file buffer in one of two modes: raw mode or HTML mode. In raw mode, the contents of the buffer is displayed in the <a href="https://codemirror.net/" target="_blank">CodeMirror</a> text editor. In HTML mode, the contents of the buffer, or some HTML contents derived from the contents of the buffer, is displayed in an HTML viewer.</p>
<p>The all-caps files (USER-MANUAL, …), which are actually HTML files, can be displayed in raw mode or HTML mode. The EVLambda source files (extension <code>.evl</code>), which contain a mix of EVLambda source code and documentation in XML format, can be displayed in raw mode or HTML mode. The other types of files are always displayed in raw mode.</p>
<h2 id="listener-buffers">Listener Buffers</h2>
<p>A listener buffer allows you to evaluate forms interactively. To evaluate a form in a listener buffer, you type in a readable representation of the form after the prompt and press the Return or Enter key when the cursor is at the very end of the buffer. In response, the form is evaluated, the printable representations of the resulting values are printed separated by a newline, and a new prompt is printed, allowing you to evaluate another form. This sequence of operations is called a read-eval-print loop (REPL).</p>
<ul>
<li>The prompt is the greater-than sign printed at the beginning of a line to inform you that the listener buffer is waiting for a form to be typed in.</li>
<li>If you press the Return or Enter key when (1) the cursor is not at the very end of the buffer or (2) the form is missing or incomplete, then a newline is simply inserted into the buffer and no evaluation takes place.</li>
- <li>If the evaluation completes abnormally, then a message describing the error is printed in place of the printable representations of the (non-existing) resulting values.</li>
+ <li>If the evaluation completes abnormally, then a message describing the error is printed in place of the printable representations of the (nonexisting) resulting values.</li>
<li>If the evaluation does not complete, then you must abort the evaluation or restart the evaluator in order to get a new prompt.</li>
</ul>
- <p>We will now illustrate some of the concepts introduced in the section <a href="#programming-language">Programming Language</a> by providing a commented transcript of a sequence of evaluations conducted in a listener buffer. If you want to reproduce the evaluations, be sure to start with a fresh Trampoline++ evaluator. To get a fresh Trampoline++ evaluator, restart the evaluator (using the Restart Evaluator… command from the Eval menu) and select Trampoline++ as the evaluator type.</p>
- <p>Here are the global functions that will be used in the evaluations. For each function, a template function call and a description of the function are provided. The variable in operator position is the name of the function (i.e., the variable bound to the function in the function namespace of the global environment).</p>
+ <p>We will now illustrate some of the concepts introduced in the section <a href="#programming-language">Programming Language</a> by providing a commented transcript of a sequence of evaluations conducted in a listener buffer. If you want to reproduce the evaluations, be sure to start with a fresh Trampoline++ evaluator. To get a fresh Trampoline++ evaluator, restart the evaluator (using the Restart Evaluator… command from the Eval menu) with Trampoline++ selected as the evaluator type.</p>
+ <p>The global functions used in the evaluations are listed below. For each function, a template function call and a description of the function are provided. The variable in operator position is the name of the function (i.e., the variable bound to the function in the function namespace of the global environment).</p>
<dl>
- <dt><code>(car <i>cons</i>)</code></dt>
+ <dt><code>(car $\cons$)</code></dt>
<dd>The function <code>car</code> returns the first element of its argument, which must be of type <code>cons</code>.</dd>
- <dt><code>(cdr <i>cons</i>)</code></dt>
+ <dt><code>(cdr $\cons$)</code></dt>
<dd>The function <code>cdr</code> returns the second element of its argument, which must be of type <code>cons</code>.</dd>
- <dt><code>(list <i>object<sub>1</sub></i> … <i>object<sub>n</sub></i>)</code></dt>
- <dd>The function <code>list</code> collects its arguments into a list: when invoked on the arguments <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>, the function returns a list whose elements are <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>.</dd>
- <dt><code>(+ <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(list $\object_1\ldots\object_n$)</code></dt>
+ <dd>The function <code>list</code> collects its arguments, which can be of any types, into a list: when invoked on the arguments $\object_1$, …, $\object_n$, the function returns a list whose elements are $\object_1$, …, $\object_n$.</dd>
+ <dt><code>(+ $\number_1\ldots\number_n$)</code></dt>
<dd>The function <code>+</code> returns the sum of its arguments, which must be of type <code>number</code>.</dd>
- <dt><code>(* <i>number<sub>1</sub></i> … <i>number<sub>n</sub></i>)</code></dt>
+ <dt><code>(* $\number_1\ldots\number_n$)</code></dt>
<dd>The function <code>*</code> returns the product of its arguments, which must be of type <code>number</code>.</dd>
- <dt><code>(values <i>object<sub>1</sub></i> … <i>object<sub>n</sub></i>)</code></dt>
- <dd>The function <code>values</code> converts its arguments into values: when invoked on the arguments <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>, the function returns the values <i>object<sub>1</sub></i>, …, <i>object<sub>n</sub></i>.</dd>
+ <dt><code>(values $\object_1\ldots\object_n$)</code></dt>
+ <dd>The function <code>values</code> converts its arguments, which can be of any types, into values: when invoked on the arguments $\object_1$, …, $\object_n$, the function returns the values $\object_1$, …, $\object_n$.</dd>
</dl>
- <p>Here are the global macros that will be used in the evaluations. For each macro, a template macro call and a description of the macro are provided. The variable in operator position is the name of the macro (i.e., the variable bound to the macro in the function namespace of the global environment).</p>
+ <p>The global macros used in the evaluations are listed below. For each macro, a template macro call and a description of the macro are provided. The variable in operator position is the name of the macro (i.e., the variable bound to the macro in the function namespace of the global environment).</p>
<dl>
- <dt><code>(vdef <variable> <value-form>)</code></dt>
+ <dt><code>(vdef $\metavar{variable}$ $\metavar{value-form}$)</code></dt>
<dd>The purpose of the macro <code>vdef</code> is to define a global variable by ensuring that the variable is bound in the value namespace of the global environment to the primary value of the value-form. The macro call evaluates to the variable.</dd>
- <dt><code>(fdef <variable> <parameter-list> <body>)</code></dt>
- <dd>The purpose of the macro <code>fdef</code> is to define a global function by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the _vlambda-form <code>(_vlambda <parameter-list> <body>)</code>. The macro call evaluates to the variable.</dd>
- <dt><code>(loop <forms>)</code></dt>
- <dd>The purpose of the macro <code>loop</code> is to create an infinite loop repeatedly evaluating the forms in sequence from left to right. For example, the macro call <code>(loop)</code> endlessly does nothing. The evaluation of the macro call normally does not complete but there are ways to exit an infinite loop.</dd>
+ <dt><code>(fdef $\metavar{variable}$ $\metavar{parameter-list}$ $\metavar{body}$)</code></dt>
+ <dd>The purpose of the macro <code>fdef</code> is to define a global function by ensuring that the variable is bound in the function namespace of the global environment to the closure resulting from the evaluation of the <code>_vlambda</code>-form <code>(_vlambda $\metavar{parameter-list}$ $\metavar{body}$)</code>. The macro call evaluates to the variable.</dd>
+ <dt><code>(loop $\metavar{serial-forms}$)</code></dt>
+ <dd>The purpose of the macro <code>loop</code> is to create an infinite loop repeatedly evaluating the serial-forms in sequence from left to right. For example, the macro call <code>(loop)</code> endlessly does nothing. The evaluation of the macro call normally does not complete but there are ways to exit an infinite loop.</dd>
</dl>
- <p>And here is the commented transcript, where each box contains a form and its values. The character ⏎ marks the places where the Return or Enter key should be pressed.</p>
+ <p>Here is the commented transcript, where each gray box contains a form and its values. The character ⏎ marks the places where the Return or Enter key should be pressed.</p>
<pre class="repl">> (+ 1 2)⏎<br>3</pre>
<p>The evaluation produces a result consisting of the sum of the two numbers <code>1</code> and <code>2</code>. Because numbers are self-evaluating, quoting the numbers is not necessary.</p>
<pre class="repl">> (+ '1 '2)⏎<br>3</pre>
<p>The evaluation produces the same result if the numbers are quoted. Quoting self-evaluating objects is unidiomatic, though.</p>
<pre class="repl">> (car '(1 2 3))⏎<br>1</pre>
<p>The evaluation produces a result consisting of the first element of the list <code>(1 2 3)</code>. Because lists are not self-evaluating, quoting the list is necessary.</p>
- <pre class="repl">> (car (1 2 3))⏎<br>ERROR: The operator form does not evaluate to a function.</pre>
- <p>The evaluation completes abnormally if the list is not quoted. The reason is as follows: The evaluator treats the list <code>(1 2 3)</code> as a function call and the operator, the number <code>1</code>, does not evaluate to a function.</p>
+ <pre class="repl">> (car (1 2 3))⏎<br>ERROR: The operator-form does not evaluate to a function.</pre>
+ <p>The evaluation completes abnormally if the list is not quoted. The reason is as follows: The evaluator treats the list <code>(1 2 3)</code> as a plain function call and the operator-form, the number <code>1</code>, does not evaluate to a function.</p>
<pre class="repl">> (cdr '(1 2 3))⏎<br>(2 3)</pre>
<p>The evaluation produces a result consisting of the sublist of the list <code>(1 2 3)</code> obtained by omitting its first element.</p>
<pre class="repl">> (car (cdr '(1 2 3)))⏎<br>2</pre>
<pre class="repl">> (disk-area 2)⏎<br>ERROR: The variable 'disk-area' is unbound in the FUNCTION namespace.</pre>
<p>The evaluation completes abnormally because the global function <code>disk-area</code> is undefined.</p>
<pre class="repl">> (fdef disk-area (r) (* 3.14 r r))⏎<br>disk-area</pre>
- <p>The evaluation produces a result consisting of the variable <code>disk-area</code>. More importantly, the evaluation has the side effect of defining the global function <code>disk-area</code>. The function accepts the radius of a disk and returns the area of the disk computed using <code>3.14</code> as the value of pi. When the function is invoked, its body is evaluated with respect to a lexical environment binding, in the value namespace, the variable <code>r</code> to the argument of the invocation (that is, the radius of the disk).</p>
+ <p>The evaluation produces a result consisting of the variable <code>disk-area</code>. More importantly, the evaluation has the side effect of defining the global function <code>disk-area</code>. In its intended usage, the function accepts the radius of a disk and returns the area of the disk computed using <code>3.14</code> as the value of pi. When the function is invoked, its body is evaluated with respect to a lexical environment binding, in the value namespace, the variable <code>r</code> to the argument of the invocation (that is, the radius of the disk).</p>
<pre class="repl">> (disk-area 2)⏎<br>12.56</pre>
<p>The evaluation produces the expected result.</p>
<pre class="repl">> (fdef disk-area (r) (* 3.1416 r r))⏎<br>disk-area</pre>
<h3>Edit Menu</h3>
<h4>Toggle HTML Mode</h4>
<p>Toggles the selected window between raw and HTML modes.</p>
- <p>This command is only available when the selected window displays the contents of an all-caps file or EVLambda source file.</p>
+ <p>This command is only available when the selected window displays the contents of an all-caps file or an EVLambda source file.</p>
<h4>Clear Listener…</h4>
<p>Clears the selected listener buffer.</p>
<p>All contents before the last prompt is deleted.</p>
<h3>Eval Menu</h3>
<h4 id="evaluate-form">Evaluate Form</h4>
<p>Evaluates a top-level form contained inside the selected file buffer.</p>
- <p>This command is only available on EVLambda source files.</p>
+ <p>This command is only available when the selected window displays the contents of an EVLambda source file.</p>
<p>A top-level form is a form that is not contained inside another form.</p>
<p>The top-level form to evaluate is selected as follows:</p>
<ul>
<li>If a top-level form is covering the cursor position, then that form is selected for evaluation.</li>
<li>Otherwise, if the character directly after the cursor position is the first character of a top-level form, then that form is selected for evaluation.</li>
- <li>Otherwise, if the first non-blank character before the cursor position is the last character of a top-level form, then that form is selected for evaluation.</li>
+ <li>Otherwise, if the first nonblank character before the cursor position is the last character of a top-level form, then that form is selected for evaluation.</li>
<li>Otherwise, no form is selected for evaluation and no evaluation takes place.</li>
</ul>
<p>If the evaluation of the top-level form completes normally, then the printable representations of the resulting values are printed in the minibuffer, separated by a comma. If the evaluation of the top-level form completes abnormally, then a message describing the error is printed in the minibuffer. If the evaluation of the top-level form does not complete, then no new evaluation is possible until the evaluation is aborted or the evaluator is restarted.</p>
<h4 id="load-buffer">Load Buffer</h4>
<p>Evaluates the top-level forms contained inside the selected file buffer.</p>
- <p>This command is only available on EVLambda source files.</p>
- <p>The top-level forms contained inside the selected file buffer are evaluated as if they were part of a progn-form.</p>
- <p>If the evaluation of the progn-form completes normally, then the printable representations of the resulting values are printed in the minibuffer, separated by a comma. If the evaluation of the progn-form completes abnormally, then a message describing the error is printed in the minibuffer. If the evaluation of the progn-form does not complete, then no new evaluation is possible until the evaluation is aborted or the evaluator is restarted.</p>
+ <p>This command is only available when the selected window displays the contents of an EVLambda source file.</p>
+ <p>The top-level forms contained inside the selected file buffer are evaluated as if they were part of a <code>progn</code>-form.</p>
+ <p>If the evaluation of the <code>progn</code>-form completes normally, then the printable representations of the resulting values are printed in the minibuffer, separated by a comma. If the evaluation of the <code>progn</code>-form completes abnormally, then a message describing the error is printed in the minibuffer. If the evaluation of the <code>progn</code>-form does not complete, then no new evaluation is possible until the evaluation is aborted or the evaluator is restarted.</p>
<h4>Abort Evaluation</h4>
<p>Aborts the current evaluation.</p>
<h4>Restart Evaluator…</h4>
<p>Only the Trampoline and Trampoline++ evaluators allow unbounded iterations through tail-recursive calls. The other evaluators are only useful as stepping stones to understand the Trampoline and Trampoline++ evaluators. The Trampoline++ evaluator is an optimized version of the Trampoline evaluator.</p>
<h3>View Menu</h3>
<h4>Select Other Window</h4>
- <p>Selects one of the non-selected windows.</p>
+ <p>Selects one of the nonselected windows.</p>
<p>This command is not available when the selected window is maximized.</p>
<h4>Toggle Maximized State</h4>
<p>Toggles the selected window between unmaximized and maximized states.</p>
<!--<li><code>/system/IMPLEMENTATION-NOTES</code>: the implementation notes</li>-->
<li><code>/system/BIBLIOGRAPHY</code>: the bibliography</li>
<li><code>/system/LICENSE</code>: the license</li>
- <li><code>/system/all-caps.css</code>: the CSS file styling all-caps files</li>
- <li><code>/system/all-caps.js</code>: the JavaScript file loaded by all-caps files</li>
+ <li><code>/system/all-caps.css</code>: the CSS file styling the all-caps files</li>
+ <li><code>/system/all-caps.js</code>: the JavaScript file loaded by the all-caps files</li>
<li><code>/system/core.js</code>: the JavaScript file implementing the evaluators, the primitive data types, the primitive functions, etc., constituting the “core” of the EVLambda programming language</li>
- <li><code>/system/evl2html.xslt</code>: the XSLT file used to convert EVLambda source files to HTML</li>
- <li><code>/system/evl2html.css</code>: the CSS file styling EVLambda source files converted to HTML</li>
- <li><code>/system/evl2html.js</code>: the JavaScript file loaded by EVLambda source files converted to HTML</li>
- <li><code>/system/mantle.evl</code>: the EVLambda source file implementing the non-primitive data types, the non-primitive functions, and the macros constituting the “mantle” of the EVLambda programming language</li>
+ <li><code>/system/evl2html.xslt</code>: the XSLT file used to convert the EVLambda source files to HTML</li>
+ <li><code>/system/evl2html.css</code>: the CSS file styling the EVLambda source files converted to HTML</li>
+ <li><code>/system/evl2html.js</code>: the JavaScript file loaded by the EVLambda source files converted to HTML</li>
+ <li><code>/system/mantle.evl</code>: the EVLambda source file implementing the nonprimitive data types, the nonprimitive functions, and the macros constituting the “mantle” of the EVLambda programming language</li>
<li><code>Listener 1</code>: the initial listener</li>
</ul>
<h3>Help Menu</h3>
<li>Changelog: link to the changelog</li>
<li>Contact: link to the contact page</li>
<li>My Account: link to the login page (if not logged in) or to the account page (if logged in)</li>
- <li>Git Repository: link to the official Git repository's web interface</li>
+ <li>Git Repository: link to the web interface of the official Git repository</li>
<li>Discussions: link to the discussion forum</li>
<li>Issues: link to the issue tracker</li>
<li>Cookie Policy: link to the cookie policy</li>
line-height: 1.4;
}
+div.preamble {
+ display: none;
+}
+
.bg {
background-color: lightgray;
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 Raphaël Van Dyck
// SPDX-License-Identifier: BSD-3-Clause
+/******************/
+/* Event Handlers */
+/******************/
+
window.addEventListener('focus', event => {
window.parent.dispatchEvent(new CustomEvent('iframeFocus', {detail: windowId}));
});
event.preventDefault();
}
});
+
+/***********/
+/* MathJax */
+/***********/
+
+const origin = document.location.origin;
+
+window.MathJax = {
+ options: {
+ skipHtmlTags: {'[-]': ['code']}
+ },
+ loader: {
+ load: ['[tex]/texhtml']
+ },
+ tex: {
+ packages: {'[+]': ['texhtml']},
+ allowTexHTML: true,
+ inlineMath: {'[+]': [['$', '$']]},
+ macros: {
+ code: ['<tex-html><code>#1</code></tex-html>', 1],
+ mlvar: ['\\textit{#1}', 1],
+ metavar: ['\\langle\\textrm{#1}\\rangle', 1],
+ metavarn: ['\\langle\\textrm{#1}_{#2}\\rangle', 2],
+ form: '\\mlvar{form}',
+ var: '\\mlvar{var}',
+ arg: '\\mlvar{arg}',
+ obj: '\\mlvar{obj}',
+ fun: '\\mlvar{fun}',
+ env: '\\mlvar{env}',
+ lexenv: '\\mlvar{lexenv}',
+ dynenv: '\\mlvar{dynenv}',
+ ns: '\\mlvar{ns}',
+ binding: '\\mlvar{binding}',
+ vbind: '\\rightarrow_\\mathrm{v}',
+ vbinding: ['\\code{#1}\\vbind\\code{#2}', 2],
+ fbind: '\\rightarrow_\\mathrm{f}',
+ fbinding: ['\\code{#1}\\fbind\\code{#2}', 2],
+ primval: '\\mlvar{primval}',
+ type: '\\mlvar{type}',
+ object: '\\mlvar{object}',
+ void: '\\mlvar{void}',
+ boolean: '\\mlvar{boolean}',
+ number: '\\mlvar{number}',
+ character: '\\mlvar{character}',
+ string: '\\mlvar{string}',
+ symbol: '\\mlvar{symbol}',
+ keyword: '\\mlvar{keyword}',
+ variable: '\\mlvar{variable}',
+ list: '\\mlvar{list}',
+ emptylist: '\\mlvar{empty-list}',
+ cons: '\\mlvar{cons}',
+ vector: '\\mlvar{vector}',
+ function: '\\mlvar{function}',
+ primitivefunction: '\\mlvar{primitive-function}',
+ closure: '\\mlvar{closure}'
+ }
+ },
+ output: {
+ //font: 'mathjax-newcm',
+ font: 'mathjax-stix2',
+ fontPath: origin + '/ide/%%FONT%%-font',
+ displayAlign: 'left',
+ displayIndent: '2em',
+ displayOverflow: 'linebreak',
+ linebreaks: {
+ inline: true
+ }
+ }
+};
+
+(function () {
+ var script = document.createElement('script');
+ script.src = origin + '/ide/mathjax/tex-chtml-nofont.js';
+ script.defer = true;
+ document.head.appendChild(script);
+})();
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 Raphaël Van Dyck
// SPDX-License-Identifier: BSD-3-Clause
+/******************/
+/* Event Handlers */
+/******************/
+
window.addEventListener('focus', event => {
window.parent.dispatchEvent(new CustomEvent('iframeFocus', {detail: windowId}));
});
import HTMLWebpackPlugin from 'html-webpack-plugin';
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
+import CopyWebpackPlugin from 'copy-webpack-plugin';
import AdmZip from 'adm-zip';
import LicenseChecker from 'license-checker';
import url from 'url';
pkgs.set(key.substring(0, key.lastIndexOf('@')), value);
}
const modules = new Set();
+ modules.add('mathjax');
+ modules.add('@mathjax/mathjax-newcm-font');
+ modules.add('@mathjax/mathjax-stix2-font');
for (const [pathname, module] of stats.compilation._modules.entries()) {
const match = pathname.match(/\/node_modules\/([^@][^\/]*)\//);
// .../node_modules/xxx/... => xxx
entry: './src/ide.jsx',
output: {
path: path.join(__dirname, 'ide'),
- filename: 'bundle.js',
+ filename: 'ide.js',
clean: true
},
module: {
new ESLintWebpackPlugin({
extensions: ['js', 'jsx']
}),
+ new CopyWebpackPlugin({
+ patterns: [
+ {
+ from: path.join(__dirname, 'node_modules', 'mathjax'),
+ to: path.join(__dirname, 'ide', 'mathjax')
+ },
+ {
+ from: path.join(__dirname, 'node_modules', '@mathjax', 'mathjax-newcm-font'),
+ to: path.join(__dirname, 'ide', 'mathjax-newcm-font')
+ },
+ {
+ from: path.join(__dirname, 'node_modules', '@mathjax', 'mathjax-stix2-font'),
+ to: path.join(__dirname, 'ide', 'mathjax-stix2-font')
+ }
+ ]
+ }),
new ArchiveSystemFilesWebpackPlugin(),
new GenerateBOMWebpackPlugin()
],