Sixx Scheme 1.0 リファレンス

Sixx Scheme の Sixx は Scheme In XX (20) kb の略で、それから分かるように非常に小さな Scheme 処理系である (実際には 20KB は越えているが、30KB よりは小さい。携帯 Java で動くかどうかは知らないが、移植するとしてもかなり容易であろうと思う)。R4RS のサブセット (JScheme から拾ってきた r4rstest.scm で、大文字小文字の部分以外はすべてクリア。その部分も、同じく大文字小文字を区別する R6RS が同じ値なので意味的にはクリア。なお、もちろんだが R5RS や R6RS に由来する部分はこれではテストされない。とりあえずこれをクリアするためにあちこちパッチ当てしたので現状 30KB をちょっと超えてしまったが、そのうちにまた 20KB 台に戻せるものと思う) だが、JVM 上の素直な処理系なので日本語も通る (サロゲートペアにも対応)。また、JVM 系では珍しく、継続渡しスタイルの実装であるため完全な継続をサポートしている (たぶん; まだ未テスト)。速度は速くはないが、この小ささでは我慢できるほどではある (簡易な作りだが、一応独自 VM 持ちのバイトコードインタプリタではある。ガベージコレクションは完全に Java 任せだが)。オリジナルはしかし、残念ながらほかのアプリへの組み込み用途を念頭に作られているらしく、インタプリタとして使うには common フォルダにある SixxMain.class を jar に放り込んで examples フォルダにある repl.scm を呼び出さなくてはならない。そこで、java -jar sixx.jar だけでインタプリタとして動くようにし、またけっこうな改良を加えた版を作った (バイナリソース)。オリジナルははっきり言ってバージョン番号すら付いてないほどのいわば草稿レベルなので、以降そちらを無印、私による改良版を 1.0 と呼びたい (以降の記述は、無印には当てはまらないものもいくつかある。なお、先の r4rstest.scm をクリアするためにけっこうあちこち改良を要した、つまり、無印は R4RS に必ずしも準拠していない)。ちなみに無印は MIT ライセンスで、1.0 もそれに準じる。なお、携帯なども含めて可能な限りマルチプラットフォームでかつ組み込み用でもあることを念頭に置き、今以上に本体を拡張する意図はまったくない (本体に改変を加えるとすれば、それはバグフィックスか、さらなる高速化・最小化目的のみである)。これ以上の拡張は、Sixx Scheme に準拠して記述されたライブラリスクリプトの形になるだろう。

以降の記述では、角括弧は省略可能であること、... は複数個可能であることを示す。

起動

java -jar sixx-バージョン番号.jar [[オプション] | [ファイル名]] ... [-- 引数 ...]


オプション

-e S式 : 単一の S式 を評価して結果を標準出力に書き出す

-- : これより後ろの引数をすべて argv に格納

-i : 対話モードをオンにする (すべてのファイル名および -e より後で指定しないと無意味)

-help : オプション一覧を表示して終了

-? : 同上

-version : バージョンを表示して終了

オプションもファイル名もない場合は対話モードで起動する。ファイル名か -e が指定された場合は、-i をさらに指定しない限りそれらを実行後に終了する。ファイル名は複数指定可能である。これらにより、-i の前にあえてファイル名を記述することで、それを設定ファイルとすることができる (各 -e と各ファイルは対話環境と同一の名前空間で評価されるので、定義などは蓄積される)。

R4RS との相違

すでに書いたように、Sixx Scheme は R4RS のサブセットなので、言語仕様の詳細はそちらに譲り、ここでは相違点のみを記す。なお、R4RS を想定した Scheme 入門へのリンクもついでに貼っておく (文字化けする場合はエンコーディングに EUC-JP を選ぶ。私の方では化けるのは表紙だけなので、contents の方にリンクを貼っておくとよいだろう)。

語句

スクリプトは UTF-8 で記述すること。

識別子

* 大文字小文字は区別される。R4RS の言語仕様からは重大な違反だが、R6RS で結局区別するようになったように、その方がより一般的ではある。

* " ; 空白系 以外の表示可能文字は、ほかのリテラルとして解釈されない限り、語頭も含め、Unicode のどの文字でも使用できる。これはどちらかと言えば手抜き実装の副産物だが、少なくとも ASCII 系文字では、R4RS 言語仕様で可能とされるもの以外は決してお勧めしない。

