0
-<p>This is a DRAFT document. It's been posted for the purposes of
0
-getting feedback <b>only</b>. Please do not post the URL or
0
-copies/excerpts of this document in a public place.</p>
0
+<?xml version="1.0" encoding="iso-8859-1"?>
0
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
0
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
0
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
0
+ <title>Getting Started with Bus Scheme</title>
0
+ <style type='text/css'>
0
+ body { font-family "Garuda", Sans; }
0
+ tt { font-family: "Nimbus Mono L", Serif; background-color: #ddd; }
0
+ pre { color: #222; font-family: "Nimbus Mono L", Serif; }
0
+<h2>Getting Started with Bus Scheme</h2>
0
+<div id="index" style="width: 60em;">
0
<p>So a number of folks have asked me how they should get started with
0
Bus Scheme.[<a href='#fn1'>1</a>]. I've mostly just said silly things
0
-like, "Umm... good question. Maybe read/watch <a
0
-href='http://mitpress.mit.edu/sicp/'>SICP</a>?", which is silly
0
+like, \"Umm... good question. Maybe read/watch <a
0
+href='http://mitpress.mit.edu/sicp/'>SICP</a>?\", which is silly
0
because it doesn't have much to do with the <i>Bus</i> part of Bus
0
Scheme, not because <i>The Structure and Interpretation of Computer
0
Programs</i> is silly.</p>
0
<p>There's a poster in <a href='http://www.powells.com/'>my favourite
0
bookstore</a> that has Dante's <i>Comedy</i>, the <i>Iliad</i>, and a
0
-few other classics captioned with something like "Might as well start
0
-them now; you're going to have to read them eventually anyway." I hold
0
+few other classics captioned with something like \"Might as well start
0
+them now; you're going to have to read them eventually anyway.\" I hold
0
the same notion regarding SICP and perhaps <i>The Little Schemer</i>,
0
but I could see how it'd be helpful to have an introduction to Scheme
0
from a Rubyist's perspective since reading a book like that can be
0
@@ -21,7 +35,7 @@ large-ish mental investment.</p>
0
<p>Scheme is a programming language directly descended from Lisp. It's
0
most often compared to Common Lisp, which is in some senses its big
0
-brother. Scheme is usually considered less
"kitchen-sink"-ish than
0
+brother. Scheme is usually considered less
\"kitchen-sink\"-ish than
0
Common Lisp in that it only defines an extremely clean small core
0
language and allows developers to extend it seamlessly to do what they
0
need. In the words of the creators of Scheme:</p>
0
@@ -38,51 +52,77 @@ notion as it directly translates into fewer concepts to learn.)</p>
0
<p>Ruby draws a lot of its heritage from Scheme, though Matz does not
0
share the idea that a language should be limited to a very small
0
number of core axioms from which everything else can be defined. [<a
0
-href='#fn2'>2</a>] Destructive method names ending in "!" and
0
-predicates ending in "?" were inspired by Scheme. Matz himself has
0
-even jokingly referred to Ruby as "MatzLisp". So this is a language
0
-that at the core should not feel too foreign to a Rubyist, even if the
0
-syntax looks quite different.</p>
0
+href='#fn2'>2</a>] Destructive method names ending in \"!\" and
0
+predicates ending in \"?\" were inspired by Scheme. Matz himself has
0
+even lightheartedly referred to Ruby as \"MatzLisp\". So this is a
0
+language that at the core should not feel too foreign to a Rubyist,
0
+even if the syntax looks quite different.</p>
0
<p>Let's dive in. <tt>sudo gem install bus-scheme</tt> if you haven't
0
-got it installed. Go ahead and launch Bus Scheme. Like <tt>irb</tt>,
0
-running the <tt>bus</tt> executable drops you into a REPL, or
0
-Read-Eval-Print Loop. Feel free to experiment with entering values and
0
-seeing what gets returned.</p>
0
-<p>Scheme programs are made up of expressions. Each expression is
0
-either an atom or a list. Atoms are simple "indivisible" values, like
0
-symbols, numeric values, and strings. Some atoms evaluate to
0
-themselves just like in Ruby, so entering <tt>12</tt> into the REPL
0
-returns (and echoes) 12. <tt>"foo"</tt> works the same way. Symbols
0
-are a little different. Ruby uses a colon before the symbol's name,
0
-but in Scheme you refer to a symbol just using its name. So
0
-<tt>baz</tt> refers to the symbol with the name "baz". But if you
0
-enter <tt>baz</tt> into the REPL, Bus Scheme complains:</p>
0
+got it installed. Go ahead and launch Bus Scheme with the <tt>bus</tt>
0
+executable. Like <tt>irb</tt>, it drops you into a REPL, or
0
+Read-Eval-Print Loop. Scheme programs are made up of
0
+<b>expressions</b>. When you enter expressions into the REPL, they get
0
+evaluated and their value is shown. There are only a few simple rules
0
+for how expressions get evaluated that we'll address below. Feel free
0
+to experiment with entering expressions and seeing what gets
0
+<p>The simplest expressions are just <b>atoms</b>, which are simple
0
+\"indivisible\" values, like symbols, numeric values, and strings. Some
0
+atoms evaluate to themselves just like in Ruby, so entering
0
+<tt>12</tt> into the REPL returns (and echoes) 12. <tt>\"foo\"</tt>
0
+works the same way. Symbols are a little different. Ruby uses a colon
0
+before the symbol's name, but in Scheme you refer to a symbol just
0
+using its name. So <tt>baz</tt> refers to the symbol with the name
0
+\"baz\". But if you enter <tt>baz</tt> into the REPL, Bus Scheme
0
<pre class='code'>> baz
0
Error: Undefined symbol: baz</pre>
0
-<p>This is because symbols aren't treated as literals; they don't
0
-evaluate to themselves. When Bus Scheme encounters a symbol in this
0
-context, it treats it as a variable and returns the value that's bound
0
-to it. So let's bind that sucker.</p>
0
-<pre class='code'>> (define baz 12)
0
-<p>Now when Bus Scheme encounters the <tt>baz</tt> symbol it returns
0
-12, since that's the value the "baz" identifier is bound to in this
0
-context. But what's this we've just entered? That's actually a list
0
-made up of the symbol <tt>define</tt>, the symbol <tt>baz</tt>, and
0
-the literal numeric value 12. In normal contexts, a list is
0
-interpreted as a function call. TODO: explain function calls and
0
-evaluation rules more clearly. Scheme determines what function to call
0
-by evaluating the first element of the list. In this case, it's the
0
-symbol <tt>define</tt>, which evaluates to a built-in (primitive)
0
-function that binds its second argument to its first argument. Then it
0
-evaluates each of the arguments [<a href='#fn3'>3</a>] and passes
0
-those values to the function.</p>
0
+<p>This is because symbols aren't considered <b>literals</b>; that is, they
0
+don't evaluate to themselves like they do in Ruby. When Bus Scheme
0
+encounters a symbol in this context, it treats it as a variable and
0
+tries to return the value that's bound to it, which doesn't work when
0
+it's not bound. So let's see what happens with a symbol that already
0
+has a value bound to it:</p>
0
+<pre class='code'>> +
0
+#<Proc:0xb7c4b2a8@./bin/../lib/primitives.rb:16></pre>
0
+<p>This is the way Bus Scheme represents a built-in (primitive)
0
+<b>function</b>. In Scheme, functions are first-class values, so you
0
+can bind them to variables, like you can with the <tt>lambda</tt>
0
+keyword in Ruby. But in Scheme this the primary way you refer to
0
+functions when you want to call them or pass them to other
0
+<p>Speaking of calling functions, it works something like this:</p>
0
+<pre class='code'>> (+ 3 4)
0
+<p>This is a <b>list</b>, which is Scheme's compound expression. This list is
0
+made up of three elements, in this case all atoms: the symbol
0
+<tt>+</tt>, the number 3, and the number 4. In normal contexts, when
0
+Scheme sees a list it treats it as a function call. First the first
0
+item in the list is evaluated, which evaluates to a Ruby Proc
0
+object. Then each of the remaining list elements are evaluated. Since
0
+they're all literals here, they evaluate to themselves. Then the
0
+arguments get passed to the function. Behind the scenes, this
0
+translates rougly into <tt>Proc.new{|*args| args.sum}.call(3,
0
+4)</tt>. Let's see something a bit more complicated:</p>
0
+<pre class='code'>> (+ (+ 1 2) (+ 3 4))
0
+<p>In this case, the first <tt>+</tt> gets evaluated, and Bus Scheme sees
0
+that it's a function. So it looks at its arguments: <tt>(+ 1 2)</tt>
0
+gets evaluated to 3, and <tt>(+ 3 4)</tt> gets evaluated to 7. Then
0
+those two arguments get passed to <tt>+</tt> and the result becomes
0
+the value of the whole expression.
0
<p>That's the basics of how program execution happens, but you won't
0
get far without having a few more functions under your belt. Here are
0
@@ -90,49 +130,49 @@ a some to get you rolling:</p>
0
<dt>+, -, *, and /</dt>
0
- <dd>I'm sure you recognize your old friends from grade-school
0
- days. + and * support any number of arguments, but - and / take
0
- two. In regular Scheme these all only work for numerical types, but
0
- Bus Scheme borrows Ruby's methods and lets you pass strings to + and
0
- <dd>The most basic conditional is <tt>if</tt>. Use it like this:
0
- <tt>(if x "x is true" "x is false")</tt>. <tt>if</tt> evaluates its
0
- first argument, which in this case is x. If it returns a true value
0
- (in Scheme every value is true except <tt>#f</tt>, which is
0
- equivalent to Ruby's <tt>false</tt>) then its second argument gets
0
- evaluated and returned. If it's false then the remaining arguments
0
- (if any) are evaluated and the last one is returned.</dd>
0
+ <dd>You've been introduced to + above, but I'm sure you recognize
0
+ your other old friends from grade-school days. + and * support any
0
+ number of arguments, but - and / take two. In regular Scheme these
0
+ all only work for numerical types, but Bus Scheme borrows Ruby's
0
+ methods and lets you pass strings and other objects to + and *.</dd>
0
+ <dt><, >, and =</dt>
0
+ <dd>These are comparison functions. They work like they do in any
0
+ language, but in Scheme you invoke them as <tt>(> 3 7)</tt>
0
+ etc. Again, Bus Scheme uses Ruby's underlying methods, so you can
0
+ pass strings and other objects in, unlike in regular Scheme.</dd>
0
<dd>If you want a list of numbers, you may think you get this by
0
- entering <tt>(1 2 3)</tt>. The problem with this is that it gets
0
- treated like a function call, and it will complain that 1 is not a
0
- function. (No joke, thanks for pointing that out.) What you can do
0
- instead is <tt>(list 1 2 3)</tt>.</dd>
0
- <dd>Remember when we entered the name of a symbol above and it
0
- returned the value that was bound to the symbol? If you really just
0
- want the symbol itself, you can pass it to quote: <tt>(quote
0
- baz)</tt> returns <tt>baz</tt>. You can also quote lists [<a
0
- href='#fn4'>4</a>] if you want their literal value returned instead
0
- of having them evaluated: <tt>(quote (define baz 12))</tt> returns
0
- <tt>(define baz 12)</tt>. Quote allows you to get around the way
0
- Scheme evaluates things to get at literal values.</dd>
0
+ entering <tt>(1 2 3)</tt>. The problem with this is that in normal
0
+ contexts it gets treated like a function call, and it will complain
0
+ that 1 is not a function. What you can do instead is <tt>(list 1 2
0
+ 3)</tt>, which evaluates to (1 2 3).</dd>
0
- <dd>This works like Ruby's map, but it's a free
standing function
0
+ <dd>This works like Ruby's map, but it's a free
-standing function
0
instead of a method. So instead of <tt>[1, 2, 3].map {|x| x +
0
3}</tt> you would do <tt>(map (lambda (x) (+ x 3)) (list 1 2
0
3)</tt>, which would return <tt>(4 5 6)</tt>.</dd>
0
+ <dd>Bus Scheme's <tt>(substring \"foobar\" 3 5)</tt> translates into
0
+ <tt>\"foobar\"[3 .. 5]</tt> in Ruby.</dd>
0
+ <dd>The most basic conditional is <tt>if</tt>. Use it like this:
0
+ <tt>(if x \"x is true\" \"x is false\")</tt>. <tt>if</tt> evaluates its
0
+ first argument, which in this case is x. If it evaluates to a true
0
+ value [<a href='#fn3'>3</a>] then its second argument gets evaluated
0
+ and returned. If it's false then the remaining arguments (if any)
0
+ are evaluated and the last one is returned.[<a
0
+ href='#fn4'>4</a>]</dd>
0
<p>Well, that's enough for now. You may not know enough to be
0
dangerous, but I hope you know enough to explore. Tune in next time
0
-when I uncover the true Secrets of Lisp &tm; by explaining
0
-<tt>cons</tt> and <tt>lambda</tt>.</p>
0
+when I uncover the true Secrets of Lisp™ by explaining
0
+<tt>cons</tt>, <tt>lambda</tt>, and special forms.</p>
0
@@ -143,22 +183,22 @@ href='http://blog.fallingsnow.net'>Evan</a> and <a
0
href='http://headius.blogspot.com/'>Charles</a> some varying amounts
0
-<p><a name='fn3'>3</a> - This isn't strictly true here;
0
-<tt>define</tt> is a special form, which means that not all its
0
-arguments get evaluated before they get passed to the function. This
0
-is why it works to pass <tt>define</tt> the symbol
0
-<tt>baz</tt>—it doesn't try to look up the value that
0
-<tt>baz</tt> is bound to. TODO: uh... too pedantic for a first
0
-<p><a name='fn4'>4</a> - So what's the difference between
0
-<tt>list</tt> and <tt>quote</tt> then? Well, quote doesn't evaluate
0
+<p><a name='fn3'>3</a> - In Scheme every value is true except
0
+<tt>#f</tt>, which is equivalent to Ruby's <tt>false</tt>.</p>
0
-<p><tt>(list 1 2 (+ 1 2))</tt> → <tt>(1 2 3)</tt></p>
0
+<p><a name='fn4'>4</a> - Observant readers will note that this does
0
+not follow the evaluation rule for functions given above which states
0
+that every argument is evaluated before the function is called. This
0
+is because <tt>if</tt> is not technically a function, but rather a
0
+<b>special form</b>, and different rules apply for the evaluation of a
0
+special form's arguments. There's more to this than I can cover in
0
+this article, but these rules allow for great syntactic
0
-<
p><tt>(quote (1 2 (+ 1 2)))</tt> → <tt>(1 2 (+ 1 2))</tt></p>
0
<p>© 2008 <a href='http://technomancy.us'>Phil
0
-Hagelberg</a>. Please send feedback to technomancy at google's mail
0
\ No newline at end of file
0
\ No newline at end of file
Comments
No one has commented yet.