A guided tour through the CHICKEN scheme republic
- A guided tour through the CHICKEN scheme republic
- What to expect from this tour
- Welcome to CHICKEN scheme
- Installing CHICKEN scheme
- Using CHICKEN
- Programming in CHICKEN
- Wrapping up
- 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
- A compiler that uses C as intermediate language and gcc to compile native code.
- An interpreter that provides a read, eval, print, loop (aka REPL) for rapid prototyping and explorative programming.
- A software package system that allows you to distribute and package software easily: The egg system.
- A wiki for gathering egg documentation, and general advice.
- An API / Identifier search system called chickadee.
- A test suite compiling all available eggs and CHICKEN core on call-cc.org called salmonella.
- A bugtracking system for all extensions and the core library.
- Mailing lists and an IRC channel for asking real people
- Code repositories for the core language and extensions
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:
- chicken: The CHICKEN compiler, called by csc
- csc: The CHICKEN scheme compiler driver
- csi: The CHICKEN scheme interpreter
- chicken-install: For installing CHICKEN scheme eggs
- chicken-status: shows the currently installed eggs
- chicken-uninstall: gets rid of rotten eggs
- chicken-profile: Shows statistics of instrumented CHICKEN code
- chicken-do: An internal build tool for CHICKEN scheme eggs
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:
- Module scheme : Standard Scheme procedures and syntax
- Module r5rs : Standard Scheme procedures and syntax (alias for scheme)
- Module r4rs : Standard procedures and syntax of an old Scheme report
- Module srfi-4 : Homogeneous numeric vector datatypes
- Module (chicken base) : Core procedures and macros
- Module (chicken bitwise) : Bitwise manipulation on integers
- Module (chicken blob) : Unstructured byte data
- Module (chicken condition) : Raising and handling of exceptions, manipulation of condition objects
- Module (chicken continuation) : Feeley's "a better API for continuations"
- Module (chicken eval) : Evaluation hooks
- Module (chicken file) : High-level API for file system manipulations
- Module (chicken file posix) : POSIX-specific file manipulations
- Module (chicken fixnum) : Operations on "fixnums" (small integers)
- Module (chicken flonum) : Operations on "flonums" (floating-point numbers)
- Module (chicken foreign) : Accessing C and C++ code and data
- Module (chicken format) : String formatting procedures
- Module (chicken io) : Reading and writing to files and other ports
- Module (chicken irregex) : Regular expressions
- Module (chicken keyword) : Operations on keyword objects
- Module (chicken load) : Loading code from files
- Module (chicken pathname) : Manipulating path names
- Module (chicken platform) : Information about the platform your code is running on
- Module (chicken port) : Manipulating port objects
- Module (chicken pretty-print) : Pretty-printing s-expressions
- Module (chicken process) : Starting subprocesses and communicating with them
- Module (chicken process signal) : Sending and receiving POSIX process signals
- Module (chicken random) : Generating pseudo-random number
- Module (chicken read-syntax) : Creating syntactic extensions to the reader
- Module (chicken repl) : Creating a Read-Eval-Print Loop
- Module (chicken sort) : Sorting lists and vectors
- Module (chicken string) : String operations
- Module (chicken syntax) : Creating syntactic extensions (macros)
- Module (chicken tcp) : Connecting over the network via TCP
- Module (chicken time) : Fetching information about the current time
- Module (chicken time posix) : Manipulating POSIX time
- Module (chicken type) : Defining and using static typing information
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:
- chicken-users: For all general questions about the usage of CHICKEN scheme. If in doubt post to this list.
- chicken-hackers: For all questions about the implementation of scheme in CHICKEN
- chicken-janitors: The bug tracking list which will post all changes to the bug tracking system. Subscribe here if you are interested in CHICKEN's bugs and the handling of those
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.