A guided tour through the CHICKEN scheme republic

  1. A guided tour through the CHICKEN scheme republic
  2. What to expect from this tour
  3. Welcome to CHICKEN scheme
  4. Installing CHICKEN scheme
    1. Building CHICKEN from a stable source
    2. Building a development snapshot or from git
  5. Using CHICKEN
    1. Using the interpreter
    2. Running interpreted scripts
    3. Compiling your programs
    4. More than just standard scheme: Extending R5RS with Units and Eggs
    5. Finding your way: The documentation
      1. Manual
      2. Wiki and egg index
      3. Chickadee
      4. Searching offline: chicken-doc
    6. The home of bugs: CHICKEN'S bug tracker
    7. Getting help from humans
  6. Programming in CHICKEN
    1. Choosing an editor
    2. Building complex projects
    3. Writing your own extensions
    4. Build your application as a static binary
    5. Using the test infrastructure
  7. Wrapping up
  8. Thanks

What to expect from this tour

This session will inform interested programmers about the infrastructure and motivations that drive the CHICKEN scheme republic and the people behind it. The major goal is to get you ready for programming in scheme today, so you can implement your great idea for a program in a nice programming language. After this talk you should be able to find your way on your own, know who you can ask for help and how to operate the tools that come with the CHICKEN scheme system.

Welcome to CHICKEN scheme

The CHICKEN scheme republic consists of

Installing CHICKEN scheme

Depending on your operating system you may choose your distribution's package system to install CHICKEN or build it yourself from source. Please do use the latest release version. If your distribution's package is too old you can nag the package maintainer to update and build your own in the meantime.

Building CHICKEN from a stable source

The CHICKEN core system is held in a git repository at http://code.call-cc.org The latest major release is 5.3.0. Please use this first. There may be development snapshots, if you want to try or need new features not already in the latest release. The code website offers tarballs for each. The CHICKEN system requires GNU make as a build dependency as well as a recent C compiler. Compilation works on all major free OSes like GNU/Linux, *BSD, Haiku, as well as Mac OS X, Windows and Solaris.

So to install the 5.3.0 release on a linux box download the tarball:

 $ wget http://code.call-cc.org/releases/5.3.0/chicken-5.3.0.tar.gz
 $ tar xfz chicken-5.3.0.tar.gz
 $ cd chicken-5.3.0
 $ make 
 # make install

This will build and install CHICKEN in the default prefix "/usr/local". If you want to use a custom path for your installation provide a PREFIX parameter to both make calls.

 $ make PREFIX=$HOME/chickens/5.3.0
 $ make PREFIX=$HOME/chickens/5.3.0 install

Note that the PREFIX is used as part of search path for extensions by the loader and needs to be consistent for both parts.

If you want to use clang instead of the default gcc as C compiler, make and make install chicken like this:

 $ make PLATFORM=<your-platform> C_COMPILER=clang
 # make PLATFORM=<your-platform> C_COMPILER=clang install 

Building a development snapshot or from git

Development snapshots differ from release tarballs in one significant way: They do not include bootstrapping code and require a pre-installed CHICKEN to build. So you need to install the latest release first and add the additional steps when building the snapshot:

 $ make boot-chicken
 $ make CHICKEN=./chicken-boot
 $ make install

Of course you can also build this in a separate PREFIX path, the same rules apply.

Using CHICKEN

After a successful installation you should have the following binaries in your path:

Using the interpreter

Calling csi without arguments will start a REPL for you:

 $ csi
 CHICKEN
 (c) 2008-2021, The CHICKEN Team
 (c) 2000-2007, Felix L. Winkelmann
 Version 5.3.0 (rev e31bbee5)
 linux-unix-gnu-arm64 [ 64bit dload ptables ]
 
 Type ,? for help.
 #;1> "hello world!"
 "hello world!"
 #;2> (+ 1 2)
 3
 #;3> (import (chicken string))
 ; loading /home/ckeen/chicken/5.3.0/lib/chicken/11/chicken.string.import.so ...
 #;4> (string-split #1)
 ("hello" "world!")