* 構文キーワードは再定義可能である。ただし、R5RS の言語仕様による規定とは異なり、実際に再定義した際の挙動は保証されない。

コメント

* #; : 式コメント (SRFI-62、R6RS)。続く S式 をコメントアウトする。

* #| |# : ブロックコメント (SRFI-30、R6RS)。両者に挟まれた部分をコメントアウトする。入れ子可。

これらは、デバッグ時に非常に便利なので導入された (と言うかそのまま残した。無印からある機能である)。


* ファイル先頭の #! で始まる行 : Unix 系シェルスクリプトの起動用コメントである。

* ファイル先頭の :: で始まる行から次の :: で始まる行まで : Windows のバッチファイルのコメントである。

前者は

#!/usr/bin/env sixx
;; sixx は sh で記述された起動用のシェルスクリプト
(display "Hello world!")
(newline)

後者は

::
@echo off
call sixx "%~f0" -- %*
exit /b
::
;; sixx は sixx.bat という名前の起動用バッチファイル
(display "Hello, world!")
;(newline)
; こちらは最後の (newline) は不要

のように用いる ("%~f0" の部分は Windows の各版でころころ変わっているようなので注意。例の場合は XP の cmd.exe のそれで、このスクリプトファイル自体の名前をフルパスで展開する意味である)。

数値リテラル

* 数は fixnum (Java の int) と flonum (Java の double) のみ実装している。

* #e #i は実装していない。

* flonum は Java のリテラル表記のみ可能である。すなわち、接尾辞 s と l、分数表記と複素数表記には対応していない (数値として解釈できない文字を含むので、それらは識別子扱いとなることに注意)。またこのため、number? complex? rational? は real? の単なる別名となっている。

* fixnum のオーバーフローとアンダーフローは flonum に自動変換される。これは、リテラルからオブジェクトが生成される場合も同様である。後者は無印にもあるものだが、前者は 1.0 で導入され、そしてその分速度が無印より遅くなっている。

文字列リテラル

* "\ の前以外の \\\ と見なされる。これは、正規表現を考慮しての措置である。

Scheme と Java の型対応

Scheme -> Java

exact -> Integer

inexact -> Double

character -> sixx.CodePoint

string -> int[]

symbol -> String

vector -> Object[]

#t -> Boolean.TRUE

#f -> Boolean.FALSE

() -> null

pair -> sixx.Pair

Scheme の string が Java の int[] になるのは、(R5RS までの) Scheme では文字列が書き換え可能であることに対応する割り当てである。これと文字型の対応クラス名から分かるように、内部的には UTF-32 (Unicode コードポイント) で取り扱われ、むろんサロゲートペアにも対応している (なお、この理由から 1.0 は Java 1.5 以上用である)。ただし、Windows ではコマンドプロンプトを始め基本ソフト自体もまだ未対応なものが多いためかサロゲートペアはどうもうまく扱えないようで、現状では、普通のコンソールでのサロゲートペア対応は Linux でのみ保証可能ではある。それで、サロゲートペアにも対応する UTF-8 な Sixx 専用 GUI コンソールを作成しつつある(バイナリソース)。まだ未完成だが (不要なファイルも含んでいる、等)、基本部分が一応使える程度には成ったので公開しておこうと思う (ただし Windows では要「-Dfile.encoding=UTF-8」指定。なお、これによりデフォルトエンコーディングが UTF-8 となることに注意。このオプションは Java のバージョンによっては使えたり使えなかったりする不安定なものだが、エンコーディングが起動時にしか指定できない System.in を内部的に JTextField へパイプしている関係上、現状ではほかに解決策はない模様)。Scame という名前は、Emacs の逆読みで、いくつかある Emacs 系 Scheme ベースエディタが「Emacs + Scheme」を目指しているのに対し、「Scheme ベースの Emacs 風エディタ」すなわち「Elisp との互換性は放棄して純粋に on Scheme であり、かつまたそのミニマリズムを体現するエディタ」をひそかに目論んでおり、この GUI はそのいわば橋頭堡としてこそ開発されたことに由来する (ただし、その成就は未定の未来の話で、今回は Sixx 専用 GUI コンソールに留まる)。使い方は一目瞭然だと思うが、下の一行エリア (上下矢印による履歴機能あり) に入力すれば上のスクロールエリア (コピーは可) に結果が表示される。また、Sixx Scheme 側からの標準入力呼び出しも同じく一行エリアを用いて入力を求める形になる。あと、むろん XP の場合は JIS2004 フォントの事前インストールが必要である。また Linux 版 Java の場合も、Swing 上でサロゲートペアを利用するには、ここ等を参考に (Debian の場合は /usr/share/fonts/japanese/TrueType/ ではなく /usr/share/fonts/truetype/) JIS2004 対応の IPA フォントを導入しておく必要がある。

