Having fun with Guile: a tutorial

1 Introductions

Hello! Welcome to Guile, and this little Guile tutorial! If you've been interested in learning Guile, but don't know how to dive in, this is the tutorial for you. We don't assume any prior programming experience in this tutorial, but if you do have prior experience, you'll find that will make things much easier.

Guile is a couple of things: it's a language in the family of Scheme and Lisp, and it's also a language virtual machine on which many languages can run. The goal of this tutorial is to introduce you to the Scheme style language that Guile provides (or in other words, "Guile Scheme").

There are many languages to choose from these days, but we hope you'll find that Guile has some special things to offer. Guile is "multi-paradigm", this means that if you can choose between imperative object-oriented style or pure functional programming style, or a variety of other techniques. (And if you don't know what that means, playing with Guile is a great way to learn!) Guile comes with many useful features built-in, and has a variety of libraries you can use to build anything from games to interactive websites. And if you've ever wanted to learn how programming languages work or ever wanted to tune them to your purposes, Guile is a great fit; you can easily peek inside to see what's going on and even easily add new language features. We think that's pretty neat!

At its best, Guile is a playground full of wonderful things to explore. As such, many of the metaphors we use in this tutorial are based around playing with toys. We hope you learn a lot, and most importantly, have fun doing so.


2 Getting up and running

2.1 Installing Guile and friends

To use this tutorial, you'll need to install Guile onto your computer. If you don't have Guile yet, go install it then come back.

You'll also need a text editor of some sort. You will want to use something that edits plain text, which means you don't want to use a word processor (so, no Libreoffice!), you want an editor to edit programs. If you already have an editor you like to use, great use that! Most Guile developers find that the best editor to use is Emacs combined with Geiser, but if you aren't already an Emacs user, it can be overwhelming to learn multiple things at once. (If do learn to use Emacs with Geiser, there are even more fun things you can do than what we show here. See the Geiser manual for more information!) If you've never programmed before, you might want to start with something simple, like gedit for Gnome. You can always set up a more advanced setup later!


2.2 Running Guile

So let's get started. Open a terminal and run guile. You should see something like this:

GNU Guile 2.0.11
Copyright (C) 1995-2014 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> 

Great! That means Guile is working just fine. Now let's try entering a small command. Type (display "Hello world!\n) and hit enter, like this:

scheme@(guile-user)> (display "Hello world!\n")
Hello world!
scheme@(guile-user)> 

Excellent! You just wrote your first piece of Guile code!

Now you might be wondering, how do I get out of this thing? You can type (quit) to quit. (Or, if you want to be a bit more fancy and hit two buttons at once, you can press Ctrl-d instead.)

This fancy "enter code and experiment with it" thing is called Guile's "REPL" (Read Eval Print Loop) and is a great way to experiment with code.


2.3 Making your life easier: readline and editor friends

Two more things. These aren't required to continue with this tutorial, but they will make it much more pleasant. The first is that you may want to add readline support to your REPL. This will make playing around much nicer, because you can now keep a "history" of commands around.

You also might build up some fun toys while running through this tutorial. You might want to play with them and re-use them without having to type them in all over again. This is where your text editor comes into play! Try opening a new file, we'll call it "sandbox.scm". When you build something in this tutorial you'd like to use over and over again without retyping it between REPL sessions, you can put it here. Let's try putting something there now:

