Common Lispのプロジェクトって何?

以前のエントリーでsqlite3を取り上げる予定だと書いたが、まだそこまでのレベルに到達していない。もっと基本的なことを書く。
まず、Common Lispのプロジェクトを作成するためにはcl-projectを使うのが便利。Ruby on Railsのscaffoldと同じ。

しかし待ってほしい。そもそもプロジェクトって何だろう?

とにかくプロジェクトを作成してみる

まずは作る。基本的には以前のエントリーで作成したCaveman2用のプロジェクト作成と同じだが、以下に例示しておく。
プロジェクトの名前を「myapp2」とする。

$ cd ~/work/sbcl  # 場所はお好みで。
$ ros run
(ここからはSBCL内。先頭の*はプロンプト。)
* (ql:quickload :cl-project)
* (cl-project:make-project #P"myapp2" :author "kitemw")  ; "myapp2"と"kitemw"はお好みで。
(CTRL+DでSBCLを終了)

これで、以下のようなディレクトリの中にファイルが作成される。

$ tree myapp2
myapp2
|-- README.markdown
|-- README.org
|-- myapp2-test.asd
|-- myapp2.asd
|-- src
|   `-- myapp2.lisp
`-- tests
    `-- myapp2.lisp

2 directories, 6 files

作成したけどそのあとは?

cl-projectで作成したファイルだけでは、実は何もできない。ただ骨組みを作っただけ。
そもそもプロジェクトでできることと言ったら?やろうと思えば何でもできるのだが、

  • スタンドアロンで、ファイルを読み、計算し、ファイルや画面に結果を出力するプログラム … 可能。メインルーチンを含むエントリーファイルを追加する。
  • ライブラリとして動作するプログラム。すなわち他のプログラムから値をもらい、計算し、元のプログラムに結果を返すプログラム … 可能。

さて何をするか。当面の目的としてフィボナッチ数列を計算するプログラムでも作ってみますか?
では今回はスタンドアロンで動作するプログラムを書いてみる。ライブラリ作成は今回やらない。
上で作成したmyapp2プロジェクトを使うことを考えてみる。これのどこをどうすればよいかについては、だいたい次のような感じで作成していく。

  1. メインルーチン … 新しくエントリーファイルを作成する。フィボナッチ数列を作る関数を呼ぶ。
  2. サブルーチン … src/myapp2.lispの中に、フィボナッチ数列を作る関数を格納する。

プログラムのコアと言える部分(フィボナッチ数列を計算する部分)はsrc/myapp2.lispの中に入る。そしてあとはそれを呼ぶための一連の手続きを書くだけなのだが、そちらのほうが割と目立つので難しく見え、Common Lisp開発をhesitateさせる原因になっている気がする。

実行可能のエントリー(main)ファイルを作成する

cl-projectで作成したmyapp2を起動させるためにはmainを含むファイルが必要で、作成する方法がちゃんと用意されている(ros init)。エントリーファイルの名前は何でもよく、ファイルの場所もどこに作成してもよいが、一番わかりやすい場所はやはりmyapp2ディレクトリだろう。

$ cd ~/work/sbcl/myapp2
$ ros init main
Successfully generated: main.ros

main.rosというファイルが作成された。中身を見る。

$ cat main.ros
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(progn ;;init forms
  (ros:ensure-asdf)
  ;;#+quicklisp (ql:quickload '() :silent t)
  )

(defpackage :ros.script.main.3735336286
  (:use :cl))
(in-package :ros.script.main.3735336286)

(defun main (&rest argv)
  (declare (ignorable argv)))
;;; vim: set ft=lisp lisp:

ファイルの中身はほとんど「呪文」のようなもので中身はよくわかっていないが全部理解する必要もなさそうだ。
ちなみにこのファイルを何も書き換えずにそのまま実行すると、もちろん何もしないで終わる。

$ ./main.ros
$   (←何も出力せず終了した。)

サブルーチン(まだ作成していない)とのやりとりを行うため書き換える箇所は2箇所ある。;;#+quicklispの行と、main関数だ。ほかのところはそのままでよい。むしろいじらないほうがよいと思う。
実際の方法は次回以降に。