How to run Cozenage¶
Cozenage provides both a file runner for evaluating code in external files, and a fully-featured interactive REPL which allows for experimentation and quick discovery. These two methods of running Cozenage will be treated in order, after a short introduction to command-line flags which affect the operation of both.
Cozenage command line flags¶
-hand--helpDisplay short usage details to the screen, ie: print the information we are discussing here.
-Vand--versionPrint the version number of the currently installed Cozenage binary, and print when it was compiled.
-land--libraryPreload Scheme and/or Cozenage libraries at startup. Accepts a mandatory comma-delimited list of libraries to load. This is a convenience flag which is identical to manually loading libraries using the
(import (scheme foo))syntax. Valid arguments to this flag are:bits,cxr,file,math,random,system, andtime.
Using the file runner¶
To evaluate code in an external file, simply pass the filename as argument on the command line:
$ cozenage file.scm
By convention, Scheme source files typically use scm or ss suffixes. Cozenage will print a warning to the
standard error stream when it detects a file without one of these two suffixes, but will attempt to run the file
anyway. Cozenage will only run one external file at a time. If you want to run multiple unrelated files in sequential
order, use your shell’s facilities for this:
$ cozenage file1.scm && cozenage file2.scm && cozenage file3.scm
Or perhaps more idiomatically:
$ for file in file1.scm file2.scm file3.scm; do
cozenage ${file}
done
If you want to load definitions from one or more files for use in a final script, you can use the (load) procedure.
In your script file:
(load "file1.scm")
(load "file2.scm")
(load "file3.scm")
;;; ...and the rest of the script...
And now these definitions are available when you run the script:
$ cozenage script.scm
You can use the -l or --library flag as a convenience to pre-load libraries:
$ cozenage -l file,system script.scm
This is functionally equivalent to adding (import) expressions at the top of your scheme source file:
(import (scheme file))
(import (scheme system))
;;; etc
Tip
Other than printing runtime errors to the standard error stream, file runner mode does not generate
any output that is not explicitly generated by the code in the Scheme file itself. Success or failure
of the run can be determined by inspecting the output of echo $?.
You can pass flags and arguments to the Scheme file you are running and these will be made available through the
(command-line) procedure which returns them as a list of strings. As an example, let’s say we have these
definitions in a file:
(write (command-line))
(newline)
Notice the results of running the file, given this invocation:
$ cozenage cli.scm -- --foo --bar --baz somefile.txt
("cli.scm" "--foo" "--bar" "--baz" "somefile.txt")
Note in particular, that you have to explicitly add ‘--’ AFTER the Scheme file name so that getopt() knows to
stop parsing the arguments as args to Cozenage itself, and ensure they are interpreted as flags and arguments to the
Scheme file.
Using the REPL¶
Most modern interpreted languages provide a REPL for interactive use. The idea of a REPL was first described by John McCarthy, the inventor of the original LISP language in his 1960 paper named “Recursive functions of symbolic expressions and their computation by machine”. The interactive loop he described is the direct ancestor of every REPL that exists today.
REPLs are a very powerful tool which allow for interactive ‘conversations’ with the interpreter, in order to experiment and try out various code expressions without the overhead of the edit-compile-test workflow required with most compiled languages.
Running Cozenage with no file arguments will start the program in REPL mode:
$ cozenage
Cozenage version 0.8.9
Press <Ctrl+d> or type 'exit' to quit
-->
The ‘-->’ is the cozenage prompt, at which you can type in Scheme expressions to be immediately evaluated when you press enter. The REPL also provides multiline input using a simple heuristic that tracks if the parentheses are balanced. If there are more left parentheses than right parentheses in the current expression, pressing enter will continue on to the next line and print a secondary prompt: ‘…’.
--> (+ 2 4)
6
--> (define (fact n)
... (if (= n 1) 1
... (* n (fact (- n 1)))))
<lambda 'fact'>
--> (fact 5)
120
-->
Note that you can type multiple expressions in a single line, and they will be evaluated in sequence:
--> (import (scheme write))
#true
--> (display "Hello, World!") (newline)
"Hello, World!"
-->
Whether Cozenage was built with GNU readline, or the *BSD and macOS provided libedit, a history of expressions typed into the prompt will be generated, and can be accessed and cycled through using the up and down arrows. This history is also written to a file for persistence between runs of the REPL. Currently, the file is written to ~/.cozenage_history, but at some point the history file name and location will become a configurable option.
Libedit provides rudimentary tab-completion, but this will only work for filepaths.
If built with GNU Readline, this file path tab-completion is available, but Cozenage will also provide extended tab completion for all defined procedures and special forms at startup. Simply type in the first few characters of the desired name. If there is no ambiguity, the rest of the name will be auto-completed at the prompt immediately upon pressing the tab key. If there are multiple possible completions, pressing the tab key a second time will display the options to the screen.
--> (def[tab]ine ;;; The REPL auto-completes the 'define' special form
--> (make-[tab][tab]
make-bytevector make-list make-string make-vector
--> (make-b[tab]ytevector
To exit the REPL, type <Ctrl-D>, or simply type ‘exit’ at the prompt and press enter.