ライブラリ

基本ライブラリは sixx で、これは初期化作業用の sixx-underground から公開されるべきでない名前を隠したものである。組み込み用に R4RS で規定された名前だけから成る r4rs ライブラリも用意されているが、対話環境でこれに切り替えると、その規定にないライブラリ切り替えや終了の手続きが隠されてしまうので切り替えないように。ただし、最後の脱出手段として ##sixx と打ち込めば選択ライブラリを sixx に戻すことができる (repl.scm の方で実装されている機能)。またさらに、セキュリティを考慮して、R4RS から入出力関連を外した r4rs-without-ports も用意しておいた。

R4RS にあって Sixx にない手続き

numerator

denominator

この 2 つは分数表記用のものなので実装されていない。


angle

make-polar

make-rectangular

magnitude

real-part

imag-part

これらは複素数用のものなので実装されていない。


transcript-off

transcript-on

これらはまったくと言ってよいほど使われないので実装されていない。

R4RS の手続きの拡張

current-input-port

current-output-port

これらは後述する仮変数で実装されており、すなわち省略可能な引数として新たなポートを設定できる。

open-input-file

open-output-file

with-input-from-file

with-output-from-file

call-with-imput-file

call-with-output-file

これらでは、省略可能な追加引数として、エンコーディングが文字列で指定可能である。使用可能なエンコーディング名は Java に準じる。

R5RS から

以下で、「ボディ」は、一つ以上の連続する S式 である (定義の S式 も可)。最後の S式 の値がそのボディの値である。

(eval S式 ライブラリ)

ライブラリはオブジェクトでもシンボルでも可。そのライブラリの名前空間で S式 を評価しその結果を返す。

(values 何か ...)

自身の引数を自己の継続へ渡す。その継続が多値に対応していない場合は最初の引数だけが渡され、ほかは捨てられる。普通は次の call-with-values と組み合わせて使う。

(call-with-values 多値生成手続き 多値受容手続き)

無引数で多値生成手続きを呼び出し、それが返す値 (単一値でもよい) を引数に多値受容手続きを呼び出す。

(interaction-environment)

Sixx では、(current-library) の別名にすぎない。

R6RS から

(call/cc)

call-with-current-continuation の略名。昔から一般的にあったが、R6RS で正式に言語仕様に取り込まれた。

(letrec* ((変数 初期値) ...) ボディ)

letrec と同様だが、変数初期化の順が左から右であることが定まっているもの。このため、右 (後ろ) の方の変数の初期化式中に左 (前) の方の変数が使用できる。

(when テスト ボディ)

(if テスト (begin ボディ)) と同じ。

(unless テスト ボディ)

(if テスト (unspecified) ボディ) と同じ。

(open-string-input-port 文字列)

文字列を普通の入出力の入力と同様に read-char などで参照できるようにするためのもの。

(fxand 整数 ...)

二進表現において、最初の整数の 1 である桁が続く引数の同じ桁でも 1 なら 1、それ以外は 0 となる値を返す。不要なビットをオフにするためによく使われる。Java の基本ライブラリではけっこうビット単位のフラグが使われており、これらビット演算はおそらくはそのための導入と思われる。

(fxior 整数 ...)

二進表現において、最初の整数と続く引数の同じ桁でどちらか (または両方とも) が 1 なら 1、それ以外は 0 となる値を返す (i は inclusive で「包含的」すなわち「一方がそれなら必ずそれになる」の意味)。ビット単位のフラグをオンにするためによく使われる。

(fxxor 整数 ...)

二進表現において、最初の整数と続く引数の同じ桁が異なる値なら 1、それ以外は 0 となる値を返す。ビット単位のフラグをトグルするためによく使われる。また、同じ整数同士の結果は必ず 0 になるため、マシン語レベルで 0 に初期化するために常用される演算である (たいていのマシン語ではメモリアクセスを要せず命令一つで済むため高速)。

(fxnot 整数)