(define my-friends 'your-friends)

Now start up guile again, in the same directory as your "sandbox.scm" file. We can use a nifty tool called load to pull toys from our sandbox file into our REPL. Let's try it!

scheme@(guile-user)> (load "sandbox.scm")
sheme@(guile-user)> my-friends
$1 = your-friends

It looks like it worked! We also see that my friends are your friends. We're all friends here!

Note the $1 = your-friends line. When at the REPL, you can refer to the value you got back by making use of this number again:

scheme@(guile-user)> $1
$2 = your-friends

However, for the rest of the tutorial, we'll be dropping the dollar-sign-number pattern and showing things like this, just so we don't have to keep track of numbers:

scheme@(guile-user)> (+ 1 2)
;; => 3

... which of course means you got 3 back as a result.

Okay, that's enough setting things up. We have our sandbox, we're in our REPL playground. Lets break out the toys and have some fun!



3 Simple toys

3.1 Opening the toy box

Let's build ourself a little toy box for us to play around with. Enter the following at your Guile REPL:

(define toy-box '(robot teddy-bear doll-with-comb toy-soldier))

If we forget what's inside our toy box, we can always look inside it.

scheme@(guile-user)> toy-box
;; => (robot teddy-bear doll-with-comb toy-soldier)

Our friend toy-box here is a variable, and the information it references is called a "list", and lists are at the heart of Scheme (and indeed Lisp, which stands for "list processing", which Scheme is a variant of). We can verify that it is indeed a list:

scheme@(guile-user)> (list? toy-box)
;; => #t

And indeed it is!

Of course, the fun of the toy box is not the box itself, but the toys. So, let's pull out the first toy from the box:

scheme@(guile-user)> (car toy-box)
;; => robot

That looks like the toy closest to the top of our box indeed. But why is that command called car? We weren't trying to pull a toy car from the box! "car" is a term with some history in lisps (it stands for "Content Address Register") but that history is not important to us at the very moment. For now, every time you see car, you can think of it as meaning "first".

Of course, there are more toys in the box than just that robot. What's under the robot in the box?

scheme@(guile-user)> (cdr toy-box)
;; => (teddy-bear doll-with-comb toy-soldier)

Another strange command... cdr! cdr is prounounced "could-er" (and also is a historical name, standing for "Content Decrement Register", which is again not important at the moment). For now, every time you see cdr, you can think of it as meaning "rest", giving you the rest of the list.

We can see that at the top of the list returned with "cdr" is a nice looking teddy-bear. Can we pull that off the top? Indeed, we can by nesting the commands!

scheme@(guile-user)> (car (cdr toy-box))
;; => teddy-bear

Horray! What a nice looking teddy-bear.

One thing we can notice from the above is that we nested the call to cdr inside the call to car. We can understand how this works by doing the substitution manually:

(car (cdr toy-box))
;; Substitute in toy-box
(car (cdr '(robot teddy-bear doll-with-comb toy-soldier)))
;; Pull out the rest of the list via cdr
(car '(teddy-bear doll-with-comb toy-soldier))
;; Pull the first item off the top with car
'teddy-bear

This is how a lot of Guile/Scheme/Lisp looks: expressions nested inside other expressions. The parentheses help you understand the beginning and end of an expression. For much of the programming you will do with Guile, you can figure out what's going on by doing the substitutions in your head like above. (Not everything works via substitution, but discussing that is beyond the scope of this tutorial!)

(There are other, easier to read ways to pull out items from a list (or toys from a toybox). We will get to them later.)

What if we want to add a toy to our toybox? Luckily we have a little friend named cons, which is used to construct (or add to) lists. Let's cons a new toy to our toybox now!

scheme@(guile-user)> (cons 'bouncy-ball toy-box)
;; => (bouncy-ball robot teddy-bear doll-with-comb toy-soldier)

It's so nice to see that bouncy-ball with its toy friends! But wait, this is surprising:

scheme@(guile-user)> toy-box
;; => (robot teddy-bear doll-with-comb toy-soldier)

Huh? When we ran cons, we got back a new list of toys that included our bouncy-ball, but when we look back inside of toy-box, we see it isn't there! This is on purpose (and is actually a feature): when we used cons, we got back a new list with our old list attached at the end. It didn't change our old list to do this... changing our old list mean that we "mutated" it. (code "toy-box") is a variable, and it still points at our original toy box list.

Suppose we did want to actully change what toy-box means and have it point to something else. We could do this. Guile has a command named set! which will let you change the value of a variable we already defined. Let's try it:

scheme@(guile-user)> (set! toy-box (cons 'bouncy-ball toy-box))
scheme@(guile-user)> toy-box
;; => (robot teddy-bear doll-with-comb toy-soldier)

This seems rather convenient! And sometimes, it is. Unfortunately, assignment and mutation can sometimes cause unexpected and unpleasant surprises for us. Imagine we were running a program with many friends running around our playground at once. Our friend Jessica may hear that there's a robot in the box from her friend Aaron, and so she may go to retrieve it, but in-between that maybe we took the toy out of the box to play with, and Jessica will become very confused when she opens the box and doesn't see the robot. (Maybe she will even think that Aaron lied to her, though of course, we really didn't mean to cause that kind of mistake, we just wanted our robot!) Computer programs run into these same kinds of issues and often times have less ideas on what to do when things unexpectedly change around them than even we might, and this can lead to all sorts of problems. We won't go into details, but procedures that might cause tricky behavior like this are said to have "side effects", and in Guile (and Scheme generally) the convention is to label these with an exclaimation mark. So when you see the explaination mark at the end of set! remember that someone is shouting, "this has a side effect, be careful!"

The good news though is that Guile provides both datastructures that do and don't require visible side effects. When it comes to lists, you can mutate them, but unless you really need to, you probably don't want to or have to!

We'll come back to lists a bit more towards the end of the chapter. For now, there are some other fun types of data to play with.


3.2 Simple types of toys

So far we've worked with two types of data: lists and symbols. Of course, there are a lot of other types of data out there! But since we've seen symbols, let's start with them. (We'll get more into lists (and other ways to group information together)later.)

All the toys that were in our box were symbols. We can create a symbol very easily:

scheme@(guile-user)> 'race-car
;; => race-car

Symbols are used to stand in for ideas. Sometimes lisp programmers use them as "keys" to look up information, and lisp programs are technically themselves made mostly out of lists and symbols! You can test if two symbols are the same with eq?:

scheme@(guile-user)> (eq? 'apple 'apple)
;; => #t
scheme@(guile-user)> (eq? 'apple 'orange)
;; => #f

Hey wait, what are those #t and #f things? Good question! These are called "booleans". In Guile, #t stands for "true" and #f stands for "false". Though you should know: in Guile everything that isn't #f is considered to be true!

It would be nice if we could work with numbers. For example, we might like to be able to count how many toys are in our toy box.

scheme@(guile-user)> (length toy-box)
;; => 4

The number we got back is an integer, in other words a whole number (which can be positive or negative). It's fun to play with integers!

;; Since Guile uses lisp-style "prefix notation", we write
;; "8 + 2" like (+ 8 2)
scheme@(guile-user)> (+ 8 2)
;; => 10
;; Multiplication looks similar:
scheme@(guile-user)> (* 6 10)
;; => 60
;; We can include multiple arguments to add or multiply many things at once:
scheme@(guile-user)> (+ 1 2 3)
;; => 6
;; And of course we can combine together math expressions
scheme@(guile-user)> (* (+ 1 2 3) 10)
;; => 60

Integers aren't the only kinds of numbers... Guile also has "rational" numbers (like fractions) and floating point numbers, or "inexact" numbers. Unlike in some other languages, Guile tries to keep numbers exact until you need to convert them to an inexact form. This makes Guile very nice for all sorts of number games!

;; Floating point (inexact) numbers
scheme@(guile-user)> .4
;; => 0.4
;; We can enter rational numbers by hand
scheme@(guile-user)> 2/3
;; => 2/3
;; If we divide, we get back rational numbers
scheme@(guile-user)> (/ 2 3)
;; => 2/3
;; ... unless we choose to convert them to inexact form!
scheme@(guile-user)> (exact->inexact (/ 2 3))
;; => 0.6666666666666666

There are more number types available in Guile, but we'll let you read the manual to find out more about them.

It would be nice to be able to describe our toys to someone. What can we use? It would be awkward to use symbols to say a whole sentence. We would like to be able to say something using a data type more befitting our words. Of course, words and sentences are made of letters, and in Guile, we call those "characters". Here is a list of characters:

scheme@(guile-user)> '(#\a #\b #\c #\d #\e #\f #\g)
;; => (#\a #\b #\c #\d #\e #\f #\g)

Well, talking to our friends letter by letter sounds very painful. Luckily, we have a nice type that deals with text called "strings", which "string together" a series of characters. And they are very easy to use!

scheme@(guile-user)> "abcdefg"
;; => "abcdefg"
scheme@(guile-user)> (string->list "abcdefg")
;; => (#\a #\b #\c #\d #\e #\f #\g)
scheme@(guile-user)> "our teddy bear is very fuzzy"
;; => "our teddy bear is very fuzzy"
scheme@(guile-user)> (string-join '("hop" "skip" "jump") " and a ")
;; => "hop and a skip and a jump"

Those are some interesting kinds of toys to play with. Now it's time to learn how to breathe some life into them.



4 Building blocks


5 Putting on a play


6 Toys that make toys


7 The grand finale


8 About this tutorial

This tutorial is released under the GNU LGPL, version 3 or later, as published by the Free Software Foundation. You can get a complete copy of its source from its git repository. If you have suggestions or improvements, you are welcome to make them to the guile-user mailing list Patches welcome!


(made with skribilo)