"Roswell Script" is implementation-independent Common Lisp scripting program which uses Roswell. Although Roswell itself is a unified interface to Common Lisp implementations, it also encourages writing scripts with it.
To start writing it, run ros init
in your terminal:
$ ros init
Usage: ros init [template] name [options...]
$ ros init fact
Successfully generated: fact.ros
It adds a file extension .ros
.
Perhaps it's hardly understandable if you have been using only Unix OSes for years like me. Actually, it works well even without .ros
on Unix, so renaming it to the name which doesn't have .ros
is a usual manner if the script doesn't have to run on Windows. However, it helps Roswell to differentiate it from shell scripts, and Roswell provides some additional features for it like Making Executables.
The content of the file looks like this:
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(defun main (&rest argv)
(declare (ignorable argv)))
This looks a little bit hacky. It actually is a shell script which exec
Roswell immediately. Roswell runs the same script, skips multi-line comments, reads the rest of the file as a Common Lisp program, and finally invokes a function main
with command-line arguments.
Here's an example program which takes the exact one argument and prints its factorial:
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(defun fact (n)
(if (zerop n)
1
(* n (fact (1- n)))))
(defun main (n &rest argv)
(declare (ignore argv))
(format t "~&Factorial ~D = ~D~%" n (fact (parse-integer n))))
$ fact.ros 3
Factorial 3 = 6
$ fact.ros 10
Factorial 10 = 3628800
Though it falls through CL debugger if there's no arguments or non-integer value, I assume it's okay for now as a simple example ;)
Hey! It's a script. And Common Lisp is pretty fast programming language like C, right?
Well, unfortunately, when scripting in Common Lisp, you have to face its startup time.
$ time fact.ros 10
Factorial 10 = 3628800
fact.ros 10 0.74s user 0.21s system 95% cpu 0.994 total
This very simple program took 0.74s to print the answer. Considering that all Common Lispers can easily compute the factorial of 10 in less than 1 sec, it runs unbearably slow to help us anyway.
One easy solution is skipping loading Quicklisp, as it doesn't require it.
Replace -Q
flag by +Q
in the ros
command:
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros +Q -- $0 "$@"
|#
...
Retry time
command to see how it worked:
$ time fact.ros 10
Factorial 10 = 3628800
fact.ros 10 0.57s user 0.19s system 97% cpu 0.780 total
It's a little bit better.
Roswell also provides a command to convert a script into an executable, ros build
:
$ ros build fact.ros
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into fact:
writing 4976 bytes from the read-only space at 0x20000000
writing 3168 bytes from the static space at 0x20100000
writing 52330496 bytes from the dynamic space at 0x1000000000
done]
An executable version is generated at fact
. If your script doesn't have a file extension .ros
, Roswell overrides your file and the behaviour is unknown.
Try time
for the executable:
$ time fact 10
Factorial 10 = 3628800
fact 10 0.00s user 0.02s system 96% cpu 0.024 total
Well, is it fast enough now? :)
When you write a script which would make other people happy, think about distributing it.
The easiest way to do it is, just sending the .ros
file to others. But, it's hard if your script is more like a "library", so too big to put all stuff into a single file.
Or, if you're a library author, you may think of providing a command-line interface to it.
ros install
would be a solution for it. It's known as a command for installing Common Lisp implementation, however,it is also a command for installing Common Lisp libraries.
$ ros install <library name>
It downloads the specified library from Quicklisp, and it installs bundled Roswell scripts if there's any.
For instance, try ros install clack
:
$ ros install clack
found system clack.
Attempting install scripts...
/Users/nitro_idiot/.roswell/bin/clackup
It copies script files which located the roswell/
directory of the library into ~/.roswell/bin
and gives an executable flag to them.
Don't forget to add ~/.roswell/bin
to $PATH
to use those scripts:
$ echo "export PATH=\"\$HOME/.roswell/bin:\$PATH\"" >> ~/.zshrc
Here're libraries bundling Roswell scripts.