851 lines
52 KiB
HTML
851 lines
52 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang='en'><head><meta charset='utf-8' /><meta name='pinterest' content='nopin' /><link href='http://stevelosh.com/static/css/style.css' rel='stylesheet' type='text/css' /><link href='http://stevelosh.com/static/css/print.css' rel='stylesheet' type='text/css' media='print' /><title>What the Hell is Symbolic Computation? / Steve Losh</title></head><body><header><a id='logo' href='http://stevelosh.com/'>Steve Losh</a><nav><a href='http://stevelosh.com/blog/'>Blog</a> - <a href='http://stevelosh.com/projects/'>Projects</a> - <a href='http://stevelosh.com/photography/'>Photography</a> - <a href='http://stevelosh.com/links/'>Links</a> - <a href='http://stevelosh.com/rss.xml'>Feed</a></nav></header><hr class='main-separator' /><main id='page-blog-entry'><article><h1><a href='index.html'>What the Hell is Symbolic Computation?</a></h1><p class='date'>Posted on June 29th, 2016.</p><p>I've been reading a lot of Lisp books lately, some more advanced than others.
|
||
|
All of the introductory books I've seen cover the idea of symbolic computation,
|
||
|
but most of them breeze past it with just a few pages about "symbols" and
|
||
|
"quoting". For many programmers coming from non-Lisp languages these are new,
|
||
|
foreign concepts that don't really map back to anything in their previous
|
||
|
experience. But the books seem to expect you to understand this things after
|
||
|
just a couple of paragraphs.</p>
|
||
|
|
||
|
<p>One book that <em>does</em> spend more time on this is the appropriately-named <a href="http://www.amazon.com/dp/0486498204/?tag=stelos-20">Common
|
||
|
Lisp: A Gentle Introduction to Symbolic Computation</a>. If you're looking
|
||
|
for a good introductory Lisp book, that's the one I'd recommend. However, it's
|
||
|
quite a long book and starts at the <em>very</em> basics (you don't even write code for
|
||
|
the first few chapters — you program with drawings). If you already know some
|
||
|
Lisp then you might find yourself bored if you go through the entire thing just
|
||
|
for the symbolic computation bits.</p>
|
||
|
|
||
|
<p>This post is an attempt to explain what symbols <em>actually are</em> and what quoting
|
||
|
does. You'll get the most out of it if you're already familiar with the basics
|
||
|
of Lisp (i.e. you aren't scared by the parentheses). But if you already know
|
||
|
what something like this would print, you'll probably be bored:</p>
|
||
|
|
||
|
<pre><code>(let ((foo ''a))
|
||
|
(print foo)
|
||
|
(print 'foo)
|
||
|
(print (car foo))
|
||
|
(print (cdr foo)))</code></pre>
|
||
|
|
||
|
<ol class="table-of-contents"><li><a href="index.html#s1-disclaimer">Disclaimer</a></li><li><a href="index.html#s2-the-repl">The REPL</a></li><li><a href="index.html#s3-loop">Loop</a></li><li><a href="index.html#s4-print">Print</a></li><li><a href="index.html#s5-read">Read</a></li><li><a href="index.html#s6-the-rpl">The RPL</a></li><li><a href="index.html#s7-reading-other-data">Reading Other Data</a></li><li><a href="index.html#s8-readable-printing">Readable Printing</a></li><li><a href="index.html#s9-reading-non-lisp">Reading Non-Lisp</a></li><li><a href="index.html#s10-evaluating-non-lisp">Evaluating Non-Lisp</a></li><li><a href="index.html#s11-reading-lisp">Reading Lisp</a></li><li><a href="index.html#s12-symbols">Symbols</a></li><li><a href="index.html#s13-evaluating-lisp">Evaluating Lisp</a><ol><li><a href="index.html#s14-strings-and-numbers">Strings and Numbers</a></li><li><a href="index.html#s15-basic-lists">Basic Lists</a></li><li><a href="index.html#s16-variables">Variables</a></li><li><a href="index.html#s17-special-forms">Special Forms</a></li><li><a href="index.html#s18-an-ouroborromean-paradox">An Ouroborromean Paradox?</a></li><li><a href="index.html#s19-exercises">Exercises</a></li></ol></li><li><a href="index.html#s20-quote">Quote</a><ol><li><a href="index.html#s21-the-special-operator">The Special Operator</a></li><li><a href="index.html#s22-the-read-macro">The Read Macro</a></li><li><a href="index.html#s23-exercises">Exercises</a></li></ol></li><li><a href="index.html#s24-a-quick-recap">A Quick Recap</a></li><li><a href="index.html#s25-where-to-go-from-here">Where to Go From Here</a></li></ol>
|
||
|
|
||
|
<h2 id="s1-disclaimer"><a href="index.html#s1-disclaimer">Disclaimer</a></h2>
|
||
|
|
||
|
<p>Before we start I'll get this warning out of the way: I'm going to gloss over
|
||
|
a lot of gory details to get at the important core ideas.</p>
|
||
|
|
||
|
<p>When I say "this thing is implemented like so" it's safe to assume that in
|
||
|
reality things are messier and more complicated and will vary between
|
||
|
implementations and dialects. My goal is to give you some intuition for the
|
||
|
basic ideas, not to exhaustively cover how a particular implementation works.</p>
|
||
|
|
||
|
<p>I'll be using Common Lisp for the examples, but the concepts apply equally to
|
||
|
Scheme, Clojure, and other Lisps too.</p>
|
||
|
|
||
|
<p>With that out of the way, let's dive in!</p>
|
||
|
|
||
|
<h2 id="s2-the-repl"><a href="index.html#s2-the-repl">The REPL</a></h2>
|
||
|
|
||
|
<p>The Read-Eval-Print-Loop that so many languages these days have built-in is
|
||
|
a good place to start in our exploration. You're probably familiar with the
|
||
|
idea of a REPL from languages like Python, Ruby, Javascript, etc. In Python it
|
||
|
looks like this:</p>
|
||
|
|
||
|
<pre><code>$ python
|
||
|
>>> if True:
|
||
|
... print "Yes"
|
||
|
... else:
|
||
|
... print "No"
|
||
|
...
|
||
|
Yes</code></pre>
|
||
|
|
||
|
<p>A handwavey definition of a REPL could be something like this:</p>
|
||
|
|
||
|
<blockquote>
|
||
|
<p>A REPL is a program that lets you type in code. It runs that code, prints out
|
||
|
the result, and loops back to the beginning to let you type in more.</p>
|
||
|
</blockquote>
|
||
|
|
||
|
<p>This is a good first start, but to understand symbols we're going to need to get
|
||
|
a much clearer, more precise handle on what exactly each letter in "REPL" means.
|
||
|
We'll start backwards and outside-in with the simplest component.</p>
|
||
|
|
||
|
<h2 id="s3-loop"><a href="index.html#s3-loop">Loop</a></h2>
|
||
|
|
||
|
<p>The "L" in "REPL" stands for "Loop", and it's the easiest part to understand.
|
||
|
A REPL doesn't just process one bit of code and then exit, it loops forever (or
|
||
|
until you tell it to quit).</p>
|
||
|
|
||
|
<p>There's not a lot to say here, except that we'll go ahead and lump together the
|
||
|
extra busywork a REPL needs to do into this step so we can ignore it for the
|
||
|
rest of the post. This includes things like:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Printing the nice prompt at the beginning (<code>>>></code> or <code>...</code> in Python).</li>
|
||
|
<li>Checking for <code>Ctrl-D</code> to quit.</li>
|
||
|
<li>Handling exceptions (so they don't kill the process).</li>
|
||
|
</ul>
|
||
|
|
||
|
<h2 id="s4-print"><a href="index.html#s4-print">Print</a></h2>
|
||
|
|
||
|
<p>The next letter is "P" for "Print". Like <code>loop</code> this should be familiar
|
||
|
territory, but let's nail down <em>exactly</em> what it does. The job of the <code>print</code>
|
||
|
function is to:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Take as input some kind of object/data structure in memory.</li>
|
||
|
<li>Produce some series of characters (a string) that represent this object.</li>
|
||
|
<li>Write those characters somewhere (standard output, a text panel in a GUI, etc).</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>For example: if we give the integer <code>1</code> to Python's <code>print</code>, it produces
|
||
|
a string of two characters (the digit <code>1</code> and a newline) and writes it to the
|
||
|
terminal. There are a lot of little details that aren't important here (line
|
||
|
endings, string encoding, where the output actually goes, etc). The important
|
||
|
part that you should fix in your mind is this:</p>
|
||
|
|
||
|
<p><strong><code>print</code> takes an object, converts it into a string, and outputs it.</strong></p>
|
||
|
|
||
|
<p>Note: I've called <code>print</code> a function here, and I'll do the same for <code>read</code> and
|
||
|
<code>eval</code> later on. This is correct for Common Lisp, but not necessarily for
|
||
|
languages like Python or Javascript. For the purposes of this post you can just
|
||
|
imagine them as functions and realize that in the real world they're more like
|
||
|
"phases" that have a lot more complex machinery under them.</p>
|
||
|
|
||
|
<h2 id="s5-read"><a href="index.html#s5-read">Read</a></h2>
|
||
|
|
||
|
<p>We'll jump over to the other side of the acronym now. "R" is for "Read", and
|
||
|
this is where things start to get tricky.</p>
|
||
|
|
||
|
<p>In most non-Lisp languages the "read" and "eval" phases of the REPL tend to get
|
||
|
blurred together, but if you want to understand symbolic computation in Lisp you
|
||
|
absolutely <em>must</em> keep these two parts cleanly separated in your mind.</p>
|
||
|
|
||
|
<p>We can define <code>read</code> as almost the polar opposite of <code>print</code>. <code>read</code> is
|
||
|
a function whose job is to:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Take as input a string of characters from some source.</li>
|
||
|
<li>"Decode" that string and produce some kind of object in memory.</li>
|
||
|
<li>Return that object.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Notice how this mirrors <code>print</code>:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>print</code>: Object → Characters</li>
|
||
|
<li><code>read</code>: Characters → Object</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>This is the second definition you need to fix in your brain:</p>
|
||
|
|
||
|
<p><strong><code>print</code> takes an object, converts it into a string, and outputs it.</strong><br>
|
||
|
<strong><code>read</code> takes a string, converts it into an object, and returns it.</strong></p>
|
||
|
|
||
|
<p>If we <code>read</code> in the string <code>1.0</code> (that's three ASCII characters), we'll get some
|
||
|
kind of floating point number object back. Sometimes there are many ways to
|
||
|
represent the same object in memory. For example: <code>read</code>ing the strings <code>1.0</code>
|
||
|
and <code>1.0000</code> will both produce equivalent floating point objects representing
|
||
|
the number "one".</p>
|
||
|
|
||
|
<p>Side note (if you're not feeling pedantic feel free to skip this): the word
|
||
|
"equivalent" here is a bit tricky. When you <code>read</code> two strings like <code>1.0</code> and
|
||
|
<code>1.000</code> you might get back two pointers to the same hunk of memory, or you might
|
||
|
get back two pointers to two separate hunks of memory, or even just a machine
|
||
|
word representing the floating point number directly. It depends on the
|
||
|
language (and even the implementation). What I mean by "equivalent" is that
|
||
|
there's no way to tell which value came from which input. You can't say "this
|
||
|
hunk of memory must have come from the string <code>1.000</code>" because <code>read</code> has
|
||
|
"sanitized" the input by that point.</p>
|
||
|
|
||
|
<h2 id="s6-the-rpl"><a href="index.html#s6-the-rpl">The RPL</a></h2>
|
||
|
|
||
|
<p>So now we've got <code>read</code>, <code>print</code>, and <code>loop</code>. <code>read</code> takes characters from
|
||
|
a stream and produces objects, and <code>print</code> takes objects and produces characters
|
||
|
and writes them to a stream. We're still missing a letter, but what would
|
||
|
happen if we just hook these three up together right now?</p>
|
||
|
|
||
|
<pre><code>CL-USER> (loop (print (read)))
|
||
|
> 1
|
||
|
1
|
||
|
> 1.0
|
||
|
1.0
|
||
|
> 1.00000
|
||
|
1.0</code></pre>
|
||
|
|
||
|
<p>I've added a little <code>></code> prompt to the output here to make it clear where I'm
|
||
|
typing.</p>
|
||
|
|
||
|
<p>Essentially what we've got here is a little pretty-printer! Notice how things
|
||
|
like extra whitespace and useless zeroes got stripped out. This isn't terribly
|
||
|
useful, but at least it's doing <em>something</em>.</p>
|
||
|
|
||
|
<p>However, it's important to realize where the "prettifying" actually happened:
|
||
|
<code>read</code> actually did the hard work! By the time <code>print</code> got its grubby little
|
||
|
paws on those one-point-zeroes the extra whitespace and digits were long gone.
|
||
|
Maybe we should give credit where it's due and call this a "pretty-reader"
|
||
|
instead.</p>
|
||
|
|
||
|
<h2 id="s7-reading-other-data"><a href="index.html#s7-reading-other-data">Reading Other Data</a></h2>
|
||
|
|
||
|
<p>Up to this point I've been using numbers as examples because they're simple, but
|
||
|
of course we can read and print lots of other kinds of things. Lists and
|
||
|
strings (and lists <em>of</em> strings!) are some common examples:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (print (read))
|
||
|
> ("hello" "world")
|
||
|
("hello" "world")
|
||
|
|
||
|
$ python
|
||
|
>>> [ "hello" , "world"]
|
||
|
['hello', 'world']</code></pre>
|
||
|
|
||
|
<p>There are lots of other kinds of things you can read and print, depending on the
|
||
|
particular language. What's important here is the strict separation of <code>read</code>
|
||
|
and <code>print</code>.</p>
|
||
|
|
||
|
<h2 id="s8-readable-printing"><a href="index.html#s8-readable-printing">Readable Printing</a></h2>
|
||
|
|
||
|
<p>Before we move on, one thing we should talk about is the idea of "readable
|
||
|
printing". This idea becomes clear almost immediately when you work at the
|
||
|
Python REPL:</p>
|
||
|
|
||
|
<pre><code>$ python
|
||
|
>>> "foo\nbar"
|
||
|
'foo\nbar'
|
||
|
>>> print "foo\nbar"
|
||
|
foo
|
||
|
bar</code></pre>
|
||
|
|
||
|
<p>Why was the first string printed with quotes and an escaped newline, and the
|
||
|
second without quotes and an actual newline?</p>
|
||
|
|
||
|
<p>When we defined <code>print</code> earlier, one of the steps was:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Produce some series of characters (a string) that represent this object.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Much like there are many character strings that result in the same object (e.g.
|
||
|
<code>1.0</code> and <code>1.000</code>) there are often many ways we can represent a particular
|
||
|
object as a series of characters. For example: we can represent the number two
|
||
|
as <code>2</code>, or <code>10</code> in binary, or <code>two</code> in English. We can represent a string as
|
||
|
the actual characters in it, or we could represent it "escaped" like Python does
|
||
|
in the first line.</p>
|
||
|
|
||
|
<p>The core idea here is that of <strong>"readable printing": printing the characters you
|
||
|
would need to give to <code>read</code> to produce this object</strong>.</p>
|
||
|
|
||
|
<p>This is different from what I'll call <strong>"aesthetic printing": printing
|
||
|
characters for this object which look nice to a human</strong>.</p>
|
||
|
|
||
|
<p>In Python these two kinds of printing are seen in the separate <a href="https://brennerm.github.io/posts/python-str-vs-repr.html"><code>__str__</code> and
|
||
|
<code>__repr__</code> methods</a>. In Common Lisp it's controlled by the
|
||
|
<a href="http://clhs.lisp.se/Body/v_pr_rda.htm"><code>*print-readably*</code> variable</a>. Other languages have different
|
||
|
mechanisms.</p>
|
||
|
|
||
|
<h2 id="s9-reading-non-lisp"><a href="index.html#s9-reading-non-lisp">Reading Non-Lisp</a></h2>
|
||
|
|
||
|
<p>So we know how reading and printing <em>data</em> works, but you can do more than that
|
||
|
at a typical REPL. Let's revisit the first Python example:</p>
|
||
|
|
||
|
<pre><code>$ python
|
||
|
>>> if True:
|
||
|
... print "Yes"
|
||
|
... else:
|
||
|
... print "No"
|
||
|
...
|
||
|
Yes</code></pre>
|
||
|
|
||
|
<p>We know that <code>read</code> takes a series of characters and turns them into an object.
|
||
|
When we <code>read</code> this series of characters, what comes out the other end? For
|
||
|
most languages (Python, Ruby, Javascript, Scala, etc) the answer is some kind of
|
||
|
<a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree">abstract syntax tree</a> represented as a data structure. You might imagine
|
||
|
something like this buried deep within the guts of the Python interpreter:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="special">class</span><span class="keyword"> IfStatement</span><span class="paren1">(<span class="code">ASTNode</span>)</span>:
|
||
|
<span class="special">def</span><span class="keyword"> __init__</span><span class="paren1">(<span class="code">self, test_node, then_node, else_node</span>)</span>:
|
||
|
self.test_node = test_node
|
||
|
self.then_node = then_node
|
||
|
self.else_node = else_node</span></code></pre>
|
||
|
|
||
|
<p>The details would surely be a lot hairier in the real world, but the general
|
||
|
idea is that the stream of characters representing your code gets read in and
|
||
|
parsed into some kind of data structure in memory.</p>
|
||
|
|
||
|
<p>This is all well and good, but our example printed "Yes", which certainly isn't
|
||
|
a representation of an AST node. Where did that come from? To answer that
|
||
|
we'll need the final letter in the acronym.</p>
|
||
|
|
||
|
<h2 id="s10-evaluating-non-lisp"><a href="index.html#s10-evaluating-non-lisp">Evaluating Non-Lisp</a></h2>
|
||
|
|
||
|
<p>The "E" in REPL stands for "Eval".</p>
|
||
|
|
||
|
<p>This is the last time we'll consider Python in this post, because we're about to
|
||
|
move past it to more powerful ideas. In Python, the purpose of the <code>eval</code> phase
|
||
|
of the REPL is to:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Take an AST node (or simple data) as input.</li>
|
||
|
<li>Run the code (also known as <em>evaluating</em> it).</li>
|
||
|
<li>Return the result (if any).</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>This is fairly straightforward, at least for our simple <code>if</code> statement. Python
|
||
|
will evaluate the <code>test_node</code> part of the <code>if</code>, and then evaluate one of the
|
||
|
other parts depending on whether the test was truthy or falsey.</p>
|
||
|
|
||
|
<p>Of course the actual process of evaluating real-life Python code is much more
|
||
|
complicated than I've glossed over here, but this is good enough for us to use
|
||
|
as a springboard to dive into the beautiful world of Lisp.</p>
|
||
|
|
||
|
<h2 id="s11-reading-lisp"><a href="index.html#s11-reading-lisp">Reading Lisp</a></h2>
|
||
|
|
||
|
<p>When we talked about reading the Python <code>if</code> statement I said that Python would
|
||
|
parse it into some kind of data structure representing an AST node. I didn't
|
||
|
point you at the <em>actual</em> data structure in the Python source code because
|
||
|
I have no idea where it actually <em>is</em>, and it's probably not nearly as simple as
|
||
|
the one I sketched out.</p>
|
||
|
|
||
|
<p>Now that we're talking about Lisp, however, I <em>really can</em> show you exactly what
|
||
|
an <code>if</code> statement in Lisp reads as! I'll use <code>read-from-string</code> to make it
|
||
|
a bit easier to see what's input and what's output, but it would work the same
|
||
|
way with just plain old <code>read</code> and input from standard in. Here we go:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (print
|
||
|
(read-from-string "(if t (print 1) (print 2))"))
|
||
|
|
||
|
(IF T (PRINT 1) (PRINT 2))
|
||
|
|
||
|
CL-USER> (type-of
|
||
|
(read-from-string "(if t (print 1) (print 2))"))
|
||
|
|
||
|
CONS</code></pre>
|
||
|
|
||
|
<p>Instead of some kind of AST node data structure buried deep within the heart of
|
||
|
our implementation we get... a list! An ordinary, garden-variety, vanilla list
|
||
|
made of good old trusty cons cells!</p>
|
||
|
|
||
|
<p>The list we get contains four elements, two of which are themselves lists. But
|
||
|
what do these lists actually <em>contain</em>?</p>
|
||
|
|
||
|
<p>The numbers are simple enough — we saw them earlier. <code>read</code> turns a series of
|
||
|
digits into a number somewhere in memory, and <code>print</code> spits out a series of
|
||
|
characters that represent the number:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (type-of (read-from-string "100"))
|
||
|
|
||
|
(INTEGER 0 4611686018427387903)</code></pre>
|
||
|
|
||
|
<p>The string <code>100</code> does indeed represent an integer between zero and four
|
||
|
squillion-something.</p>
|
||
|
|
||
|
<p>But what are those <em>other</em> things in our list? The <code>if</code> and <code>t</code> and <code>print</code>?
|
||
|
Are they some magic keywords internal to the guts of our Lisp that <code>print</code> is
|
||
|
just outputting nicely for our benefit?</p>
|
||
|
|
||
|
<pre><code>CL-USER> (type-of (read-from-string "if"))
|
||
|
|
||
|
SYMBOL</code></pre>
|
||
|
|
||
|
<p>Buckle up — it's time to learn about symbols.</p>
|
||
|
|
||
|
<h2 id="s12-symbols"><a href="index.html#s12-symbols">Symbols</a></h2>
|
||
|
|
||
|
<p>A symbol in Lisp is <a href="http://www.lispworks.com/documentation/lw70/CLHS/Body/t_symbol.htm">a simple data structure</a> that turns out to be
|
||
|
<em>extremely</em> useful. You can imagine it being defined something like this:</p>
|
||
|
|
||
|
<pre><code>(defstruct symbol
|
||
|
name
|
||
|
function
|
||
|
value
|
||
|
property-list
|
||
|
package)</code></pre>
|
||
|
|
||
|
<p>The <code>name</code> of a symbol is a string of characters representing the symbol's name:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (type-of (read-from-string "if"))
|
||
|
|
||
|
SYMBOL
|
||
|
|
||
|
CL-USER> (symbol-name (read-from-string "if"))
|
||
|
|
||
|
"IF"</code></pre>
|
||
|
|
||
|
<p>Symbols get created (usually) when they are <code>read</code> for the first time. If you
|
||
|
<code>read</code> a sequence of characters that matches the name of an existing symbol
|
||
|
(let's ignore the lowercase/uppercase thing for now), <code>read</code> just returns that
|
||
|
existing symbol:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (eq (read-from-string "cats")
|
||
|
(read-from-string "cats"))
|
||
|
|
||
|
T</code></pre>
|
||
|
|
||
|
<p>Here <code>read</code> saw the string <code>cats</code> and created a new symbol somewhere in memory
|
||
|
with <code>CATS</code> as its <code>name</code>. The second call to <code>read-from-string</code> read in the
|
||
|
string <code>cats</code>, saw an existing symbol with the matching name, and just returned
|
||
|
it straight away. That's why <code>eq</code> returned true — the two <code>read</code> calls
|
||
|
returned pointers to the exact same hunk of memory.</p>
|
||
|
|
||
|
<p>(<code>read</code> also "interned" the symbol into the current package. We're going to
|
||
|
ignore the package system for this post — it's not important to the core
|
||
|
topic. We'll also ignore the property list.)</p>
|
||
|
|
||
|
<p>So to recap:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>read</code> is a function that takes characters and turns them into objects.</li>
|
||
|
<li>When you feed <code>read</code> certain strings of characters (i.e. without special
|
||
|
characters), it returns a symbol object whose name matches those characters
|
||
|
(creating it if necessary).</li>
|
||
|
<li>Symbols are just normal Lisp data structures with a few specific fields.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>So what does <code>print</code> do with a symbol? It just prints the <code>name</code>!</p>
|
||
|
|
||
|
<pre><code>CL-USER> (print (read-from-string "cats"))
|
||
|
|
||
|
CATS</code></pre>
|
||
|
|
||
|
<p>Simple enough. Note that this is <em>readably printed</em> — if we feed it back to
|
||
|
<code>read</code> we'll get an equivalent symbol back (the <em>exact same</em> symbol, in fact).</p>
|
||
|
|
||
|
<p>But wait! If we <code>read</code> symbols in and they're just normal vanilla structures,
|
||
|
then how do we actually <em>do</em> anything in Lisp? How does anything actually
|
||
|
<em>run</em>?</p>
|
||
|
|
||
|
<h2 id="s13-evaluating-lisp"><a href="index.html#s13-evaluating-lisp">Evaluating Lisp</a></h2>
|
||
|
|
||
|
<p>Now we need to go back to <code>eval</code>. In the Python example I handwaved a bit and
|
||
|
said that <code>eval</code> "ran the code" but didn't really explain how that happened.
|
||
|
Now that we're in the warm embrace of Lisp we can nail things down a lot more
|
||
|
cleanly.</p>
|
||
|
|
||
|
<p><code>eval</code> (in Lisp) is a function whose job is to:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Take an object.</li>
|
||
|
<li>Do something useful with it to get another object.</li>
|
||
|
<li>Return the resulting object.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>I know, I know, that seems as clear as a brick. But if we can actually define
|
||
|
what "something useful" means it will be a lot more helpful. Lisp's <code>eval</code>
|
||
|
follows a few simple rules to produce its output.</p>
|
||
|
|
||
|
<h3 id="s14-strings-and-numbers"><a href="index.html#s14-strings-and-numbers">Strings and Numbers</a></h3>
|
||
|
|
||
|
<p>First of all, <code>eval</code> will just pass numbers and strings straight through without
|
||
|
touching them at all:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>This makes sense because there's not a lot more useful stuff you can do with
|
||
|
a number or a string on its own. I suppose you could write a language where the
|
||
|
evaluation phase ran all numbers through the absolute value function because you
|
||
|
wanted to remove all negativity from programming or something, but that seems
|
||
|
a bit esoteric.</p>
|
||
|
|
||
|
<h3 id="s15-basic-lists"><a href="index.html#s15-basic-lists">Basic Lists</a></h3>
|
||
|
|
||
|
<p>What about lists, like our friend the <code>if</code> statement (a list of four things)?
|
||
|
Well the first thing anyone learns about Lisp is the funny syntax. In most
|
||
|
cases, when passed a list <code>eval</code> treats the first element as the name of
|
||
|
a function, and the rest as the arguments. It will evaluate the arguments and
|
||
|
call the function with them:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">typep thing 'list</span>)</span>
|
||
|
<span class="paren4">(<span class="code">destructuring-bind <span class="paren5">(<span class="code">head . arguments</span>)</span> thing
|
||
|
<span class="paren5">(<span class="code">apply <span class="paren6">(<span class="code">symbol-function head</span>)</span>
|
||
|
<span class="paren6">(<span class="code">mapcar #'eval arguments</span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>At this point we know enough to understand exactly what happens when we say
|
||
|
something like <code>(+ 1 2)</code> at a Lisp REPL!</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Lisp <code>read</code>s the seven characters we gave it, which becomes a list of three
|
||
|
objects: the symbol <code>+</code>, the integer <code>1</code>, and the integer <code>2</code>.</li>
|
||
|
<li>Lisp passes that three-object list to <code>eval</code>.</li>
|
||
|
<li><code>eval</code> looks up what is in the <code>function</code> slot of the symbol at the front of
|
||
|
the list (that symbol is <code>+</code>).</li>
|
||
|
<li>The symbol <code>+</code> was helpfully given a function by the Lisp implementation (run
|
||
|
<code>(symbol-function (read-from-string "+"))</code> to confirm that I'm not lying to
|
||
|
you).</li>
|
||
|
<li>Lisp evaluates each item in the rest of the list. In this case they're each
|
||
|
a number, so each one evaluates to itself.</li>
|
||
|
<li>Lisp calls the function with the evaluated arguments to get a result (in this
|
||
|
case: the integer <code>3</code>).</li>
|
||
|
<li>Lisp passes the result to <code>print</code>, which turns it into a string of characters
|
||
|
(one character, in this case) and prints it to standard out.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Whew! That seems like a lot, but each piece is pretty small. Go slowly through
|
||
|
it and make sure you <em>really</em> understand each step in the preceding list before
|
||
|
you move on.</p>
|
||
|
|
||
|
<p>If you don't believe me that this is really how it works, try this:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (setf (symbol-function (read-from-string "square"))
|
||
|
(lambda (x) (* x x)))
|
||
|
|
||
|
#<FUNCTION (LAMBDA (X)) {1005DCF2FB}>
|
||
|
|
||
|
CL-USER> (square 4)
|
||
|
|
||
|
16</code></pre>
|
||
|
|
||
|
<p>We set the <code>function</code> slot of the symbol <code>square</code> to be a function that squares
|
||
|
its argument, and then we can run it like any other function.</p>
|
||
|
|
||
|
<p>Trace through the evaluation of that last <code>(square 4)</code> call before moving on.</p>
|
||
|
|
||
|
<h3 id="s16-variables"><a href="index.html#s16-variables">Variables</a></h3>
|
||
|
|
||
|
<p>What about symbols that <em>aren't</em> at the front of a list? For example:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (defvar ten 10)
|
||
|
|
||
|
10
|
||
|
|
||
|
CL-USER> (square ten)
|
||
|
|
||
|
100</code></pre>
|
||
|
|
||
|
<p>In this case, everything proceeds as it did before until the recursive call to
|
||
|
<code>eval</code> the argument to <code>square</code>. The argument is just a bare symbol (not
|
||
|
a number or a list or a string), so we need another rule in our <code>eval</code> function:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">symbolp thing</span>)</span> <span class="paren4">(<span class="code">symbol-value thing</span>)</span></span>)</span> <span class="comment">; NEW
|
||
|
</span> <span class="paren3">(<span class="code"><span class="paren4">(<span class="code">listp thing</span>)</span>
|
||
|
<span class="paren4">(<span class="code">destructuring-bind <span class="paren5">(<span class="code">head . arguments</span>)</span>
|
||
|
<span class="paren5">(<span class="code">apply <span class="paren6">(<span class="code">symbol-function head</span>)</span>
|
||
|
<span class="paren6">(<span class="code">mapcar #'eval arguments</span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>If <code>eval</code> sees a symbol on its own, it will just return whatever is in the
|
||
|
<code>value</code> slot of the symbol data structure. Simple enough!</p>
|
||
|
|
||
|
<h3 id="s17-special-forms"><a href="index.html#s17-special-forms">Special Forms</a></h3>
|
||
|
|
||
|
<p>If course there are a few things we haven't talked about yet. First of all:
|
||
|
there are some "magic" symbols that aren't functions, but are hardcoded into the
|
||
|
evaluation function to do certain things. In Common Lisp they're called
|
||
|
<a href="http://www.lispworks.com/documentation/HyperSpec/Body/03_ababa.htm">"special operators"</a> and there are twenty-five of them.</p>
|
||
|
|
||
|
<p>Let's add a special rule to our <code>eval</code> function to handle one of them (our old
|
||
|
friend <code>if</code>):</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">symbolp thing</span>)</span> <span class="paren4">(<span class="code">symbol-value thing</span>)</span></span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">listp thing</span>)</span>
|
||
|
<span class="paren4">(<span class="code">destructuring-bind <span class="paren5">(<span class="code">head . arguments</span>)</span> thing
|
||
|
<span class="paren5">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren6">(<span class="code"><span class="paren1">(<span class="code">eq head <span class="paren2">(<span class="code">read-from-string <span class="string">"if"</span></span>)</span></span>)</span> <span class="comment">; NEW
|
||
|
</span> <span class="paren1">(<span class="code">destructuring-bind <span class="paren2">(<span class="code">test then else</span>)</span> arguments
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">if</span></i> <span class="paren3">(<span class="code">eval test</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval then</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval else</span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="paren6">(<span class="code">t
|
||
|
<span class="paren1">(<span class="code">apply <span class="paren2">(<span class="code">symbol-function head</span>)</span>
|
||
|
<span class="paren2">(<span class="code">mapcar #'eval arguments</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>At this point your head might be starting to hurt. How have we just used <code>if</code>
|
||
|
to define itself? Is anything here actually <em>real</em>, or is Lisp just a serpent
|
||
|
eating its own tail forever?</p>
|
||
|
|
||
|
<h3 id="s18-an-ouroborromean-paradox"><a href="index.html#s18-an-ouroborromean-paradox">An Ouroborromean Paradox?</a></h3>
|
||
|
|
||
|
<p>If the "metacircularity" (god, I hate that word) of what we've just done bothers
|
||
|
you, remember that this <code>eval</code> function here is just a sample of how you <em>can</em>
|
||
|
write it in Lisp. You could also write it in some other language, like C or
|
||
|
Java (see: <a href="https://common-lisp.net/project/armedbear/">ABCL</a>) or really anything. That would let you "bottom out" to
|
||
|
something that's not Lisp.</p>
|
||
|
|
||
|
<p>But really, is that any <em>less</em> circular? You still need <em>some</em> language to run
|
||
|
the thing! Why does an <code>eval</code> written in C seem less "cheaty" than one written
|
||
|
in Lisp? Because it compiles to machine code? Try
|
||
|
<code>(disassemble #'sb-impl::simple-eval-in-lexenv)</code> in SBCL and you'll get a few
|
||
|
thousand bytes of x86 assembly that was <a href="https://github.com/sbcl/sbcl/blob/fdc4e9fa86b5eaaf8939f004a66e4be075069aa8/src/code/eval.lisp#L131-L272">originally some Lisp code much like
|
||
|
ours</a>.</p>
|
||
|
|
||
|
<p>My advice is to just let it flow over you, even if you feel a bit uneasy at the
|
||
|
sight of something like this. Eventually as you become more at home in your
|
||
|
chosen Lisp, writing high-level code one moment and <code>disassemble</code>ing a function
|
||
|
the next, you'll make peace with the serpent.</p>
|
||
|
|
||
|
<h3 id="s19-exercises"><a href="index.html#s19-exercises">Exercises</a></h3>
|
||
|
|
||
|
<p>There are quite a few things in <code>eval</code> that we haven't covered here, like the
|
||
|
other twenty-four special operators, lexical variables, lambda forms, and more.
|
||
|
But this should be enough for you to wrap your head around symbols and how
|
||
|
they're used in Lisp.</p>
|
||
|
|
||
|
<p>Before we move on to the final part of this story, make sure you can figure out
|
||
|
the answers to these questions:</p>
|
||
|
|
||
|
<ol>
|
||
|
<li>What does the single character <code>1</code> read as? What does it evaluate to?</li>
|
||
|
<li>What do the characters <code>"hello\"world"</code> read as? What do they evaluate to?
|
||
|
How would the result be printed readably? How would the result be printed
|
||
|
aesthetically?</li>
|
||
|
<li>What do the characters <code>(list (+ 1 2) ten)</code> read as? What does it evaluate
|
||
|
to? How does each step of the evaluation work? Trace out each of the calls
|
||
|
to <code>eval</code> on paper, with their arguments and their results. What does the
|
||
|
final result print as?</li>
|
||
|
<li>Use <code>symbol-function</code> to see what's in the function slot of the symbol <code>car</code>.
|
||
|
How does your Lisp print that thing?</li>
|
||
|
<li>Try to look up the function slot of a symbol without a function. What
|
||
|
happens?</li>
|
||
|
<li>Use <code>symbol-function</code> to see what's in the function slot of the symbol <code>if</code>.
|
||
|
What happens? Does that seem right? If so, why?</li>
|
||
|
<li>Go to the <a href="http://www.lispworks.com/documentation/lw70/CLHS/Body/t_symbol.htm">HyperSpec page for <code>symbol</code></a> and search for
|
||
|
"the consequences are undefined if". Try all of those things and find out
|
||
|
what interesting things break in your Lisp.</li>
|
||
|
</ol>
|
||
|
|
||
|
<p>If you're not using Common Lisp, port these exercises to your language.</p>
|
||
|
|
||
|
<h2 id="s20-quote"><a href="index.html#s20-quote">Quote</a></h2>
|
||
|
|
||
|
<p>Up to now we've been using the clumsy <code>(read-from-string "foo")</code> form to get
|
||
|
ahold of symbols, but there's an easier way called "quoting".</p>
|
||
|
|
||
|
<p>Quoting often confuses new Lisp programmers, and they'll end up randomly
|
||
|
adding/removing quotes to something until it appears to do what they want. Now
|
||
|
that you've got <code>read</code>, <code>eval</code>, and <code>print</code> firmly separated in your mind,
|
||
|
<code>quote</code> will be much easier to understand.</p>
|
||
|
|
||
|
<h3 id="s21-the-special-operator"><a href="index.html#s21-the-special-operator">The Special Operator</a></h3>
|
||
|
|
||
|
<p>Quoting actually has two distinct components: one that affects <code>read</code> and one
|
||
|
that affects <code>eval</code>. In most books the distinction between these two only gets
|
||
|
barely a sentence or two, which is probably why beginners are so confused.
|
||
|
Let's look at the <code>eval</code> side of things first.</p>
|
||
|
|
||
|
<p><code>quote</code> is one of the twenty-five special operators. All it does it pass its
|
||
|
(single) argument back from <code>eval</code> <em>untouched</em>. Normally the argument itself
|
||
|
would have been evaluated, but <code>quote</code> prevents that:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">symbolp thing</span>)</span> <span class="paren4">(<span class="code">symbol-value thing</span>)</span></span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">listp thing</span>)</span>
|
||
|
<span class="paren4">(<span class="code">destructuring-bind <span class="paren5">(<span class="code">head . arguments</span>)</span> thing
|
||
|
<span class="paren5">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren6">(<span class="code"><span class="paren1">(<span class="code">eq head <span class="paren2">(<span class="code">read-from-string <span class="string">"if"</span></span>)</span></span>)</span>
|
||
|
<span class="paren1">(<span class="code">destructuring-bind <span class="paren2">(<span class="code">test then else</span>)</span> arguments
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">if</span></i> <span class="paren3">(<span class="code">eval test</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval then</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval else</span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="paren6">(<span class="code"><span class="paren1">(<span class="code">eq head <span class="paren2">(<span class="code">read-from-string <span class="string">"quote"</span></span>)</span></span>)</span> <span class="comment">; NEW
|
||
|
</span> <span class="paren1">(<span class="code">first arguments</span>)</span></span>)</span>
|
||
|
<span class="paren6">(<span class="code">t
|
||
|
<span class="paren1">(<span class="code">apply <span class="paren2">(<span class="code">symbol-function head</span>)</span>
|
||
|
<span class="paren2">(<span class="code">mapcar #'eval arguments</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>I know that seems strange, but let's look at it in action:</p>
|
||
|
|
||
|
<pre><code>CL-USER> (+ 1 2)
|
||
|
|
||
|
3
|
||
|
|
||
|
CL-USER> (quote (+ 1 2))
|
||
|
|
||
|
(+ 1 2)</code></pre>
|
||
|
|
||
|
<p>Our first example is the same one we used in the previous section:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>read</code> takes in seven characters and returns a list of three items: the symbol
|
||
|
<code>+</code> and two numbers.</li>
|
||
|
<li><code>eval</code> gets the three-element list, looks up the function for the symbol <code>+</code>,
|
||
|
recursively evaluates the arguments (which evaluate to themselves), and
|
||
|
applies the function.</li>
|
||
|
<li><code>print</code> gets the integer <code>3</code>, turns it into ASCII, and writes it to the
|
||
|
terminal.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>The second example uses <code>quote</code>:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>read</code> takes in fifteen characters and returns a list of two items: the symbol
|
||
|
<code>quote</code> and a list of three items (the symbol <code>+</code> and two numbers).</li>
|
||
|
<li><code>eval</code> gets the two element list and notices that the first element is the
|
||
|
special operator <code>quote</code>. It simply returns the second element in the list
|
||
|
untouched, which in this case is a list of three items.</li>
|
||
|
<li><code>print</code> gets that three element list, turns it into seven characters, and
|
||
|
writes it to the terminal.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Just for fun, let's ride the serpent and use <code>quote</code> in the definition of
|
||
|
itself inside <code>eval</code> to clean things up a bit:</p>
|
||
|
|
||
|
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defun</span></i> eval <span class="paren2">(<span class="code">thing</span>)</span>
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">numberp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">stringp thing</span>)</span> thing</span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">symbolp thing</span>)</span> <span class="paren4">(<span class="code">symbol-value thing</span>)</span></span>)</span>
|
||
|
<span class="paren3">(<span class="code"><span class="paren4">(<span class="code">listp thing</span>)</span>
|
||
|
<span class="paren4">(<span class="code">destructuring-bind <span class="paren5">(<span class="code">head . arguments</span>)</span> thing
|
||
|
<span class="paren5">(<span class="code"><i><span class="symbol">cond</span></i>
|
||
|
<span class="paren6">(<span class="code"><span class="paren1">(<span class="code">eq head <span class="paren2">(<span class="code"><i><span class="symbol">quote</span></i> <i><span class="symbol">if</span></i></span>)</span></span>)</span>
|
||
|
<span class="paren1">(<span class="code">destructuring-bind <span class="paren2">(<span class="code">test then else</span>)</span> arguments
|
||
|
<span class="paren2">(<span class="code"><i><span class="symbol">if</span></i> <span class="paren3">(<span class="code">eval test</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval then</span>)</span>
|
||
|
<span class="paren3">(<span class="code">eval else</span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="paren6">(<span class="code"><span class="paren1">(<span class="code">eq head <span class="paren2">(<span class="code"><i><span class="symbol">quote</span></i> <i><span class="symbol">quote</span></i></span>)</span></span>)</span> <span class="comment">; WHAT IN THE
|
||
|
</span> <span class="paren1">(<span class="code">first arguments</span>)</span></span>)</span>
|
||
|
<span class="paren6">(<span class="code">t
|
||
|
<span class="paren1">(<span class="code">apply <span class="paren2">(<span class="code">symbol-function head</span>)</span>
|
||
|
<span class="paren2">(<span class="code">mapcar #'eval arguments</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
||
|
<span class="comment">; ...
|
||
|
</span> <span class="paren3">(<span class="code">t <span class="paren4">(<span class="code">error <span class="string">"What the hell is this?"</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
|
||
|
|
||
|
<p>That <code>(quote quote)</code> looks just completely bonkers, right? Step through it
|
||
|
piece by piece to figure it out:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>What do the five characters <code>quote</code> read as? What do they evaluate to?</li>
|
||
|
<li>What do the thirteen (spooky!) characters <code>(quote quote)</code> read as? When
|
||
|
<code>eval</code> gets its hands on that, what clause in the <code>cond</code> does it hit? What
|
||
|
does that return?</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Try these in a Lisp REPL if you're not 100% sure of the answers. The functions
|
||
|
<code>read-from-string</code>, <code>eval</code>, and <code>type-of</code> will come in handy.</p>
|
||
|
|
||
|
<h3 id="s22-the-read-macro"><a href="index.html#s22-the-read-macro">The Read Macro</a></h3>
|
||
|
|
||
|
<p>Now let's look at the final piece of the puzzle. <code>'</code> (that's a single ASCII
|
||
|
quote character) is a <a href="https://gist.github.com/chaitanyagupta/9324402">read macro</a>. Don't worry if you don't know exactly
|
||
|
what that means right now. The important part is that when <code>read</code> sees a quote
|
||
|
character, it returns a two-element list containing the symbol <code>quote</code> and the
|
||
|
next form, which is read normally.</p>
|
||
|
|
||
|
<p>The four characters <code>'foo</code> go into <code>read</code> and come out as a two-element list
|
||
|
containing: the symbol <code>quote</code> and the symbol <code>foo</code>. Again, because it's
|
||
|
important: this happens <em>at read time</em>. By the time <code>eval</code> sees anything it's
|
||
|
already been turned into that two-element list.</p>
|
||
|
|
||
|
<p>It can be a bit slippery to get a grip on this, because <code>print</code> will "helpfully"
|
||
|
print a list of <code>(quote whatever)</code> as <code>'whatever</code>! But we can use trusty old
|
||
|
<code>car</code> and <code>cdr</code> to see what's really going on:</p>
|
||
|
|
||
|
<pre><code><span class="code">CL-USER> <span class="paren1">(<span class="code">read-from-string <span class="string">"'foo"</span></span>)</span>
|
||
|
|
||
|
'FOO
|
||
|
|
||
|
CL-USER> <span class="paren1">(<span class="code">type-of <span class="paren2">(<span class="code">read-from-string <span class="string">"'foo"</span></span>)</span></span>)</span>
|
||
|
|
||
|
CONS
|
||
|
|
||
|
CL-USER> <span class="paren1">(<span class="code">car <span class="paren2">(<span class="code">read-from-string <span class="string">"'foo"</span></span>)</span></span>)</span>
|
||
|
|
||
|
QUOTE
|
||
|
|
||
|
CL-USER> <span class="paren1">(<span class="code">cdr <span class="paren2">(<span class="code">read-from-string <span class="string">"'foo"</span></span>)</span></span>)</span>
|
||
|
|
||
|
<span class="paren1">(<span class="code">FOO</span>)</span></span></code></pre>
|
||
|
|
||
|
<p>That's really all there is to it: <code>'form</code> is returned by <code>read</code> as <code>(quote
|
||
|
form)</code>. Then that gets passed along to <code>eval</code>, which sees the <code>quote</code> special
|
||
|
operator and passes the argument back untouched.</p>
|
||
|
|
||
|
<p>Note that <code>form</code> doesn't have to be a symbol:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>'(1 2 (4 5))</code> reads as <code>(quote (1 2 (4 5)))</code></li>
|
||
|
<li><code>'150</code> reads as <code>(quote 150)</code></li>
|
||
|
<li><code>'"hello"</code> reads as <code>(quote "hello")</code></li>
|
||
|
<li><code>'(if if if if)</code> reads as <code>(quote (if if if if))</code></li>
|
||
|
</ul>
|
||
|
|
||
|
<h3 id="s23-exercises"><a href="index.html#s23-exercises">Exercises</a></h3>
|
||
|
|
||
|
<p>That pretty much wraps up <code>quote</code>. Once you've cleanly separated <code>read</code>,
|
||
|
<code>eval</code>, and <code>print</code> in your mind it becomes a lot less mystical (or perhaps
|
||
|
<em>more</em>, depending on your point of view).</p>
|
||
|
|
||
|
<p>If you want to twist your brain just a bit more, try these exercises:</p>
|
||
|
|
||
|
<ol>
|
||
|
<li>What do the characters <code>foo</code> read in as? What do they evaluate to? How does it print?</li>
|
||
|
<li>What do the characters <code>'foo</code> read in as? What do they evaluate to? How does it print?</li>
|
||
|
<li>What do the characters <code>''foo</code> read in as? What do they evaluate to? How does it print?</li>
|
||
|
<li>What do the characters <code>'1.0</code> read in as? What do they evaluate to? How does it print?</li>
|
||
|
<li>What do the characters <code>'(1 2 3)</code> read in as? How many elements are in the list? What does it evaluate to? How many elements are in <em>that</em> list?</li>
|
||
|
<li>Update our implementation of <code>eval</code> to use the <code>'</code> read macro instead of <code>quote</code>.</li>
|
||
|
<li>Certain symbols like <code>t</code> and <code>nil</code> are special — they evaluate to themselves like numbers or strings. Add this to <code>eval</code>.</li>
|
||
|
<li>What do the characters <code>nil</code> read in as? What is the type of that object? What do they evaluate to? What type is that result?</li>
|
||
|
<li>What do the characters <code>'nil</code> read in as? What is the type of that object? What do they evaluate to? What type is that result?</li>
|
||
|
<li>What do the characters <code>''nil</code> read in as? What is the type of that object? What do they evaluate to? What type is that result?</li>
|
||
|
</ol>
|
||
|
|
||
|
<h2 id="s24-a-quick-recap"><a href="index.html#s24-a-quick-recap">A Quick Recap</a></h2>
|
||
|
|
||
|
<p>If you've gotten this far and understood everything, you should have a good
|
||
|
grasp of how symbolic computation works. Here are the main things I hope you've
|
||
|
taken away from this post:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><code>read</code>, <code>eval</code>, and <code>print</code> are three separate, distinct functions/phases in
|
||
|
the interpretation of Lisp (and really <em>all</em> (okay, <em>most</em>)) code.</li>
|
||
|
<li>Keeping these three phases <em>clearly separated</em> in your mind will make it
|
||
|
easier to understand symbols and quoting in Lisp.</li>
|
||
|
<li>Symbols are nothing magic, they're just a particular data structure with
|
||
|
a couple of fields.</li>
|
||
|
<li>The important thing is how <code>read</code> and <code>eval</code> <em>treat</em> symbols. That's where
|
||
|
the magic happens.</li>
|
||
|
<li><code>quote</code> is just a "short-circuit" in <code>eval</code> that turns out to be really
|
||
|
useful.</li>
|
||
|
<li><code>'</code> is just a lazier way of writing <code>(quote ...)</code>.</li>
|
||
|
</ul>
|
||
|
|
||
|
<h2 id="s25-where-to-go-from-here"><a href="index.html#s25-where-to-go-from-here">Where to Go From Here</a></h2>
|
||
|
|
||
|
<p>Now that you've got a firmer grasp on what the hell symbols actually <em>are</em>,
|
||
|
there are a lot of cool things you might want to check out that will show you
|
||
|
what you can do with them:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Reread some of your introductory Lisp books again, seeing if things seem to
|
||
|
make a bit more sense now.</li>
|
||
|
<li>Read about backquote/quasiquote. How does it compare to the <code>quote</code> we
|
||
|
explored here?</li>
|
||
|
<li>Read <a href="http://www.amazon.com/dp/1558601910/?tag=stelos-20">Paradigms of Artificial Intelligence Programming</a> and pay
|
||
|
attention to how Norvig uses symbols for various tasks. Also pay attention to
|
||
|
what he says about property lists, because we skipped them here.</li>
|
||
|
<li>Read the <a href="https://www-fourier.ujf-grenoble.fr/~sergerar/Papers/Packaging.pdf">guide to the Common Lisp package system</a> to learn all the
|
||
|
stuff I left out about the Common Lisp package system.</li>
|
||
|
<li>Gaze upon <a href="https://github.com/zkat/squirl/blob/f0dc57dfee728df94b2a35956e18e143e8b8d275/src/vec.lisp#L28-L38">this macro</a> in wonder (or horror).</li>
|
||
|
<li>Read the HyperSpec pages for things like <code>symbol</code> and <code>quote</code>.</li>
|
||
|
<li>Find and read your Lisp implementation's <code>eval</code> function.</li>
|
||
|
<li>Find and read <em>another</em> Lisp implementation's <code>eval</code> function.</li>
|
||
|
<li>Watch the <a href="http://www.amazon.com/dp/0262510871/?tag=stelos-20">SICP Lectures</a> on YouTube.</li>
|
||
|
</ul>
|
||
|
</article></main><hr class='main-separator' /><footer><nav><a href='https://github.com/sjl/'>GitHub</a> ・ <a href='https://twitter.com/stevelosh/'>Twitter</a> ・ <a href='https://instagram.com/thirtytwobirds/'>Instagram</a> ・ <a href='https://hg.stevelosh.com/.plan/'>.plan</a></nav></footer></body></html>
|