Having fun with Guile: a tutorial
|
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.
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!
So let's get started.
Open a terminal and run guile
.
You should see something like this:
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.
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!
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:
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.
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!
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!
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!
Those are some interesting kinds of toys to play with. Now it's time to learn how to breathe some life into them.
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!