Scheme language introduction

...more code basics, including loop and format for easy iteration and fancy printing, eval and quote

Starting guile again fresh, you will need to load CM as shown. Note how cm.scm adds the definition of loop.

guile> (defined? 'loop)
#f
guile> (load "/user/c/cc/220a/system/snd-cm/cm-2.6.0/src/cm.scm")
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/guile.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/goops.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/level1.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/loop.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/utils.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/mop.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/objects.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/io.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/scheduler.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/sco.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/clm.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/clm2.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/midi1.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/midi2.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/midi3.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/data.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/scales.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/spectral.scm
; Loading: /home/cc/220a/system/snd-cm/cm-2.6.0/src/patterns.scm
guile> (defined? 'loop)
#t
guile>


loop is a macro that makes plain language iteration convenient. It's been around a long time as an addition to the lisp language and was reimplemented for CM. Many features that we'll use in CM are macros, which are used to interact with procedures dressing up the way that the procedure is called. In this case, there's a hidden CM procdure called scheme-loop that is handed plain language syntax like”for, in, from, below, do” when called from the loop macro. In our work we'll mostly be concerned with defining our own new procedures as seen earlier and using pre-defined macros loaded by CM. In the example, list l contains 8 elements and the loop expression walks down the list displaying each element in turn, finally the loop macro itself evaluates to #f. Where do these new procedures come from? list and is part of scheme, loop is defined in CM's loop.scm, and display is part of scheme.

guile> ; define a list for testing
guile> (define l (list 'a 'b 'c 'd 1 2 3 4))
guile> l
(a b c d 1 2 3 4)
guile> ; loop through the list printing its elements
guile> (loop for x in l do (display x))
abcd1234#f

loop syntax is described in loop.html, a useful document to have handy, which ends with this example. Study the document and try to decypher:

guile> (loop repeat 10
      collect (random 10) into res
      finally (return (remove 3 res)))
(9 2 6 7 0 5 5 8 9)

format is another venerable feature from lisp and reimplemented in scheme. Over time it has evolved to be quite powerful and I just demonstrate the basics which we'll use in course examles. A format expression forms up a string of characters and controls where the string goes. The first call, with it's first argument set to #f simply returns the string as the value of the expression. That's why you see the quotes that indicate a string data type. The second prints it to the interaction terminal, stripping off the quotes. In this case, I've added an explicit newline character \n, to make it look right.

guile> ; printing with format
guile> (format #f "this is a string of characters")
"this is a string of characters"
guile> (format #t "this is a string of characters\n")
this is a string of characters
guile>

format evaluates arguments according to variable codes embedded in the format string. Here's the ~a code formatting the contents of the list from earlier. You will get an error unless you provide for each ~a a trailing argument that tells what gets inserted at that location in the string sequence.

guile> (format #f "the list from earlier still contains ~a" l)
"the list from earlier still contains (a b c d 1 2 3 4)"
guile> (format #f "first ~a, second ~a, third ~a" 1 2.0 'three)
"first 1, second 2.0, third three"
guile>

You should be scratching your head about why I had to single-quote the token three above. Just like guile evals the expressions typed to it, so do procedures when parsing their arguments. The following error would have happened had we asked format to eval three without quoting, since three is as of yet, undefined.

guile> ; evaluation of unquoted undefined variable is error
guile> three
<unnamed port>: In expression three:
<unnamed port>: Unbound variable: three
ABORT: (unbound-variable)
guile> ; but quoted undefined variable is ok, just returns the name
guile> 'three
three

Both quote and eval are procdures in scheme. Here's a brain-teaser that nests layers of quoting and then unravels with primitive-eval. The hint here is that we're doing quote twice. Then we're doing eval twice, once with primitive-eval and once with the interpreter's read-eval-print loop.

guile> ; up and down the levels of quoting 
guile> (define x (quote (quote three)))
guile> x
(quote three)
guile> (primitive-eval x)
three

Back to looping, this time printing the list elements in a fancier format...

guile> (loop for x in l for c from 0 do (format #t "element ~a = ~a\n" c x))
element 0 = a
element 1 = b
element 2 = c
element 3 = d
element 4 = 1
element 5 = 2
element 6 = 3
element 7 = 4
#f 

There is a plethora of documentation on versions of format, see the one for guile in our case. Generally, there are two reference sources to use: the guile reference manual and Sitaram's index. Between them you will find descriptions for everything we'll be using from the scheme language (which won't be all that much, actually).