As you can see you can refer to results from an earlier command by using its history number prefixed with a pound sign (#). To leave the interpreter type ",q". To see a list of available special commands type ,?.

Unlike in earlier versions of CHICKEN the (import) statement now universally imports and loads extensions. So for this example the ```string-split``` procedure is part of a CHICKEN core module calles *strings*.

Running interpreted scripts

Another common use for csi is to be used as a interpreter for your CHICKEN scripts. Here is a small script that reverses all input:

 #!/usr/local/bin/csi -s
 ; This imports the nonstandard procedures read-string and string-reverse
 (import (chicken io) srfi-13)
 (display (string-reverse (read-string #f)))
 (newline)

When calling the script, it does reverse all input:

 $ chmod +x ./rev.scm
 $ echo -n hello world|./rev.scm
 dlrow olleh
 $

Notice the -s parameters above. -s will exit the REPL for you when the script has been evaluated completely. For a complete list call "csi -h".

Compiling your programs

The real strength of CHICKEN is its compiler. Your code will run faster and some more advanced features like calling C functions of other libraries in your scheme code are available during compilation only. For everyday usage you will use the CHICKEN scheme compiler driver mostly. Suppose we want to compile our reverse script from above:

 $ csc rev.scm
 $ echo -n hello world|./rev
 dlrow olleh
 $

csc will generate a binary that has the same name as your scheme file without the .scm extension. Note that this extension is not enforced by the compiler but has been used by most schemers in the past. The resulting binary will be dynamically linked to the CHICKEN runtime library. In a more complex example you may need to add additional libraries for the linker yourself, for example external libraries that you use, like SDL, libexif, etc.

If you want to distribute your binary as a standalone application without the need of CHICKEN installed there is the possibility of building a static binary.

More than just standard scheme: Extending R5RS with Units and Eggs

The simple example above is of course not at all that simple. There is a lot of work going on under the hood. Reading everything from a port, then reversing this string. If you already know scheme and the scheme standard you might have noticed that these procedures are not part of R5RS, the scheme standard CHICKEN is based on. To meet the goal of being a practical scheme environment CHICKEN ships with extensions included in the core distribution. These are covered by the CHICKEN Manual. They include the following topics:

Some modules have been omitted from this list, as they cover advanced topics. For the complete overview and description see the manual section about included modules.

As those are so commonly used in scheme programming they are part of the core distribution. Extensions not shipped with the core system are called "eggs". Those can be installed with the chicken-install program. If we need a sha1-sum in our application for example we just install the "simple-sha1" egg:

 $ chicken-install simple-sha1
 retrieving...
 [loads of output]
 $

This will need a working internet connection and download the extension and its scheme dependencies from call-cc.org or a mirror. After that the extension is compiled and placed in your PREFIX, ready to be used. To be able to use the procedures exported by an egg just place (import egg-name) in your program. If we now want to calculate a sha-1 has from all input read instead of reversing it, change or script like this:

 #!/usr/local/bin/csi -ns
 ; This imports the nonstandard procedures read-string
 (import (chicken io))
 ; This makes the sha1 egg procedures available
 (import simple-sha1)
 (display (string->sha1sum (read-string #f)))
 (newline)

So let's see the sha1 hashsum for the string "hello world":

 $ csc sha1.scm
 $ echo -n "hello world" | ./sha1
 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
 $

As you can see it is quite easy to reuse other people's code by using their published extensions. How do I know which procedures simple-sha1 exports? I have checked the documentation.

Finding your way: The documentation

Manual

CHICKEN scheme is documented in mainly two places, one offline and one online: The manual and the wiki. The manual is part of every release tarball and installs HTML versions of the wiki pages locally in $PREFIX/share/chicken/doc/manual/. Point your browser to the index.html file in this directory to get started. The manual is also available online in the CHICKEN wiki. The wiki resides at http://wiki.call-cc.org with the manual being available at /manual The manual covers the usage of the core binaries, the deviations and extensions to the scheme standard and the documentation of the core units.

Wiki and egg index

The wiki also includes documentation for eggs. All eggs are supposed to host their api description there. Also there is a list of available eggs in the egg index at: /egg-index Note that the wiki can be edited by anyone including yourself. Feel free to reword unclear passages or correct spelling errors as you encounter them. The wiki is backed by svn so do not be afraid of breaking anything. Since it is svn you can also do a checkout of the whole wiki and edit it locally in your favourite text editor:

 $ svn co https://code.call-cc.org/svn/wiki wiki
 (user: anonymous, empty password)

Chickadee

The wiki's search function is currently not optimised for searching for suitable procedures. For identifier searches use the chickadee. Chickadee is reachable at http://api.call-cc.org and supports identifier searching as well as regexp searching. Both chickadee and the wiki search the manual as well as egg documentation.

Searching offline: chicken-doc

The database for chickadee can be reused offline by installing the chicken-doc extension. To be able to use chicken-doc install it with chicken-install and download the database:

 $ chicken-install chicken-doc
 $ cd `csi -R 'chicken.platform' -p '(chicken-home)'`
 $ curl http://3e8.org/pub/chicken-doc/chicken-doc-repo.tgz | sudo tar zx

After this you can query chicken-doc for procedures as well as whole module documentation. Calling chicken-doc without arguments will list all possible options as well as usage examples. For our simple-sha1 example we can ask chicken-doc about anything that contains "sha1" in its name:

 $ chicken-doc -m sha1
 (pbkdf2 pbkdf1-sha1)           (pbkdf1-sha1 password salt count dklen #!optional (result-type 'blob))
 (pbkdf2 pbkdf2-hmac-sha1)      (pbkdf2-hmac-sha1 password salt count dklen #!optional (result-type 'blob))
 (sha1)                         sha1 egg
 (sha1 sha1-primitive)          (sha1-primitive)
 (simple-sha1 sha1sum)          (sha1sum filename)
 (simple-sha1)                  simple-sha1 egg
 (simple-sha1 string->sha1sum)  (string->sha1sum str)

So there are two eggs for calculating sha1 hashes: sha1 and simple-sha1. Let's have a look at the egg documentation for the simple-sha1 egg as we only want to convert a string to a hash:

 $ chicken-doc simple-sha1
 [simple-sha1's egg page]

we could have skipped this step and just asked for the description of string->sha1sum:

 $ chicken-doc "string->sha1sum"
 path: (simple-sha1 string->sha1sum)
 
 -- procedure: (string->sha1sum str)
 
 Generates the SHA1 hash for the given string `str`.
 $

The latter tells us that string->sha1sum is part of the simple-sha1 egg (in the "path:" line) and it does what we need for our little script.

The home of bugs: CHICKEN'S bug tracker

CHICKEN scheme uses trac as its bug tracker. It can be reached at http://bugs.call-cc.org. Currently filing a new ticket requires getting a trac account, which we will do happily upon request. Please follow the instructions on /contribute to get one.

Getting help from humans

Searched through the manual, wiki, bugs, and chickadee without finding an answer to your question? Then it might be time to ask a human. Chickenistas can be found online on IRC in #chicken on freenode or if you want to reach more people and have an archived form of your question you can post to one of the mailing lists. These are:

These lists are quite responsive as is the IRC channel. Provided the usual netiquette you will get an answer to your problem almost instantly.

Programming in CHICKEN

Up to now you should be able to find your way around and write simple scripts. There are a couple of hints and tricks scattered throughout the CHICKEN village that try to make programming in CHICKEN scheme even more pleasant. The most requested things are collected here.

Choosing an editor

People in #chicken usually do not engage in the editor wars. Be it notepad, vim, nano or emacs you should choose the one that floats your boat. There are bindings for vim and emacs available that enable auto completion of identifiers, easy integration of the REPL and basic compilation support. As emacs is more popular among schemers the support here is a bit better but in the end it does not matter much. If you are coming from Common Lisp you might enjoy the SLIME egg that provides a SWANK backend for the famous Lisp mode. Another common caveat for new users is the missing line editing support for csi. Here you can either install bindings for readline, linenoise or parley to get line editing support. The installation procedures are covered in the documentation for those eggs.

Building complex projects

Once your application grows you will want to split up your code into separate, independent entities. The CHICKEN way to do so is to write modules. Modules give you means to separate and manipulate namespaces and encourage encapsulation and controlled exposure of your code to the outside world.

Writing your own extensions

If you have modules that may be used by others or you want to be able to deploy those with chicken-install you can wrap them into an egg. An egg can include 1 or more modules and executables. The current infrastructure (known as "the new system" amongst chicken-users) allows you to either include your egg in the svn egg tree (you will need to apply for an account, where "application" means just asking for it) or you can host it in a git, mercurial or fossil repository. If you choose the decentralised version you still need to get an entry into a centralised egg-location file for chicken-install being able to pick it up. Again, this is another matter of asking for it.

Whatever you choose please consider your egg complete only if you provide documentation for it in the wiki. Otherwise people are unable to find information about it neither through chickadee nor chicken-doc.

An egg consists of your source files, and a so called .egg file that handles the compilation of your source files and optionally a test directory including a test suite that will get run by salmonella, CHICKEN's test infrastructure.

Let's suppose you want to write an mp3 decoder. An egg file for it may look like this:

 ((synopsis "Chicken bindings for a mp3 player")
  (category audio)
  (license "LGPL-2.1")
  (author "Eva Lu Ator")
  (components (extension mp3)))

This assumes that all your code resides in a file called mp3.scm. chicken-install will handle all the compiling and installing for you.

And if you want to release your egg as part of the CHICKEN scheme infrastructure you need to add a release-info file that includes version information.

For an example of that see the release information on the wiki.

Build your application as a static binary

Sometimes it is convenient to deploy a static binary as a compilation result. This is what is done in a simple password manager called 'pee'.

Consider pee's egg file: ((synopsis "Pee - a command line password manager.")

(author "Christian Kellermann")
(maintainer "Christian Kellermann")
(category misc)
(license "BSD")
(dependencies srfi-1 srfi-4 srfi-14 srfi-13 stty matchable tweetnacl getopt-long fmt blob-utils)
(components (program pee (linkage static)
                         (csc-options "-C" "--std=c99")
                         (source-dependencies "hash" "tag")
                         (source-dependencies "blake2.h" "blake2s-ref.c"))
                         (component-dependencies crypto-helper))))

See pee's repo for all files.

This will build the application as a static binary and linking all extensions statically to it. Note that for some extensions static building is not supported as the depending foreign libraries do not provide a static library.

Using the test infrastructure

Salmonella, located at http://tests.call-cc.org, will compile your egg every day against the development branch of CHICKEN, giving you hints for API changes in CHICKEN and build problems. You can subscribe to RSS feeds of your eggs to get notifications if your egg suddenly fails to build.

Wrapping up

Now we have reached the end of our tour through the CHICKEN landscape. There have been rough edges and lots of omissions for the sake of clarity and simplicity. I hope you got a good impression of the CHICKEN infrastructure and will try it out on your own during the workshop.

Thanks

I want to thank the fine people from #chicken on Freenode IRC for their corrections and suggestions. Many corrections of the CHICKEN 4 version have been done by John Gabriele.