Guile/Scheme
Last edited December 9, 2008
More by Ian Lewis »
Teach Yourself Scheme in Fixnum Days
www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z...

2.2.4  Conversions between data types

Scheme offers many procedures for converting among the data types. We already know how to convert between the character cases using char-downcase and char-upcase. Characters can be converted into integers using char->integer, and integers can be converted into characters using integer->char. (The integer corresponding to a character is usually its ascii code.)

(char->integer #\d) =>  100
(integer->char 50)  =>  #\2

Strings can be converted into the corresponding list of characters.

(string->list "hello") =>  (#\h #\e #\l #\l #\o)

Other conversion procedures in the same vein are list->string, vector->list, and list->vector.

Numbers can be converted to strings:

(number->string 16) =>  "16"

Strings can be converted to numbers. If the string corresponds to no number, #f is returned.

(string->number "16")
=>  16

(string->number "Am I a hot number?")
=>  #f

string->number takes an optional second argument, the radix.

(string->number "16" 8) =>  14

because 16 in base 8 is the number fourteen.

Symbols can be converted to strings, and vice versa:

(symbol->string 'symbol)
=>  "symbol"

(string->symbol "string")
=>  string
Teach Yourself Scheme in Fixnum Days
www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z...

2.2.2  Vectors

Vectors are sequences like strings, but their elements can be anything, not just characters. Indeed, the elements can be vectors themselves, which is a good way to generate multidimensional vectors.

Here's a way to create a vector of the first five integers:

(vector 0 1 2 3 4)
=>  #(0 1 2 3 4)

Note Scheme's representation of a vector value: a # character followed by the vector's contents enclosed in parentheses.

In analogy with make-string, the procedure make-vector makes a vector of a specific length:

(define v (make-vector 5))

The procedures vector-ref and vector-set! access and modify vector elements. The predicate for checking if something is a vector is vector?

Teach Yourself Scheme in Fixnum Days
www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z...

2.2.1  Strings

Strings are sequences of characters (not to be confused with symbols, which are simple data that have a sequence of characters as their name). You can specify strings by enclosing the constituent characters in double-quotes. Strings evaluate to themselves.

"Hello, World!"
=>  "Hello, World!"

The procedure string takes a bunch of characters and returns the string made from them:

(string #\h #\e #\l #\l #\o)
=>  "hello"

Let us now define a global variable greeting.

(define greeting "Hello; Hello!")

Note that a semicolon inside a string datum does not trigger a comment.

The characters in a given string can be individually accessed and modified. The procedure string-ref takes a string and a (0-based) index, and returns the character at that index:

(string-ref greeting 0)
=>  #\H

New strings can be created by appending other strings:

(string-append "E "
               "Pluribus "
               "Unum")
=>  "E Pluribus Unum"

You can make a string of a specified length, and fill it with the desired characters later.

(define a-3-char-long-string (make-string 3))

The predicate for checking stringness is string?.

Strings obtained as a result of calls to string, make-string, and string-append are mutable. The procedure string-set! replaces the character at a given index:

(define hello (string #\H #\e #\l #\l #\o)) 
hello
=>  "Hello"

(string-set! hello 1 #\a)
hello
=>  "Hallo"
Teach Yourself Scheme in Fixnum Days
www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z...

2.1.3  Characters

Scheme character data are represented by prefixing the character with #\. Thus, #\c is the character c. Some non-graphic characters have more descriptive names, eg, #\newline, #\tab. The character for space can be written #\  , or more readably, #\space.

The character predicate is char?:

(char? #\c) =>  #t
(char? 1)   =>  #f
(char? #\;) =>  #t

Note that a semicolon character datum does not trigger a comment.

The character data type has its set of comparison predicates: char=?, char<?, char<=?, char>?, char>=?.

(char=? #\a #\a)  =>  #t
(char<? #\a #\b)  =>  #t
(char>=? #\a #\b) =>  #f

To make the comparisons case-insensitive, use char-ci instead of char in the procedure name:

(char-ci=? #\a #\A) =>  #t
(char-ci<? #\a #\B) =>  #t

The case conversion procedures are char-downcase and char-upcase:

(char-downcase #\A) =>  #\a
(char-upcase #\a)   =>  #\A
Local Bindings - Guile Reference Manual
www.gnu.org/software/guile/manual/html_node/Local-...

5.10.2 Local Variable Bindings

As opposed to definitions at the top level, which are visible in the whole program (or current module, when Guile modules are used), it is also possible to define variables which are only visible in a well-defined part of the program. Normally, this part of a program will be a procedure or a subexpression of a procedure.

With the constructs for local binding (let, let* and letrec), the Scheme language has a block structure like most other programming languages since the days of Algol 60. Readers familiar to languages like C or Java should already be used to this concept, but the family of let expressions has a few properties which are well worth knowing.

The first local binding construct is let. The other constructs let* and letrec are specialized versions for usage where using plain let is a bit inconvenient.

— syntax: let bindings body

bindings has the form

          ((variable1 init1) ...)

that is zero or more two-element lists of a variable and an arbitrary expression each. All variable names must be distinct.

A let expression is evaluated as follows.

  • All init expressions are evaluated.
  • New storage is allocated for the variables.
  • The values of the init expressions are stored into the variables.
  • The expressions in body are evaluated in order, and the value of the last expression is returned as the value of the let expression.
  • The storage for the variables is freed.

The init expressions are not allowed to refer to any of the variables.

— syntax: let* bindings body

Similar to let, but the variable bindings are performed sequentially, that means that all init expression are allowed to use the variables defined on their left in the binding list.

A let* expression can always be expressed with nested let expressions.

          (let* ((a 1) (b a))
             b)
          ==
          (let ((a 1))
            (let ((b a))
              b))
— syntax: letrec bindings body

Similar to let, but it is possible to refer to the variable from lambda expression created in any of the inits. That is, procedures created in the init expression can recursively refer to the defined variables.

          (letrec ((even?
                    (lambda (n)
                        (if (zero? n)
                            #t
                            (odd? (- n 1)))))
                   (odd?
                    (lambda (n)
                        (if (zero? n)
                            #f
                            (even? (- n 1))))))
            (even? 88))
          
          #t

There is also an alternative form of the let form, which is used for expressing iteration. Because of the use as a looping construct, this form (the named let) is documented in the section about iteration (see Iteration)

Creating a Procedure - Guile Reference Manual
www.gnu.org/software/guile/manual/html_node/Creati...
3.1.2.3 Creating and Using a New Procedure

Scheme has lots of standard procedures, and Guile provides all of these via predefined top level variables. All of these standard procedures are documented in the later chapters of this reference manual.

Before very long, though, you will want to create new procedures that encapsulate aspects of your own applications' functionality. To do this, you can use the famous lambda syntax.

For example, the value of the following Scheme expression

     (lambda (name address) expression ...)

is a newly created procedure that takes two arguments: name and address. The behaviour of the new procedure is determined by the sequence of expressions in the body of the procedure definition. (Typically, these expressions would use the arguments in some way, or else there wouldn't be any point in giving them to the procedure.) When invoked, the new procedure returns a value that is the value of the last expression in the procedure body.

To make things more concrete, let's suppose that the two arguments are both strings, and that the purpose of this procedure is to form a combined string that includes these arguments. Then the full lambda expression might look like this:

     (lambda (name address)
       (string-append "Name=" name ":Address=" address))

We noted in the previous subsection that the procedure part of a procedure invocation expression can be any Scheme expression whose value is a procedure. But that's exactly what a lambda expression is! So we can use a lambda expression directly in a procedure invocation, like this:

     ((lambda (name address)
        (string-append "Name=" name ":Address=" address))
      "FSF"
      "Cambridge")

This is a valid procedure invocation expression, and its result is the string "Name=FSF:Address=Cambridge".

It is more common, though, to store the procedure value in a variable —

     (define make-combined-string
       (lambda (name address)
         (string-append "Name=" name ":Address=" address)))

— and then to use the variable name in the procedure invocation:

     (make-combined-string "FSF" "Cambridge")

Which has exactly the same result.

Simple Invocation - Guile Reference Manual
www.gnu.org/software/guile/manual/html_node/Simple...
3.1.2.2 Simple Procedure Invocation

A procedure invocation in Scheme is written like this:

     (procedure [arg1 [arg2 ...]])

In this expression, procedure can be any Scheme expression whose value is a procedure. Most commonly, however, procedure is simply the name of a variable whose value is a procedure.

For example, string-append is a standard Scheme procedure whose behaviour is to concatenate together all the arguments, which are expected to be strings, that it is given. So the expression

     (string-append "/home" "/" "andrew")

is a procedure invocation whose result is the string value "/home/andrew".

Similarly, string-length is a standard Scheme procedure that returns the length of a single string argument, so

     (string-length "abc")

is a procedure invocation whose result is the numeric value 3.

Each of the parameters in a procedure invocation can itself be any Scheme expression. Since a procedure invocation is itself a type of expression, we can put these two examples together to get

     (string-length (string-append "/home" "/" "andrew"))

— a procedure invocation whose result is the numeric value 12.

(You may be wondering what happens if the two examples are combined the other way round. If we do this, we can make a procedure invocation expression that is syntactically correct:

     (string-append "/home" (string-length "abc"))

but when this expression is executed, it will cause an error, because the result of (string-length "abc") is a numeric value, and string-append is not designed to accept a numeric value as one of its arguments.)

Definition - Guile Reference Manual
www.gnu.org/software/guile/manual/html_node/Defini...
3.1.1.3 Defining and Setting Variables

To define a new variable, you use Scheme's define syntax like this:

     (define variable-name value)

This makes a new variable called variable-name and stores value in it as the variable's initial value. For example:

     ;; Make a variable `x' with initial numeric value 1.
     (define x 1)
     
     ;; Make a variable `organization' with an initial string value.
     (define organization "Free Software Foundation")

(In Scheme, a semicolon marks the beginning of a comment that continues until the end of the line. So the lines beginning ;; are comments.)

Changing the value of an already existing variable is very similar, except that define is replaced by the Scheme syntax set!, like this:

     (set! variable-name new-value)

Remember that variables do not have fixed types, so new-value may have a completely different type from whatever was previously stored in the location named by variable-name. Both of the following examples are therefore correct.

     ;; Change the value of `x' to 5.
     (set! x 5)
     
     ;; Change the value of `organization' to the FSF's street number.
     (set! organization 545)
The content on this page is provided by a Google Notebook user, and Google assumes no responsibility for this content.