二進表現において、その整数のすべてのビットが反転した値を返す。一般的に、この値はその整数の絶対値に 1 を足して符号を反転させた値に等しい (負数をいかに表現するかに依拠するため、システムによっては異なる値となり得る)。

SRFI-39 から

(make-parameter 初期値 [セッタ手続き])

仮変数 (パラメータとも言う) となる手続きを返す。その手続きが無引数で呼び出されると現在保持している値を返し、単一引数で呼び出されるとその値を以降保持する。セッタ手続きはその値を引数として受け取り、特別なチェックや加工を行うためのものである。この仮変数により、参照されるたびに値が改めて評価される動的変数が Scheme に導入される。Sixx では、current-library などで利用するための導入であり、その意味で不要な SRFI-39 のもう一つの名前は実装されていない (Sixx における、R5RS までの実装選択はサイズの問題だが、R6RS とその他の実装選択はすべてこの理由、すなわち Sixx 自体に必要だったから、によっている)。

SRFI-69 から

Sixx のライブラリにおいて識別子の管理に java.util.Hashtable を利用しており、それへの Scheme 側からのアクセスを容易にするための導入である。Gauche のものとはちょっと、R6RS のものとはいろいろと異なるので注意されたい。

(make-hash-table)

無引数のみである点ではサブセット。Java の new Hashtable() (無引数) と同じ。

(hash-table?)

java.util.Hashtable のインスタンスなら #t。

(hash-table-ref ハッシュテーブル キー)

そのキーに呼応する値を返す。キーがそのハッシュテーブルにない場合は空リストを返す。

(hash-table-ref/default ハッシュテーブル キー [デフォルト値])

hash-table-ref と同様だが、キーがそのハッシュテーブルになくてデフォルト値が指定されている場合はそのデフォルト値を返す。なお、SRFI-39 ではデフォルト値の省略はできない。

(hash-table-set! ハッシュテーブル キー 値)

