Guile User Manual

Introduction - what is Guile?

Guile is the GNU Extension Language (I'm not really sure if GUILE is an acronym for anything). It started out as an embeddable scheme interpreter, and has rapidly evolved into a kitchen-sink package including an embeddable scheme interpreter, several graphics options, at least two other languages that can be used along with scheme (Tcl and ctax), a formalism for applets, and hooks for much more.

What are scripting and extension languages?

A scripting language is a programming language which serves as glue between other system programs. In the UNIX world, the traditional scripting language is the Bourne shell, which allows many UNIX commands to be executed in sequence, or in pipelines. Traditional UNIX commands are cleverly written to work well when put together in a script.

Other examples of UNIX scripting languages are AWK, Perl, Scsh (the Scheme Shell: a scheme interpreter enhanced to do good scripting), Python, Tcl, Java @dots{}

UNIX programmers noticed more than 25 years ago that scripting languages can do serious work, so the Bourne shell was written to have variables, operators and control structures just like a full-featured programming language.

What scripting languages have, that traditional programming languages do not, is the ability to run an external program (or a pipeline of external programs) and use the returned values and output from that program in useful ways.

An extension language is a programming language interpreter offered by an applications program, so that users can write macros or even full-fledged programs to extend the original application. Embeddable languages have a C interface (it is usually C, but it could be any other compiled language), and can be given access to the C data structures. Likewise, there are C routines to access the extension language data structures.

Extension languages abound in the software world, even though the name extension language is seldom used. Examples are

One lesson we can learn from looking at classical large software applications is that "writers of large programs" always end up throwing in some kind of parser for configurations or scripting.

Of the examples listed above, Emacs lisp, Tcl, Libscheme and Guile have an important property: they are not added as an afterthought for a specific application. They are general-purpose languages which a user can learn (even in college courses) and then use to customize the application program.

This is a new and (in my opinion) very exciting direction in large-program software engineering: program designers can link to the Guile or Tcl library from the very beginning, and tell their users "You want to customize this program? Just use Scheme (or Tcl, or whatever language), which you already know!"

History of Guile and its motivations

A few separate threads of events lead to the development of Guile.

In the fall of 1994 Richard Stallman, director of the GNU project, posted an article with the subject "Why you should not use Tcl", in which he argued that Tcl is inadequate as an extension language. This generated a flurry of flames (available in the hypermail archive The Tcl War).

The result was that Stallman then proposed his design for the GNU Extension Language, first called GEL and then renamed Guile. The discussion triggered by that article is also available in a hypermail archive.

One interesting feature of this GNU Extension Language plan was that users should have a choice of languages to use in extending their program. The basic language would be a slightly modified scheme, and translators would be written to convert other languages (like Tcl, Python, C-like languages @dots{}) into scheme.

Tom Lord started working on this project immediately, taking Aubrey Jaffer's small and portable implementation of scheme, SCM, and making it into an embeddable interpreter: callable from C and allowing new scheme procedures to be written in C.

In the spring of 1995, the guile-ii snapshot was released. This made it possible to start writing code in C and Scheme using the guile facilities.

The guile-iii snapshot was released the summer of 1995, and it had fixed enough problems so that the access to scheme data structures from C was almost complete.

Today (March 1996) a new snapshot guile-r0 is available internally to cygnus; it is not yet clear when the general public will get it, because there is still a problem coordinating the FSF release of Guile and the Cygnus extensions.

The guile-r0 release also includes a method for programming and executing applets, similar to Java applets but written in scheme and/or Tcl. There is at least one World Wide Web browser (SurfIt!) which will run these applets.

How to get and install Guile

The latest guile snapshot, guile-r0, can be obtained by anonymous ftp from

ftp://ftp.cygnus.com/pub/not-yet-known/guile-r0.tar.gz

You can unbundle and compile it with

gzcat guile-r0.tar.gz | tar xvf -
./configure --prefix=your-prefix-path
make
make install

You can read the `INSTALL' document if any of these steps fail, or if you are curious.

Once you have installed guile, you will have some binaries, C libraries, scheme libraries, Tcl/Tk libraries in your directory tree. What should you do now?

How to start up guile - a quick tour

Guile as a basic scheme interpreter

You could start by running the actual guile program. In a most basic sense, guile is a souped-up version of Aubrey Jaffer's scheme interpreter SCM.

If the binary directory into which you installed guile is in your path, you should be able to just type guile. Here is an example session:

<shell-prompt> guile
;;; loading modops...
;;; ...loaded /packages/lib/gls/bootstrapping/modops.
;;; loading libguile...
;;; ...loaded /packages/lib/gls/bootstrapping/libguile.
;;; loading slibhooks...
;;; ...loaded /packages/lib/gls/bootstrapping/slibhooks.
;;; loading require...
;;;   loading slibcat...
;;;   ...loaded /packages/lib/gls/bootstrapping/slibcat.
;;; ...loaded /packages/lib/gls/bootstrapping/require.
;;; loading mule...
;;; ...loaded /packages/lib/gls/bootstrapping/mule.
guile> (+ 20 35)
55
;Evaluation took 0 mSec (0 in scm_gc) 65 cells work, 44 bytes other
guile> (define (recursive-factorial n)
         (if (= n 0)
             1
            (* n (recursive-factorial (- n 1)))))
recursive-factorial
;Evaluation took 0 mSec (0 in scm_gc) 191 cells work, 87 bytes other
guile> (recursive-factorial 5)
120
;Evaluation took 0 mSec (0 in scm_gc) 229 cells work, 42 bytes other
guile> (recursive-factorial 500)
1220136825991110068701238785423046926253574342803192842192413588
3858453731538819976054964475022032818630136164771482035841633787
2207817720048078520515932928547790757193933060377296085908627042
9174547882424912726344305670173270769461062802310452644218878789
4657547771498634943677810376442740338273653974713864778784954384
8959553753799042324106127132698432774571554630997720278101456108
1188373709531016356324432987029563896628911658974769572087926928
8712817800702651745077684107196243903943225364226052349458501299
1857150124870696156814162535905669342381300885624924689156412677
5654481886506593847951775360894005745238940335798476363944905313
0623237490664450488246650759467358620746379251842004593696929810
2226397195259719094521782333175693458150855233282076282002340262
6907898342451712006207714640979456116127629145951237229913340169
5523638509428855920187274337951730145863575708283557801587354327
6888868012039988238470215146760544540766353598417443048012893831
3896881639487469658817504506926365338175055478128640000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000
;Evaluation took 140 mSec (30 in scm_gc) 2042 cells work, 110102 bytes other
guile> (quit)
;;; QUIT executed, repl exiting
;Evaluation took 0 mSec (0 in scm_gc) 55 cells work, 40 bytes other
<shell-prompt>

In this last example we did some simple arithmetic (+ 20 35) and got the answer 55. Then we defined the classic (and rather wasteful) factorial function, and got a glimpse of scheme's nice bignumbers by asking for the factorial of 1000. Then we quit with (quit).

Using Tk widgets

Here are some small programs that use the Tk toolkit to do graphics. More is said about this in section More on the Guile interface to Tk.

Start with a trivial program that brings up a button that destroys itself when clicked:

#!/packages/bin/guile -
; -*-scheme-*-

;; a first learning program for STk, by Mark Galassi

(require 'Gwish)
(use-library tcl)
(use-interface tcl)
(use-interface tclhack)


(define (quit-callback)
  (begin
    (display "quitting now\n")
    (destroy ".")))


;;(button '.quit :text "quit" :command 'quit-callback)
(button '.quit :text "quit" :command (tcl-lambda() (quit-callback)))
(pack .quit)
(tk-main-loop)
(quit)

Notice that in this one-button program, the quit-callback procedure could have been put on the creation line for that widget:

(button '.quit :text "quit" :command
  (tcl-lambda()
    (begin
      (display "quitting now\n")
      (destroy "."))))

Now a slightly more intricate use of widgets:

#!/packages/bin/guile -
; -*-scheme-*-

(require 'Gwish)
(use-library tcl)
(use-interface tcl)
(use-interface tclhack)

;; create the menubutton, and when the user clicks, invoke the menu .mb.m
(menubutton '.mb :text "sample menu" :menu ".mb.m")
(pack '.mb)

;; create the actual drop-down menu
(menu '.mb.m)
(.mb.m 'add 'command :label "Open")
(.mb.m 'add 'command :label "Close")
(.mb.m 'add 'separator)
(.mb.m 'add 'command :label "Exit" :command (tcl-lambda() (destroy ".")))

(tk-main-loop)
(quit)

Notice that the Exit menu option will actually work.

The next example shows how to read the mouse in Tk.

#!/packages/bin/guile -
; -*-scheme-*-

(require 'Gwish)
(use-library tcl)
(use-interface tcl)
(use-interface tclhack)

(canvas '.c)
(pack .c :fill "both" :expand "yes")

(bind .c "<B1-Motion>" (tcl-lambda ("%x %y" (number x) (number y))
                         (.c 'create 'rectangle x y x y :width 5)))

(tk-main-loop)

Applets in Guile

More advanced and interesting examples of all these uses of Guile are given in other chapters; the last example I want to show you here involves World Wide Web browsers and applets written in scheme.

You might have noticed that one of the programs created when you installed scheme is called SurfIt! (invoked by surfit, without the !). SurfIt! is a full-featured (although in early release) WWW brouser developed by Steve Ball at Australian National University. It is capable of executing applets written in Tcl, much like Sun's Hot Java broser and Netscape Navigator can execute applets written in Java.

The version of SurfIt! shipped with Guile has been extended to allow execution of Guile applets. To see a simple example, do three things:

Congratulations! You have just written your first applet, and it has been executed by a browser. [This is also the author's first applet; he is also excited.]

Notice how the applet uses Tk widgets that are shown directly on your own display.

New commands in Guile

This chapter gives an overview of the new primitives available to Scheme programmers who use Guile. We have already mentioned that Guile has become a kitchen sink language; here you can see how Guile freely takes new commands and constructs from the portable scheme library slib, the Tk widget set, the goonix posix library (useful for UNIX systems programming), various ways you can program OpenGL, the C syntax for Guile ctax, the regular expression library rx, and many more @dots{}

So Guile has many more commands available to it than what are specified in section 'Standard Procedures' in Revised(4) Report on the Algorithmic Language Scheme. On top of that, Guile will interpret almost all standard scheme programs. The only differences between the basic guile language and R4RS scheme are that:

Here is an outline of the broad classes into which these new functions fall:

Using Guile

Using Guile to write Guile programs

In this section we give a tutorial introduction to programming in scheme, with a slant toward the interesting things that can be done in Guile. Applets are so chic that they get their own section, but this section will try to touch on all other interesting and cool aspects of Guile, showing you how new types of problems can be solved with guile. Note that using guile as a library with libguile.a is described in its own chapter (see section Guile in a library - using libguile.a). Also notice that some small examples are given in section How to start up guile - a quick tour.

To get started you need to know how to program in scheme (a dialect of LISP). Fortunately scheme is a small, clean language and is not hard to learn, and is used in many undergraduate courses to introduce computer programming.

We will not try to teach you scheme here (although you might end up learning by example), since there are many good books on the subject, listed in section Where to find more Guile/Scheme resources. (1)

Hello World

Our first program is the typical scheme "hello world" program. Put the following code in a file called hello.scm

#!/whatever-path/guile -
; -*-scheme-*-
(display "hello world\n")
(quit)

The run guile on it. One way to do so is to start up guile and load this file:

<shell-prompt> guile
guile> (load "hello")

A bunch of operations in scheme

Here is some code you can type at the guile> prompt to see some of the scheme data types at work (mostly lists and vectors).

guile> (define ls (list 1 2 3 4 5 6 7))
guile> ls
guile> (vector? ls)
guile> (list? ls)
guile> (length ls)
guile> (car ls)
guile> (cdr ls)
guile> (car (cdr (cdr ls)))
guile> (caddr ls)
guile> (append ls (list 8 9 10))
guile> (reverse ls)
guile> (memq 4 ls)
guile> (memq 4 (reverse ls))
guile> (map sin ls)
guile> (map (lambda (n) (expt n n)) ls)

guile> (define v #(1 2 3 4 5 6 7))
guile> v
guile> (vector? v)
guile> (list? v)
guile> (vector-length v)
guile> (vector-ref v 2)
guile> (vector-ref (list->vector (reverse (vector->list v))) 2)
guile> (vector-set! v 4 "hi there")
guile> v

Using recursion to process lists

Here are some typical examples of using recursion to process a list.

(define (my-reverse l)
  (if (null? l)
      l
      (append (my-reverse (cdr l)) (list (car l)))))

Processing matrices

Suppose you have a matrix represented as a list of lists:

(define m
  (list
   (list 7 2 1 3 2 8 5 3 6)
   (list 4 1 1 1 3 8 9 8 1)
   (list 5 5 4 8 1 8 2 2 4)))

Then you could apply a certain function to each element of the matrix in the following manner:

;; applies the function func to the matrix m element-by-element;
;; returns a matrix with the result.
(define (process-matrix m func)
  (map (lambda (l)
         (map func l))
       m))

This could then be invoked with (process-matrix m sin) or (process-matrix m (lambda (x) (* x x))).

To print a representation of the matrix, we could define a generalized routine:

;; proc is a procedure to represent the single element,
;; row-proc is a procedure that is invoked after each row.
;; For example, proc could be (lambda (x) (begin (display x) (display " ")))
;; and row-proc could be (lambda (l) (display "\n"))
(define (represent-matrix m proc row-proc)
  (for-each (lambda (l)
              (begin
                (for-each proc l)
                (row-proc l)))
            m))

And then invoke it with

(represent-matrix m
                  (lambda (x) (begin (display x) (display " ")))
                  (lambda (l) (begin (display "\n"))))

Now we write a helper routine that uses guile closures to make objects with state that then receive messages to draw little squares. These objects can then be passed to represent-matrix so that we get a graphical representation of the matrix.

But let us take it one step at a time. I will start by showing you a simple example of object in scheme. The object I make here represents a cell, which could be a cell in a matrix. The cell responds to commands to draw itself, to return the next cell, and so forth. Later I will add graphical messages.

;; cell-object.scm: routines for creating and manipulating cell objects

;; (the-x, the-y) is the initial position of the cell.
;; the-color is a string representing a color; must be something Tk can grok.
;; square-size is the size of the square that gets drawn.
;; (sizex, sizey) is the size of the matrix.
(define (MAKE-CELL the-x the-y the-color square-size sizex sizey)
  (define (get-x) the-x)
  (define (get-y) the-y)

  (define (set-x! new-x)
    (set! the-x new-x)
    the-x)
  (define (set-y! new-y)
    (set! the-y new-y)
    the-y)
  (define (set-color! new-color)
    (set! the-color new-color)
    the-color)
  (define (next!)
    (set! the-x (+ the-x 1))
    (if (>= the-x sizex)
	(begin
	  (set! the-x 0)
	  (set! the-y (+ the-y 1))))
	(if (>= the-y sizey)
	    (begin
	      (display "CELL next!: value of y is too big; not changing it\n")
	      (set! the-y (- the-y 1))))
	(cons the-x the-y))
  (define (draw)
    (let* ((x0 (* the-x square-size))
	   (y0 (* the-y square-size))
	   (x1 (+ x0 square-size))
	   (y1 (+ y0 square-size)))
      (display "I should draw a ")
      (display the-color)
      (display " rectangle with corners at ")
      (display x0) (display y0) (display x1) (display y1)
      ))

  ;; self is the dispatch procedure
  (define (self message)
    (case message
      ((x)            get-x)
      ((y)            get-y)
      ((set-x!)       set-x!)
      ((set-y!)       set-y!)
      ((set-color!)   set-color!)
      ((next!)        next!)
      ((draw)         draw)
      (else (error "CELL: Unknown message -> " message))))
  ;; and now return the dispatch procedure
  self
  )

What is this procedure doing? It returns another procedure (self) which receives a message (x, y, set-x!, set-y!, @dots{}) and takes an action to return or modify its state. The state consists of the values of variables the-x, the-y, the-color and so forth.

Here are some examples of how to use MAKE-CELL:

(define c (MAKE-CELL 0 0 "red" 10 7 9))

((c 'x))
((c 'y))
;; change the x coordinate
((c 'set-x!) 5)
((c 'x))
;; change the color
((c 'color))
((c 'set-color!) "green")
((c 'color))
;; now use the next! message
((c 'next!))
((c 'x))
((c 'y))
;; now make things wrap around
((c 'next!))
((c 'next!))
((c 'next!))
((c 'x))
((c 'y))

You will notice that expressions like (c 'next) return procedures that create other procedures to do the job, so we have to use extra parentheses to make the job happen. This makes for somewhat awkward syntax; one way around it is to define a send procedure:

;; send makes object syntax a bit easier; instead of saying
;;     ((my-cell 'set-x!) 4)
;; you can say
;;    (send my-cell 'set-x! 4)
(define (send obj . args)
  (let ((first-eval (apply obj (list (car args)))))
    (if (null? (cdr args))
	(first-eval)
	(apply first-eval (cdr args)))))

You can see that send passes the message to the object, making sure that things are evaluated the proper number of times. You can now type:

(send c 'x)
(send c 'set-x! 5)
(send c 'color)
(send c 'set-color! "green")
(send c 'next!)
(send c 'x)
(send c 'y)

Using Guile to write Guile applets

Applet is a trendy word in the mid-1990s. It is used to denote a (usually small) program which executes within the context of a parent program.

The most common use for applets is in the World Wide Web. In setting up a web page you put an applet in a document. When a browser visits that document, the applet will be executed locally on the browser's machine.

Having a program execute on the client machine allows many more things to be done with the web, but it also opens a pandora's box of safety, security and privacy issues: if you are running a stranger's program on your workstation, couldn't that program go erase your files, or mail your files to some other person on the net?

Applet system implementors have solved this problem by creating safe execution enviromnents for the languages they support. Guile and Tcl have safe environments in which access to the operating system has to be authorized by the user.

Some examples of Guile applets

In section Applets in Guile, I showed you how to create a simple applet and an enclosing html document. Then we saw how to load that into a browser (SurfIt!) and execute the applets.

From the `learn-applet-0.scm' example, we can deduce that an applet must take the following steps (this list will expand as we write more complicated applets).

  1. If you are going to use Tk widgets (quite likely), have the following lines at the top:
    (require 'Gwish)
    
    (use-library tcl)
    (use-interface tcl)
    (use-interface tclhack)
    

  2. Have a line that says (require 'applet).

  3. Have a line that says (define-applet-terminate thunk).

  4. Write your code; make sure you include some kind of waiting loop, such as (tk-main-loop), or a read-eval-print loop. This is important because you should not monopolize the CPU.

learn-applet-1.scm

Now I will show you some other examples of Guile applets. The first one, `learn-applet-1.scm', is very much like `learn-applet-0.scm', but it creates its button in the browser window, rather than creating a new window.

;; Simple button demo; this version uses the browser window instead
;; of making a new top-level window.

(require 'Gwish)

(use-library tcl)
(use-interface tcl)
(use-interface tclhack)

(require 'applet)

(display "entering learn-applet-1\n")	; just some crap

(display "applet window name is ")
(display applet-window-name)
(display "\n")

(display "browser window name is ")
(display browser-window-name)
(display "\n")

;; Clean up before we start.  ??? For some reason, this is necessary
;; or surfit! will die when we enter (tk-main-loop).  This is a pity
;; because it would be nice to put the button *inside* the current
;; broser window, at the point where the applet is invoked.
(applet-newpage)

;; put the button under the broser window
(define button-name (string-append browser-window-name ".quit-1"))

(define (quit-1-callback)
  (begin
    (display "quitting now\n")
    (destroy button-name)))

; A callback for when the user terminates the applet (boiler plate)
(define-applet-terminate (tcl-lambda () (quit-1-callback)))

(display "button-name is ")
(display button-name)
(display "\n")

(button (string->symbol button-name) :text "quit-1"
	:command (tcl-lambda () (quit-1-callback)))

(display "about to pack the button\n")
(pack (name->window button-name))

(display "about to enter tk-main-loop\n")

(tk-main-loop)
(quit)

The only difference in `learn-applet-1.scm' is that the button is a sub-widget of the browser-window-name widget, rather than being in a new top level widget.

Drawing a matrix on a canvas

The next program [??? not yet]

Guile Applet Specification

This section has has been written by Gordon Irlam, gordoni@cygnus.com, at Cygnus Support, February 28, 1996. It is included here verbatim.

This section provides the specification for writing Guile applets for use with the SurfIt! demo browser.

HTML Applet Extension

Guile Scheme applets are denoted by the mime type application/guile. This is the default type for the file extension .scm.

An applet can be inlined within a HTML document.

@
@
@
The applet applet.scm will be loaded, inserted into the page, and run when the document containing it is first loaded. fallback_html will be displayed by browsers that don't support Guile applets.

An applet may also be invoked when a hyperlink is followed.

@
@
@
When the hyperlink is selected the applet applet.scm will be loaded and executed. The original document will be cleared from the page only if the applet explicitly requests it to be. fallback_html will be displayed by browsers that don't support Guile applets.

Applet Requirements

An applet is required to be a syntactically well formed Guile Scheme program. When an applet is invoked the corresponding Guile program is retrieved, loaded, and executed.

Every applet is required to include the applet library:

@
Incorporate the applet library into a Guile application. This is needed as a prerequisite to performing any of the other applet commands.

Every applet is required to define a routine to be called by the browser when the browser requires the applet to terminate execution:

@
routine is the name of a routine that will be invoked by the browser when the applet is required to terminate execution. If the applet is visible it should destroy the Tk canvas upon which it is visible and then exit.

An applet will persist for as long as it is accessible -- either externally through it's being displayed on a page, or internally through the Scheme environment.

Applet API

All applets reside in the same top level environment. This allows state to be shared between applets and to persist between applet invocations.

An applet has access to all the features of a regular Guile Scheme program and to the gTcl/gtk Guile extensions. The features of gtk allow the Guile applet to interactively display itself within the parent document.

Note: While Guile provides the ability to control namespaces, and this is necessary to provide a secure environment within which applets can be run, this has not been done for the SurfIt! Guile demo browser. The SurfIt! Guile demo browser is mainly intended as a research prototype, not a production web browser.

@
@
browser-window-name is a string containing the Tk window name of the browser window. browser-window is the corresponding Tcl proc to which window commands can be sent.

@
@
applet-window-name is a string containing a Tk window name for a frame that can be used to contain the applet. applet-window is the corresponding Tcl proc to which window commands can be sent. The frame still needs inserting into the browser window, assuming the applet is visible.

@
applet-embedindex is a string containing the offset within the browser window of the applet's anchor. Most commonly this is used when insert the applet into the browser window at the same location as the original html:
(browser-window 'window 'create applet-embedindex :window
applet-window-name).

@
This routine clears the current contents of the browser window.
@
This routine parses the html specified by html and renders the result adding it to bottom of the browser window.

@
This routine loads and renders the contents of the object specified by URL url inserting it into the applet window.

@
This routine loads and returns the contents of the object specified by URL url. Note: This particular routine will probably not be present in guile-r0. Its suggested incorporation into the API, and it's syntax are still tentative.

Applet Behavior

Applets should not monopolize the cpu. Instead they should be written using a callback or event loop polling based style so that the Tk event handler can continues to operate, and the user can continue to interact with the browser.

Browser Behavior

An run time error occurring within an applet that goes uncaught will cause the applet to exit, but the browser will continue to function.

Guile in a library - using libguile.a

@nobreak In the previous chapters Guile was used to write programs entirely in scheme, and no C code was seen; but we have been claiming ad nauseam that Guile is an extension language. Here we see how that is done, and how that can be useful.

Two world views

In this manual we usually jump into examples and explain them as you type in the code; here will will digress and ramble for a few paragraphs to set some concepts straight, and then let you type (or paste) in fun examples.

In 1995 the author of this manual implemented a large program, Gnudl, using Guile quite extensively. In the design phase of Gnudl I (I switch to first person in this paragraph) found I had to make a choice: should the fundamental data structures be C or scheme data structures?

Guile allows C to see its data structures (scalar types, lists, vectors, strings @dots{}). C also allows guile to see its data structures. As a largre program designer, you have to decide which of those capabilities to use. You have two main choices.

You can write your software mostly in scheme. In this case, your C software will mostly parse the scheme code with Guile calls, and provide some new primitive procedures to be used by scheme. This is what Gnudl does.

Or you can write your software mostly in C, occasionally allowing scheme code to be parsed by Guile, either to allow the user to modify data structures, or to parse a configuration file, @dots{}

Mixing the two approaches seems unwise: the overall layout would be confusing. But who knows? There might be problems that are best solved by a hybrid approach. Please let us know if you think of such a problem.

If you use the former approach, we will say that the master world is scheme, and the C routines serve scheme and access scheme data structures. In the latter case, the master world is C, and scheme routines serve the C code and access C data structures.

In both approaches the libguile.a library is the same, but a predominantly different set of routines will be used. To clarify these two approaches further, when we go through examples of libguile use, we will point out which is the master world.

What is libguile?

Libguile is the library which can be linked to C programs and which allows the C programs to start a scheme interpreter and execute scheme code. There are also facilities in libguile to make C data structures available to scheme and vice versa.

This chapter gives a gentle introduction to libguile.a, presenting some hello world-style programs which Mark Galassi wrote while teaching himself to use libguile.

The Guile Programmer's Manual gives more examples of programs written using libguile, illustrating diverse applications. You can also consult Mark Galassi's Gnudl document to see a large scale project that uses C and scheme code together.

How to get started with libguile

Here is an elementary first program, learn0, to get going with libguile. The program (which uses scheme as a master world) is in a single source file learn0.c:

#include <stdio.h>

/* the include file for guile */
#include <gscm.h>

static GSCM_status guile_init()
{
#if 0                           /* don't need any of these extra packages */
  scm_init_ctax();
  scm_init_unix();
  scm_init_posix();
  scm_init_ioext();
  scm_init_gTcl();
  scm_init_gtk();
#endif /* 0 */
}

main(int argc, char *argv[])
{
  GSCM_status status;
  GSCM_top_level toplev;
  char *eval_answer;
  char input_str[200];
  int done;

  printf("hello guile\n");

  /* start a scheme interpreter */
  status = gscm_run_scm(argc, argv, 0, stdout, stderr, guile_init, 0, "#t");
  if (status != GSCM_OK) {
    fputs(gscm_error_msg(status), stderr);
    fputc('\n', stderr);
    exit(1);
  }

  /* create the top level environment */
  status = gscm_create_top_level(&toplev);
  if (status != GSCM_OK) {
    fputs(gscm_error_msg(status), stderr);
    fputc('\n', stderr);
    exit(1);
  }

  /* for fun, evaluate some simple scheme expressions here */
  status = gscm_eval_str(NULL, toplev, "(define (square x) (* x x))");
  status = gscm_eval_str(NULL, toplev, "(define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1)))))");
  status = gscm_eval_str(NULL, toplev, "(square 9)");
  status = gscm_eval_str(NULL, toplev, "(factorial 100)");

  /* now sit in a scheme eval loop: I input the expressions, have guile
   * evaluate them, and then get another expression.
   */
  done = 0;
  while (!done) {
    if (gets(input_str) == NULL || strcmp(input_str, "quit") == 0) {
      done = 1;
    } else {
      status = gscm_eval_str(NULL, toplev, input_str);
    }
  }

  /* now clean up and quit */
  gscm_destroy_top_level(toplev);
  exit(0);
}

If you name this program learn0.c, it can now be compiled with:

gcc -g -I/packages/include/guile -c learn0.c -o learn0.o
gcc -o learn0 learn0.o -L/packages/lib -lguile -lm
(remember to fix the paths if you don't use `/packages' as a prefix).

The program is simple: it creates a scheme interpreter, passes a couple of strings to it that define new scheme functions square and factorial, and then a couple of strings that invoke those functions.

It then goes into a read-eval loop, so you could type one-line scheme expressions to it and have them evaluated. For example:

<shell-prompt> ./learn0
hello guile
;;; loading modops...
;;; ...loaded /packages/lib/gls/bootstrapping/modops.
;;; loading libguile...
;;; ...loaded /packages/lib/gls/bootstrapping/libguile.
;;; loading slibhooks...
;;; ...loaded /packages/lib/gls/bootstrapping/slibhooks.
;;; loading require...
;;;   loading slibcat...
;;;   ...loaded /packages/lib/gls/bootstrapping/slibcat.
;;; ...loaded /packages/lib/gls/bootstrapping/require.
;;; loading mule...
;;; ...loaded /packages/lib/gls/bootstrapping/mule.
learn0> (require 'debug)
;;; loading debug...
;;; ...loaded /packages/lib/gls/debug.
; type (init-debug)learn0> 
learn0> (print (sin 1.3))
963.558185417193e-3 
learn0> (print (factorial 10))
3628800 
learn0> (quit)
<shell-prompt> 

You should notice the key steps involved in this learn0 program:

  1. #include <gscm.h>
  2. You need a guile_init()-like routine, which could even be trivial like the one in this example, to pass to gscm_run_scm(). This allows you to tell gscm_run_scm() which optional guile packages to use. Note that in this example I am only interested in the scheme interpreter, and not in the extra packages, so all the extra package initialization has been #if-ed out.
  3. You must invoke gscm_run_scm() and gscm_create_top_level() at the beginning of your program. This sets up the scheme interpreter to which you can then pass strings for evaluation.
  4. You pass strings to the scheme interpreter with the gscm_eval_str() routine.
  5. You quite with gscm_destroy_top_level().
  6. You link your program with -lguile.

More interesting programming with libguile

The learn0 program shows how you can invoke scheme commands from a C program. This is not such a great achievement: the same could have been done by opening a pipe to SCM or any other scheme interpreter.

A true extension language must allow callbacks. Callbacks allow you to write C routines that can be invoked as scheme procedures, thus adding new builting procedures to scheme. This also means that a scheme procedure can modify a C data structure.

Guile allows you to define new scheme procedures in C, and provides a mechanism to go back and forth between C and scheme data types.

Here is a second program, learn1, which demonstrates these features. It is split into three source files: learn1.c, c_builtins.h and c_builtins.c. I am including the code here, but you might just want to look at the online source code and the Makefile that come in the learn_libguile distribution. Notice that learn1 uses a scheme master world, and the C routines in c_builtins.c are simply adding new primitives to scheme.

learn1.c

Here is `learn1.c':

#include <stdio.h>

#include <gscm.h>
/*
#include <Tcl.h>
#include <tk.h>
*/

#include "c_builtins.h"


static GSCM_status guile_init()
{
#if 0                           /* don't need fancy packages */
  scm_init_ctax();
  scm_init_unix();
  scm_init_posix();
  scm_init_ioext();
  scm_init_gTcl();
  scm_init_gtk();
#endif /* 0 */
}

main(int argc, char *argv[])
{
  GSCM_status status;
  GSCM_top_level toplev;
  char *eval_answer;
  char input_str[200];          /* ugly hack: assume strlen(line) < 200 */
  int done;

  printf("hello guile\n");

  /* start an interpreter */
#if 0                           /* this is the old way */
  status = initialize_gscm(0, argc, argv);
#endif /* 0 */
  /* start a scheme interpreter */
  status = gscm_run_scm(argc, argv, 0, stdout, stderr, guile_init, 0, "#t");
  if (status != GSCM_OK) {
    fputs(gscm_error_msg(status), stderr);
    fputc('\n', stderr);
    exit(1);
  }

  /* create the top level environment */
  status = gscm_create_top_level(&toplev);
  if (status != GSCM_OK) {
    fputs(gscm_error_msg(status), stderr);
    fputc('\n', stderr);
    exit(1);
  }

  /* for fun, evaluate some simple scheme expressions here */
  status = gscm_eval_str(NULL, toplev, "(define (square x) (* x x))");
  status = gscm_eval_str(NULL, toplev,
            "(define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1)))))");
  status = gscm_eval_str(NULL, toplev, "(square 9)");
  status = gscm_eval_str(NULL, toplev, "(factorial 100)");

  /* now try to define some new builtins, coded in C, so that they
   * are available in scheme.  note that I have put junk in the documentation
   * strings because I have not yet read the manual on how doc strings
   * should be written :-|
   */
  gscm_define_procedure("c-factorial", c_factorial, 1, 1, 0, "hi there");
  gscm_define_procedure("c-sin", c_sin, 1, 1, 0, "hi there");
  gscm_define_procedure("v-t", vector_test, 1, 1, 0, "hi there");

  /* now sit in a scheme eval loop: I input the expressions, have guile
   * evaluate them, and then get another expression.
   */
  done = 0;
  fputs("learn1> ", stdout);
  while (!done) {
    if (gets(input_str) == NULL || strcmp(input_str, "(quit)") == 0) {
      done = 1;
    } else {
      status = gscm_eval_str(NULL, toplev, input_str);
      fputs("learn1> ", stdout);
    }
  }

  /* now clean up and quit */
  gscm_destroy_top_level(toplev);
  exit(0);
}

c_builtins.h

Here is `c_builtins.h':

/* builtin function prototypes */

SCM c_factorial(SCM n);
SCM c_sin(SCM n);
SCM vector_test(SCM s_length);

c_builtins.c

Here is `c_builtins.c':

#include <stdio.h>
#include <math.h>

#include <gscm.h>

#include "c_builtins.h"

/* this is a factorial routine in C, made to be callable by scheme */
SCM c_factorial(SCM s_n)
{
  int i;
  unsigned long result = 1, n;

  n = gscm_2_ulong(s_n);

  GSCM_DEFER_INTS;
  for (i = 1; i <= n; ++i) {
    result = result*i;
  }
  GSCM_ALLOW_INTS;
  return gscm_ulong(result);
}

/* a sin routine in C, callable from scheme.  it is named c_sin()
 * to distinguish it from the default scheme sin function
 */
SCM c_sin(SCM s_x)
{
  double x = gscm_2_double(s_x);

  return gscm_double(sin(x));
}

/* play around with vectors in guile: this routine creates a
 * vector of the given length, initializes it all to zero except
 * element 2 which is set to 1.9.
 */
SCM vector_test(SCM s_length)
{
  SCM xvec;
  unsigned long c_length;

  c_length = gscm_2_ulong(s_length);
  printf("requested length for vector: %ld\n", c_length);

  /* create a vector */
  xvec = gscm_vector(c_length, gscm_double(0.0));
  /* set the second element in it */
  gscm_vset(xvec, 2, gscm_double(1.9));

  return xvec;
}

What learn1 is doing

If you compare learn1 to learn0, you will find that learn1 uses a new guile construct: the function gscm_define_procedure():

  /* now try to define some new builtins, coded in C, so that they
   * are available in scheme.  note that I have put junk in the documentation
   * strings because I have not yet read the manual on how doc strings
   * should be written :-|
   */
  gscm_define_procedure("c-factorial", c_factorial, 1, 1, 0, "hi there");
  gscm_define_procedure("c-sin", c_sin, 1, 1, 0, "hi there");
  gscm_define_procedure("v-t", vector_test, 1, 1, 0, "hi there");

It is clear that gscm_define_procedure() adds a new builtin routine written in C which can be invoked from scheme. We can now revise our checklist for programming with libguile, so it includes adding callbacks.

  1. #include <gscm.h>
  2. You need a guile_init()-like routine, which could even be trivial like the one in this example, to pass to gscm_run_scm(). This allows you to tell gscm_run_scm() which optional guile packages to use. Note that in this example I am only interested in the scheme interpreter, and not in the extra packages, so all the extra package initialization has been #if-ed out.
  3. You must invoke gscm_run_scm() and gscm_create_top_level() at the beginning of your program. This sets up the scheme interpreter to which you can then pass strings for evaluation. I believe that this routine will soon be renamed to start with the prefix gscm_: the prefix of all the routines in the guile programmer's interface.
  4. You can now register callbacks; i.e. define new builtin scheme functions, with the gscm_define_procedure() routine.
  5. You pass strings to the scheme interpreter with the gscm_eval_str() routine.
  6. You quit with gscm_destroy_top_level() (which currently gives some silly error message).
  7. You link your program with -lguile.

I breezed by the issue of how to write your C routines that are registered to be called from scheme. This is non-trivial, and is discussed at length in the Guile Programmer's Manual.

Compiling and running learn1

gcc -g -I/packages/include/guile   -c learn1.c -o learn1.o
gcc -g -I/packages/include/guile   -c c_builtins.c -o c_builtins.o
gcc -o learn1 learn1.o c_builtins.o -L/packages/lib/scm -L/packages/lib -lguile -lm

If you run learn1, it will prompt you for a one-line scheme expression, just as learn0 did. The difference is that you can use the new C builtin procedures (c-factorial, c-sin, v-t).

<shell-prompt> ./learn1
hello guile
;;; loading modops...
;;; ...loaded /packages/lib/gls/bootstrapping/modops.
;;; loading libguile...
;;; ...loaded /packages/lib/gls/bootstrapping/libguile.
;;; loading slibhooks...
;;; ...loaded /packages/lib/gls/bootstrapping/slibhooks.
;;; loading require...
;;;   loading slibcat...
;;;   ...loaded /packages/lib/gls/bootstrapping/slibcat.
;;; ...loaded /packages/lib/gls/bootstrapping/require.
;;; loading mule...
;;; ...loaded /packages/lib/gls/bootstrapping/mule.
learn1> (require 'debug)
;;; loading debug...
;;; ...loaded /packages/lib/gls/debug.
; type (init-debug)learn1> 
learn1> (print (c-factorial 6))
720 
learn1> (print (c-factorial 20))
2192834560 
learn1> (print (c-factorial 100))
0 
learn1> (print (c-sin 1.5))
997.494986604054e-3 
learn1> (print (c-sin 1.5))
997.494986604054e-3 
learn1> (print (v-t 10))
requested length for vector: 10
#(0.0 0.0 1.9 0.0 0.0 0.0 0.0 0.0 0.0 0.0) 
learn1> (print (v-t 15))
requested length for vector: 15
#(0.0 0.0 1.9 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0) 
learn1> (quit)
<shell-prompt> 

As you see, taking (c-factorial 100) does not use bignumbers and returns a bogus answer.

Further examples

Further "idealized" examples are included in the examples distribution. They include programs to:

More on the Guile interface to Tk

A couple of the examples in the quick tour made use of the Tk toolkit. Here we will say more about how Guile interfaces to Tk. We will also give you a recipe for reading Tk documentation, which is written assuming the Tcl interface, and writing scheme code with it.

In this chapter we do not give any sort of introduction to Tk in general. There are books on Tk, but maybe the best way to learn the Tk widgets is to go through the wtour tour of widgets that is distributed with Tk. It is much more pedagogical than the main book Tcl and the Tk Toolkit.

What you need to use Tk

The Guile program is usually compiled with the Tk interface, so to use Tk you only need to include this preamble:

(require 'Gwish)
(use-library tcl)
(use-interface tcl)
(use-interface tclhack)

and then conclude the main script with:

(tk-main-loop)
(quit)

Note: the preamble is kind of ugly, and it will probably change.

Creating a widget

Here are some (out of context) examples of the syntax for creating Tk widgets:

(button '.quit :text "quit" :command (tcl-lambda () (quit-callback)))
(text '.a :yscrollcommand ".b set")
(scrollbar '.b :command ".a yview")
(frame '.button-bar :relief 'raised :bd 2)
(canvas '.ca :width 200 :height 300)
(label '.lab :text "this is a label")

What can we deduce from these examples of widget creation?

  1. There are new primitive scheme procedures for each type of widget; invoking this procedure creates the widget.

  2. The widget name is always followed by a quoted variable name. The variable name is the standard Tk widget hierarchical name with the dot separator.

  3. Options that modify the appearance or behaviour of the widget are given with a colon, such as :text, :command, :width @dots{}

Scheme callbacks

A widget callback (or simply callback) is a procedure that gets invoked when something happens in a widget, for example if the mouse is clicked on a button or scrollbar.

When you first create a Tk widget, you can specify that a procedure should become the callback, usually with the :command option in the widget creation, although a widget could allow several callbacks, and those could be set by other options such as :yscrollcommand.

If a command is to invoke a scheme procedure, it is done with the tcl-lambda primitive. This is similar to a simple scheme lambda expression, but it straightens out the calling convention between Tcl and scheme.

The tcl-lambda expression also makes sure that the anonymous procedure created will not be garbage-collected away while a callback is not being executed.

Notice that tcl-lambda is not a clean implementation, and Guile will probably be fixed eventually so that you can just use lambda.

But not all callbacks invoke scheme procedures. In the creation examples just given, the widget created by

(scrollbar '.b :command ".a yview")
passes a message to the text widget .a. This message passing is done with the string ".a yview", which just maps directly to the equivalent Tcl code.

Sending a command to a widget

Once a widget has been created and its callbacks (if any) have been registered, that widget becomes a new scheme primitive procedure. This procedure can be used to give further instructions to a widget.

One example of this is to add or change configuration options to a widget after it has been created. Try this self-contained program to see an example of the config command being sent to a widget. It also shows examples of putting several buttons together in a frame, and illustrates the destroy command that kills off a Tk widget.

#!/whatever-path/guile -
; -*-scheme-*-

;; an abbreviated version of the quit button program

(require 'Gwish)
(use-library tcl)
(use-interface tcl)
(use-interface tclhack)

;; create a frame widget to house the buttons
(frame '.button-bar :relief 'raised :bd 2)
(pack '.button-bar)

;; create the quite button: its callback destroys the top level widget
(button '.button-bar.quit :text "quit" :command
  (tcl-lambda ()
    (begin
      (display "quitting now\n")
      (destroy "."))))

;; create the "change text" button: its callback changes the text
;; of the "quit" button, and destroys itself.
(button '.button-bar.change-text :text "change text" :command
  (tcl-lambda ()
    (begin
      (.button-bar.quit 'config :text "hey, it just changed")
      (destroy ".button-bar.change-text"))))

(pack '.button-bar.quit '.button-bar.change-text :side 'left)

(tk-main-loop)
(quit)

Goonix - the Guile interface to Posix

Guile has a module called goonix which implement the posix system calls (a standardized set of UNIX system calls) in scheme. This makes it easy to do things like list directories, create processes and so forth.

Here is an example of using the goonix opendir, readdir and closedir calls.

;; list-dir takes a path and returns a list of files in that directory
(define (list-dir path)
  (letrec ((dport (%opendir path))
	   (form-dlist			; a procedure that forms the list
	    (lambda (dl)
	      (let ((fname (%readdir dport)))
		(if (eof-object? fname)
		    dl
		    (form-dlist (cons fname dl))))))
	   )
    (define output-list (form-dlist '()))
    (%closedir dport)
    output-list
    )
  )

@paragraphindent 2

@parskip 4pt plus 1pt

Internationalization Features in Guile

This chapter has been written by Takumi Doi at Cygnus Support, March 29 1996. It is included here verbatim.

Among significant improvements made to Guile in this release, this appendix describes the internationalization features that allows Guile manipulate and render characters from various international character sets including Latin, Japanese Kanji, Chinese Hanji, Korean Hangul, et al.

Building Guile with Internationalization Features

To include internationalization feature in Guile, you should specify the option --enable-i18n when you configure Guile, such as:

% ./configure --enable-i18n --prefix=`pwd`/=inst

In the current release, the modules affected by this option are only libguile, gls, and gtcltk. In addition, Tcl/Tk that comes with this release incorporates support solely for Japanese EUC patches. This also means the rest of plugin libraries are yet to be internationalized.

Character and String representations

In Guile, each character is identified by a unique internal character code, a 24 bit integer. The function char->integer can be used to retrieve the internal character code of a character.

On the other hand, strings are represented as sequences of 8 bit-byte elements, where characters with character codes beyond 255 are split into adjacent bytes to form a multibyte string.

This design decision of using multibyte strings is motivated by one of major goals of Guile; to provide an east-to-integrate underlying implementation for GNU Emacs. Authors also believe that this design allows a single string data type and compact string representation that can easily be support evolving international standards with larger character sets.

External Character Encodings

While Guile has its own internal character representation, the new internationalization features enable users to easily handle characters from wide variety of existing coded character sets.

By external character encoding the author means any character encoding method other than the Guile Scheme internal encoding, whose coded characters have to be converted when reading from text streams and writing to external devices for saving or rendering.

In Guile Scheme, such conversion is controled by optional arguments to several I/O procedures, in addition to a couple of global variable values to be used as the default conversion method.

Following self-evaluating symbols designate available character encodings for file I/O as well as process I/O:

These symbols can be specified as encoding parameter for procedures described later in this document.

For precise meaning of these values, see also online Info manuals included in Mule, the Multilingual Emacs. As of this writing, Guile supports as many external coded character sets as the Mule version 2.3, in addition to Unicode.

New Guile Scheme variables

{Variable} input-coding-system

{Variable} output-coding-system

These variables are used by the function open-file and its buddies to determine default external encoding to associate with opened ports. The value #f means no conversion takes place on I/O, which is the default.

{Variable} process-coding-system

Used by functions to determine the character encoding understood by the operating system environment. The value of this variable affects the behavior of each of follwing functions:

The initial value is #f, meaning that no conversion takes place.

Changes to existing Guile Scheme commands

Although not apparent changes, each of string operations now treats a string as a sequence of characters, not a byte chunk. Namely, index value is assumed to be the character position instead of byte position, the length of a string is the number of characters in the string, not the number of bytes, and so on. This is also the case with the uniform vector operations on multibyte strings.

Users who need to operate on byte sequences are encouraged to use byte-vector extensions instead.

Follwing procedures are now extended to form the internationalization features in Guile:

{Function} open-file str mode &optional encoding

{Function} open-input-file str &optional encoding

{Function} open-output-file str &optional encoding

{Function} open-io-file str &optional encoding

These functions open a file specified by str, and return a port associated with the file. str must be a string or a symbol that names the file to open.

The mode argument to open-file specifies the direction[s] to which I/O operations are allowed via the returned port. It can be one of following values:

The optional argument encoding can be a symbol that names an external character encoding. If specified, further I/O operations via opened port will convert the file contents between the specified character encoding and the Guile Scheme internal character encoding. If encoding is omitted, the encoding of the file is determined by the current value of input-coding-system (for input) and output-coding-system (for output).

The functions open-input-file, open-output-file and open-io-file are similiar to open, except for opening a file for read-only, write-only, and read-write, respectively.

{Function} call-with-input-file str proc &optional encoding

{Function} call-with-output-file str proc &optional encoding

Call proc with one argument, a port which is the file named by str.

Both functions close the port after proc returns.

Both return the value of proc.

The optional argument encoding specifies the external character encoding used in the file str. Default behavior is determined by the current values of input-coding-system and output-coding-system, respectively.

{Function} load name &optional encoding

Loads the Scheme source file named by name in core. if encoding is specified, the file name is assumed to have contents encoded in encoding. Otherwise, the current value of input-coding-system is used.

New Guile Scheme commands

{Function} port-coding port

{Function} set-port-coding! port encoding &optional modes

The function port-coding retrieves the character encoding used by port. port must be an open port object, otherwise an error is signaled. It returns a symbol that names the character encoding currently used by port. Refer previous sections for external character encoding symbols that are available in this release.

The function set-port-coding! sets the character encoding attribute of port to encoding.

Following procedures are not immediately relevant to internationalization, however added in the hope they will effectively compliment the uses of raw byte data (such as binary image data and network packet data) that might normally have been implemented using strings:

{Function} uniform-vector->string uve encoding

{Function} string->uniform-vector str encoding

Coerces between byte-vector and string. In Guile, a byte-vector is a uniform-vector whose prototype is #\nul.

If specified, code conversion between encoding and Guile internal encoding is performed. Otherwise, no conversion takes place.

For uniform-vector->string, programmers must make sure if each vector element has a valid value to form a string element.

{Function} concatenate &rest args

{Function} concatenate! &rest args

Similiar to string-append, but works on any uniform vectors. each of args must be uniform-vector with same element type. concatenate returns a newly created vector, where concatenate! modifies the original vector.

{Function} subvector vec start end

Returns a uniform-vector formed from elements of the uniform-vector vec, beginning from index start (inclusive) and ending with index end (exclusive).

Note in this release, returned vector is a shared-vector to the original vector. This implementation is subject to change in future releases.

New libguile procedures

{Function} gscm_foreign_str src len encoding

{Function} gscm_foreign_str0 src encoding

Used for converting a string from the encoding in "foreign" (anywhere outside GSCM) code to Guile Scheme internal encoding.

Similiar to gscm_str and gscm_str0 respectively, except for accepting encoding argument. encoding must be of type SCM and a valid Scheme symbol representing an character encoding. This means you may have to scm_intern the encoding name in your code. This subject to change.

{Function} gscm_2_foreign_str str_out len_out obj_in encoding

Used for converting SCM string contents to "foreign" string encoded in encoding.

Similiar to gscm_2_string. but accepts encoding argument. encoding must be of type SCM and a valid Scheme symbol representing an character encoding. This means you may have to scm_intern the encoding name in your code (this is subject to change).

str_out must be an address to unsigned char * storage, but not neccessarily be an allocated memory.

Where to find more Guile/Scheme resources

Right now this appendix is just pasted in from the bibliographies in Gnudl and Jacal. It requires format cleanup and some changes.

Online resources

@
William Clinger and Jonathan Rees, Editors. Revised(4) Report on the Algorithmic Language Scheme. In ACM Lisp Pointers IV (July-September 1991).

@
Todd R. Eigenschink, Dave Love, and Aubrey Jaffer. SLIB, The Portable Scheme Library. Edition 2.01, for SLIB version 2a2, January 1995.

@
Aubrey Jaffer. JACAL Symbolic Mathematics System. Version 1a5, April 1994.

@
@
Documentation of scm extensions (beyond Scheme standards). Documentation on the internal representation and how to extend or include scm in other programs.

Books and papers

@
IEEE Standard 1178-1990. IEEE Standard for the Scheme Programming Language. IEEE, New York, 1991.

@
Brian Harvey and Matthew Wright. Simply Scheme: Introducing Computer Science MIT Press, 1994 ISBN 0-262-08226-8

@
Harold Abelson and Gerald Jay Sussman with Julie Sussman. Structure and Interpretation of Computer Programs. MIT Press, Cambridge, 1985.

Bug reports and hackarounds for various guile releases

Note: this is the r0 release I picked up on April 12 1996; I am not clued in to the release nomenclature, but I thought it was important to call it r0.3 because version r0 has changed around a few times already.

Other note: the guile-1.0b0 is a version I got from Tom Lord on 1996/04/22. It has diverged significantly from guile-r0.3, and I am now experimenting with it.

Installation problems with guile-1.0b0

Installation problems with guile-r0.3

The guile-r0.3 snapshot is one Tom Tromey made for me. It contains fixes to the tcl-lambda() problem I reported.

I configure it with

./configure --prefix=/packages --enable-i18n

Execution problems with guile-r0.3

Installation problems with guile-r0.2

BELOW HERE REFERS TO r0.2

=======================================================

Note: this is the r0 release I picked up on March 29 1996; I am not clued in to the release nomenclature, but I thought it was important to call it r0.2 because version r0 has changed around a few times already.

Execution problems with guile-r0.2

tcl-lambda () seems to have a problem in defining menu buttons. The `learn-guile-3.scm' example of using Tk widgets identifies this pretty well. The last tcl-lambda () command in any menu item gets applied to *all menu items* from *all menus*.

I don't yet have a hackaround.

What is missing in this manual?

I feel that a few things have not been treated here; either they were missing in the outline, or I don't know much about them. I would like to add them eventually.

Ggl, mesa and glut: Guile has an interface to SGI's Open GL library, using the free GL clone "mesa". This also works with the glut toolkit. There is no documentation; I will have to study the code.

ctax: Ctax is a C-like syntax for scheme, provided as one of the plugin modules for Guile. It would be nice to show examples of ctax, and examples of how to switch from one language to another as you fancy.

threads: Threads are as trendy as applets, and are used in the applet formalism of Guile. What is the interface to threads from C and from scheme?

Concept Index

a

  • anonymous procedure
  • applets

    b

  • builtin functions

    c

  • callback
  • closure

    e

  • extension languages

    g

  • GNU Extension Language
  • guile

    l

  • learn0
  • learn1
  • libguile

    m

  • master world

    o

  • object

    p

  • posix

    s

  • scripting languages

    w

  • widget callback