そのキーでその値をハッシュテーブルに登録する。そのキーの古い値 (キーがなかった場合は空リスト) を返す。SRFI-39 を始め、set! 系の暗黙の規定に従い未定義値を返すタイプの方が普通であることに注意。また、値が空リストである場合、Scheme 側からは空リストとして出し入れできるが、Java 側での実体は new sixx.Pair(Boolean.FALSE, Boolean.FALSE) で生成されるオブジェクト ((#f . #f) のペア) となっていることに注意。これは、Java の Hashtable が空リストの実体である null 値を受け付けないためである。なお、キー側でも、int の配列は Java 側では sixx.CharArray というクラスにラップされる形になっている (Java 1.5 より前の java.util.HashTable にあった制約の名残り)。

(hash-table-delete! ハッシュテーブル キー)

ハッシュテーブルからそのキー (と呼応する値も) を削除してその値を返す。こちらも SRFI-39 を始め、未定義値を返す方がより暗黙の規定に一貫的ではある。

(hash-table-exists? ハッシュテーブル キー)

そのキーがハッシュテーブルにあれば #t を返す。

(hash-table-keys ハッシュテーブル)

ハッシュテーブルが持つキーすべてから成るリストを返す。

(hash-table-values ハッシュテーブル)

ハッシュテーブルが持つ値すべてから成るリストを返す。


次の二つは Sixx による拡張。

(hash-table-for-each ハッシュテーブル 手続き)

手続きの引数はキーと対応する値の二つ。

(hash-table-map ハッシュテーブル 手続き)

手続きの引数はキーと対応する値の二つ。

Sixx による拡張

(unspecified)

識別子が未定義、すなわち束縛されていない場合に返す値を返す。シンボル unspecified 自体の再定義は手続きでのみできるが (手続き以外で再定義しようとするとクラッシュ)、未定義値が返される状況では本来の未定義値を返す。

(library 名前 エクスポートリスト インポートリスト ボディ)

その名前のライブラリを定義する。R6RS のそれとはあちらこちら違っているので注意されたい。

静的スコープからは逸脱するが、ライブラリ内のボディからはそのライブラリに登録されている名前しか見えない。つまり、このライブラリ定義を囲む名前空間 (別のライブラリ) にはアクセスできない。ライブラリごとに異なる名前空間となるので、このライブラリ定義がなされる現在のライブラリとは互いに疎通がないのである。

名前には名前のリストも可。

エクスポートリストは (export 識別子 ...) の形で、ほかのライブラリによってインポートされた際にそこへ登録される識別子を指定する。この識別子はインポートリストでほかのライブラリから暗黙にこのライブラリに登録されたものでもかまわない。なお、実装の手抜きでこのリストの最初の要素は単に無視されるだけだが、やはり export を使うのが無難であろうと思う。

インポートリストは (import ライブラリ名識別子 ...) の形で指定する。どの識別子を取り込むかの制御は、取り込まれる側のライブラリのエクスポートリストでしか行えない。なお、実装の手抜きでこのリストの最初の要素は単に無視されるだけだが、やはり import を使うのが無難であろうと思う。

ボディは、いわゆるトップレベルである (プログラムのトップレベルも、実際には sixx ライブラリ内のトップレベルである)。省略はできないが、在りさえすれば '() や #f だけでもよい。

ライブラリ内のボディでは、(current-library) はそのライブラリ自身を返す。

(current-library [ライブラリ])

ライブラリはオブジェクトでもシンボルでも可。現在選択されているライブラリを指定のものに変更する。省略時は現在選択されているライブラリオブジェクトを返す。

(define-macro (名前 引数 ...) ボディ)

マクロを定義する。用法はこちらを参照のこと。なお、(define-macro 名前 (lambda (引数 ...) ボディ)) の方の形式は Sixx では実装されていないので、上の形に直す必要がある。

(gensym)

まだ使われていない任意のシンボルを生成する。具体的用法は define-macro のそれを参照のこと。

(interpreter)

sixx.Sixx のインスタンスである現在のインタプリタ自身を返す。

argv

コマンドライン引数から成る文字列のリスト。

(debug 値)

対話環境でない状況で、対話環境の応答と同様のものを表示させるためのもの。値自身を返す。

Sixx による拡張: Java とのインタフェース

ここで、「クラス」、「メソッド」、「フィールド」、「引数型」および「要素型」は、Java でのそれらの名称から成る文字列である。クラス名の場合は、パッケージもすべて記述しなければならない。引数や要素が配列の場合は、java.lang.Class.getName() における方法論に準じる。すなわち:

* 先頭の [ で配列であることを示し、その個数で次元数を示す。

* 続けて、要素が boolean なら Z、byte なら B、char なら C、short なら S、int なら I、long なら L、float なら F、double なら D を続ける。または、要素がオブジェクトなら Lクラス名 とする (この場合のクラス名も、要パッケージ全記述である)。

すなわち、int[][] は "[[I"、String[] は "[Ljava.lang.String" と表記する。

(make-array 要素型 リスト)

リストの各要素で初期化された、要素型の配列を返す。一見ベクタだが、ほかの型の値は受けつけない点でベクタとは異なる (ただし、vector? では #t を返す)。Sixx の文字列は int の配列で Java の文字列と型が異なること、またこのために int の配列は Sixx Scheme 側では読み書きにおいて文字列と見なされてしまうこと、に注意。

(class クラス)

そのクラスを指す java.lang.Class のインスタンスを返す。ちなみに任意のクラスのインスタンスから java.lang.Class のインスタンスを得るには、((method "java.lang.Object" "getClass") 何か) とすればよい (デフォルトでは定義されていない)。

(constructor クラス [引数型 ...])

そのクラスの、その引数型をシグネチャとするコンストラクタをラップする sixx.Procedure のインスタンスを返す。そのコンストラクタインスタンスの呼び出し方は Scheme の普通の手続きと同様である。

(method クラス メソッド [引数型 ...])

そのクラスの、その引数型をシグネチャとするメソッドをラップする sixx.Procedure のインスタンスを返す。そのメソッドインスタンスを呼び出す際は、スタティックメソッドなら Scheme の普通の手続きのように引数を与えるだけでよいが、インスタンスメソッドの場合は引数の前にそのクラスのインスタンスを置かなければならない。

(field クラス フィールド)

そのクラスのそのフィールドをラップする sixx.Procedure のインスタンスを返す。そのフィールドインスタンスをフィールド参照のために呼び出す際は、スタティックフィールドなら無引数、インスタンスフィールドならそのクラスのインスタンスを引数とする。代入の場合は、スタティックフィールドなら新しい値、インスタンスフィールドならそのクラスのインスタンスと新しい値を引数とする。

(make-type-predicate クラス)

単一引数がそのクラスかどうかを判定する手続きを返す。

(thread サンク)

そのサンクを内容とする sixx.SixxThread のインスタンスを返す。

(synchronized 何か 手続き)

Java の synchronized で「何か」をロックした状態でその無引数の手続きを評価する。

(throw 例外)

例外は Java.lang.Exception 系のインスタンスでなければならない。その例外を投げる。

(try-catch-finally トライ キャッチ ファイナリ)

トライ、キャッチ、ファイナリはいずれも手続きである。トライとファイナリは無引数で、キャッチはキャッチされた例外を引数に取る。キャッチとファイナリは、不要な場合は #f とする (省略は不可)。トライを評価中に例外が投げられたらそれを引数にキャッチが評価され、またその例外の有無にかかわらず、最後に必ずファイナリが評価される。

(error メッセージ [引数 ...])

そのメッセージと引数を表示してから例外を投げる。表示のエンコーディングはデフォルトのそれである (エラーを発行するような状況でのエンコーディング変換は危険なので、指定可能にする予定はない)。

(jbyte 数値)

数値を Java の byte の数値に変換する。ビット表現で byte を超える桁部分は単純に切り捨てられる (Java の強制キャストと同じ)。

(jfloat 数値)

数値を Java の float の数値に変換する。ビット表現で float を超える桁部分は単純に切り捨てられる (Java の強制キャストと同じ)。

(jstring 文字列)

Sixx の文字列と同じ内容の Java の文字列を返す。

(jchar 文字列)

Sixx の文字と同じ内容の Java の文字 (ただし int) を返す。

1.0 の作り手による拡張

見て分かるように、ほぼ対話環境用の追加が主である。

(exit [終了コード])

Java の System.exit() を呼び出す。終了コード省略時は 0 と見なされる。

(sixx-libraries)

ライブラリが登録されているハッシュテーブルを返す。

(current-library-name)

現在選択されているライブラリの名前を返す。

(symbols-in-library ライブラリ)

ライブラリはオブジェクトでもシンボルでも可。そのライブラリに登録されている識別子 (マクロ識別子は含まない) のリストを返す。

(macros-in-library ライブラリ)

ライブラリはオブジェクトでもシンボルでも可。そのライブラリに登録されているマクロ識別子のリストを返す。

(expand-macro 'マクロ式)

マクロ式を展開したものを返す。マクロのネストには未対応の簡易版。

(show-value 識別子)

「識別子名 : その値」を標準出力に表示してそのその値を返す。

(time ボディ)

ボディの実行に要した時間を表示する。

組み込みスクリプトエンジンとして使う

組み込みスクリプトエンジンとして使う場合は、SixxMain.class と repl.scm は不要なので jar から取り除いても問題はない (3KB 小さくなる程度だが)。ソースの方での ant javadoc で (詳細はまだほとんど書かれていないが) API ドキュメントを得ることができる。なお、サイズの問題から、既存の標準 API に準拠する予定はまったくない。

どう使うにせよ、まずは Sixx の VM を起動する必要がある。

sixx.Sixx vm = new sixx.Sixx();
sixx.Library r4rs = vm.getLib("r4rs");

スクリプトファイルを評価する場合は

vm.loadFromJar(ファイル名文字列, r4rs);

loadFromJar() は該当するファイルをまず自身の jar 内から (先頭に / をつけて) 探し、なければ外部から探す (この場合は先頭に / を加えない)。ハナから外部から探す場合は load(java.io.InputStream) を使う (java.io.Reader 系でないのは、環境のデフォルトコードを無視して UTF-8 エンコーディングを強制するため)。

S式 を内容とするソース文字列を評価する場合は

vm.load(ソース文字列, r4rs);

Sixx の手続きを直接利用する場合は

// 手続き名に呼応する sixx.Procedure インスタンスを得る
Object write = vm.eval("write", r4rs);
Object newline = vm.eval("newline", r4rs);

// vm.apply(手続き, 引数から成る Sixx のリスト)
// sixx.Pair(car, cdr)
// Sixx のリストは sixx.Pair のデイジー・チェーン
vm.apply(write, new sixx.Pair("symbol", null));
vm.apply(newline, null);

vm.apply(write, new sixx.Pair(sixx.CharArray.toInts("string"), null));
vm.apply(newline, null);

これは、次の Scheme コードと同じである。

(write 'symbol)
(newline)
(write "string")
(newline)