Eclipse の Cusp プラグインを使って Lisp アプリケーションを開発する

Lisp はもはや人工知能専用のものではありません -- Lisp を使うことで Java や C のプログラミングを別の角度から考えられるようになります

Lisp は素晴らしいプログラミング言語です。ほとんど型を持たないという Lisp の性質を活用することで、プログラミング言語の知識を広げることができます。また、Java™ プログラミング言語や PHP、あるいは C/C++ の経験が豊富な人達にとっても、新しい考え方でアプリケーションを開発する上で Lisp が役に立ちます。さらに、Lisp を使うとスマートなことがいくつかできるのです。Eclipse の Cusp プラグインを使って Lisp アプリケーションを開発する方法を学びましょう。

Tyler Anderson (tyleranderson5@yahoo.com), Freelance writer

Tyler Andersonは2004年にBrigham Young Universityにてコンピューター・サイエンスの学位を取得しており、現在はコンピューター・エンジニアリングの修士取得に向けての最終学期を送っています。これまで、DPMG.COMのデータベース・プログラマーとして働いたことがあり、現在はオレゴン州BeavertonにあるStexar Corp.のエンジニアです。



2007年 10月 09日

Cusp: Lisp のための Eclipse 開発環境

Cusp は Common Lisp プログラミング言語のための開発環境です。Lisp を使うと、Web アプリケーションをはじめとする、あらゆる種類のアプリケーションを開発することができます。Lisp は、今日でも相変わらず広く使われている、(Fortran に次ぐ) 2 番目に古いプログラミング言語であり、そして最初の関数型言語として知られています。Lisp の作成は 1950年代後半に始まり、最初に実装されたのは MIT による 1958年の AI (Artificial Intelligence: 人工知能) プロジェクトです。Lisp の強みはリストの処理、つまり AI と記号計算にあります。実際、Lisp は「list processor」の略であり、以下の段落で説明するように、このプログラミング言語はリスト処理のために作られたのです (Lisp の歴史に関しては「参考文献」を参照してください)。

すぐにおわかりになると思いますが、Lisp は他の一般的なプログラミング言語とはまったく異なります。例えば、大部分の一般的なプログラミング言語で乗算を行う際には、紙の上で計算する場合とまったく同じように、int times = 5 * 5; のようにします。

Lisp では、(* 5 5 3) とすると 75 が生成されます。(MAX 9 8 7 6 20) というリストがあると、最大値として 20 が返されます。

ここで「最初の関数型言語」という言い方が当を得ていることに注目してください。すべてが関数に基づいているのです。各関数が持つパラメーターの数は変更可能です。上記のようなリストを、再帰と、carcdr などの Lisp 関数を使って処理できることを見ると、Lisp を使ったリスト処理が強力なことがわかります。

Lisp の歴史は古いため、Lisp 用の開発環境は数多くあります。しかし同時に、古いプログラミング言語にありがちなことですが、ツールのサポートは大部分がテキスト・ベースであり、慣れない人には直感的ではありません。従って Cusp を試す 1 つの理由は、Cusp のインターフェースがテキスト・ベースの「すべてのコマンドを覚えて使う」種類のものではなく、初めての人でも Lisp を学べ、Lisp で開発できる直感的な GUI であるためです。また Cusp には、Eclipse の GUI フレームワークに特有の、優れたプロジェクト管理機能があるという利点もあります。

先に進む前に、Eclipse.org から最新の Eclipse Classic のバンドルをダウンロードする必要があります。ダウンロードが終わったら Cusp のインストールと設定の方法を学ぶことができます。


Cusp をインストールする

圧縮された Eclipse Classic バンドルのアーカイブを入手できたことと思いますので、アーカイブを解凍し、eclipse.exe を実行します。

最新バージョンの Cusp を入手するには、Help > Software Updates > Find and Install をクリックします。Search for new features to install (インストールする新規フィーチャーを検索) オプションをクリックします。今度は New Remote Site ボタンをクリックします。リモート・サイトの名前として Cusp update site と入力し、URL には http://www.sergeykolos.com/cusp/update と入力し、OK をクリックします (図 1)。

図 1. Cusp 用のリモート・サイト情報を入力する
Cusp 用のリモート・サイト情報を入力する

追加した新しいリモート・サイトの隣にあるチェックボックスをクリックし、Finish をクリックします (図 2)。

図 2. Cusp Eclipse Update Site を選択する
Cusp Eclipse Update Site を選択する

別のウィンドウが表示されるので、そこで Cusp Eclipse Update Site を展開して Cusp を選択します (図 3)。

図 3. インストールするフィーチャーを選択する
インストールするフィーチャーを選択する

Next をクリックします。次に使用許諾契約書を読み、I accept the terms in the license agreement (使用許諾契約書に同意します) をクリックして使用許諾契約書に同意し、Next をクリックします。すべてのライブラリーが選択されていることを確認し (図 4)、そして再度 Next をクリックします。

図 4. オプションのフィーチャーを選択する
オプションのフィーチャーを選択する

最後のページには、これからインストールしようとしているフィーチャーのインストールの概要が説明されているので、Finish をクリックします。すると、プラグインとそのコンポーネントがダウンロードされ、インストールされます。ダウンロードが終わると、署名されていないフィーチャーをインストールしようとしています、という内容の警告が表示されるので、Install all をクリックします。インストールの最後では Eclipse をリスタートするように促されるので、Yes をクリックします。

これで Eclipse の Cusp プラグインをインストールできました。次に Lisp プロジェクトを設定します。


Lisp プロジェクトを設定する

Lisp 開発を始める前に、新しい Lisp プロジェクトを設定する必要があります。そのためには、File > New > Project と進みます。Lisp フォルダーを展開し、Lisp Project をクリックし、Next をクリックします。新しいプロジェクトの名前として my_new_lisp_project と入力し (図 5)、Finish をクリックします。

図 5. 新しい Lisp プロジェクトに名前を付ける
新しい Lisp プロジェクトに名前を付ける

Finish をクリックすると、新しいプロジェクトが作成され、Lisp パースペクティブが開きます (図 6)。

図 6. Lisp パースペクティブ
Lisp パースペクティブ

Lisp パースペクティブをよく見てください。Lisp Navigator ウィンドウは、開いているプロジェクトと、そのプロジェクトの関連ファイルを表示しています。Outline ウィンドウは現在開いているファイルの概要を表示しています。最上部右のウィンドウ (main.lisp を示しています) が Lisp 開発ウィンドウです。最下部右のウィンドウ (REPL) はコマンドラインの Lisp インタープリターであり、ここで Lisp コマンドを実行することができます。

Eclipse を閉じてから再度開いた場合には、プロジェクトの .asd ファイルをロードする必要があります (図 7)。

図 7. ASD ファイルをロードする
ASD ファイルをロードする

my_new_lisp_project フォルダーの下にある my_new_lisp_project.asd ファイルを右クリックし、Load asd を選択する必要があることに注意してください。これは要するに REPL ウィンドウで Lisp プロジェクトをコンパイルし、新しいコードを使用する Lisp コマンドを入力できるようにしているのです。

次に、Cusp を使った Lisp 開発を試してみましょう。


Cusp を使った Lisp 開発

まず、単純なカスタム関数を定義し、その関数のテストも行います。main.lisp ファイルを開き、defun (define function) コマンドを使って下記を追加します。

...
(defun first_howdy_function ()
  "howdy ho")

Save the file. To export the function from within the package, type the following code in defpackage.lisp:

...
   ;; Exported symbols go here
  first_howdy_function
   ))

このファイルを保存します。この関数をパッケージ内部からエクスポートするには、defpackage.lisp 内で次のコードを入力します。

この関数は、パッケージの外部から使うことができます。新しい関数をテストするためには、REPL の下側のウィンドウで (my_new_lisp_project:first_howdy_function) と入力します。

この場合では、これは (my_new_lisp_project::first_howdy_function) と入力することと同じであることに注目してください。これを入力する必要があるのは、この関数を defpackage.lisp 内でエクスポートしなかった場合です。

Send をクリックし、出力を確認します。上記のどちらかのコマンドを入力すると、出力は次のようになります。

COMMON-LISP-USER>
(my_new_lisp_project:first_howdy_function)

"howdy ho"

これで、最初の Lisp 関数 Howdy ができあがりました。

入力を持つ echo 関数を試してみましょう。

...
(defun first_echo_function (echoval)
  echoval)

先ほどの関数と同じように、これを defpackage.lisp 内でエクスポートします。この first_echo_function をテストするには、REPL ウィンドウの下の方の部分に (my_new_lisp_project:first_echo_function '("howd" "y h" "o")) と入力します。'("howd" "y h" "o") の部分がリストを定義する構文であることに注意してください。まず、括弧の前に単一引用符が必要であり、そしてその括弧の中でリスト要素が定義されます。この出力は次のようになります。

COMMON-LISP-USER>
(my_new_lisp_project:first_echo_function '("howd" "y h" "o"))

("howd" "y h" "o")

今度は、各リスト要素を個別に処理するメソッドを作成します。このメソッドが Lisp の真の実力を示すのです。これを次のように定義します。

(defmethod concat2 ((str1 string) (str2 string))
  (concatenate 'string str1 str2))

上記のメソッドが実際にはストリング型を定義していることに注意してください。ここまでは、ほとんど型を持たない言語として Lisp を使ってきました。二重引用符でデータを暗黙的にストリング型にすることもできますが、上記のメソッドは concat2 関数の入力と出力の両方を明示的にストリング型にします。またこのメソッドは、組み込みの連結関数を使って 2 つのストリングを結合させ、それらを 1 つのストリングとして返します。

concat2 をテストするためには、concat2 をエクスポートし、(my_new_lisp_project:concat2 "howd" "y ho") と入力します。その出力は次のようになります。

リスト 7. 2 つのストリングを連結した出力
COMMON-LISP-USER>
(my_new_lisp_project:concat2 "howd" "y ho")

"howdy ho"

これでできあがりです。ストリング「howd」と「y ho」が「howdy ho」になります。今度はもっと一般的な連結関数を、carcdr という 2 つの関数を使って作成します。Lisp は、この 2 つの関数で有名です。

リスト 1. リストの中の 3 つの要素を連結する
(defun concat3 (args_list)
  (concat2 (car args_list)
           (concat2 (car (cdr args_list))
                    (car (cdr (cdr args_list))))))

この関数も先ほどと同じく concat2 関数を使っていますが、入力としてパラメーターのリストを使っていることに注意してください。連結される各部分が、どのように args_list から取得されるのかを見てみましょう。car はリストの最初の要素を取得します。cdr は最初の要素を除いたリストを返します。最初の要素を取得するには、単にリストに対して car 関数をコールすればよいことがわかります。2 番目の要素を取得するためには、リストに対して cdr をコールし、次に新しいリストに対して car をコールする必要があります。3 番目の要素を取得するには、リストに対して cdr を 2 回コールし、最後のリストに対して car をコールします。

上記の関数をエクスポートした後の関数の出力は次のようになります。

COMMON-LISP-USER>
(my_new_lisp_project:concat3 '("howd" "y h" "o"))

"howdy ho"

これでできあがりです。3 つのストリングは正しく連結され、「howdy ho」になりました。次に、再帰関数を作成します。


Lisp を使った再帰

最後に作成する関数は、再帰を行います。Lisp を使ったリスト処理の真の実力は、ここにあります。Lisp でリストを処理する方法としては、繰り返しも (各項目を 1 つずつループすることで) 可能ですが、Java 言語などの一般的な言語とは異なり、何と言っても再帰が最も容易なのです。このセクションを最後まで読むと、再帰とは一体何かを正確に理解できるはずです。

まず、再帰的な concat 関数を作ります。

リスト 2. 再帰的な連結 (無限のパラメーター)
1   (defun concat_recursive (args_list)
2     (if (equal (cdr args_list) nil)
3         (car args_list)
4         (concat2 (car args_list)
5                  (concat_recursive (cdr args_list)))))

再帰は理解しにくい概念なので、順を追ってこの関数を見ていきましょう。

  • 上記の関数に任意の引数リストが渡されたとします。
  • リストの中に 1 つの要素しかない場合 (2 行目の (cdr args_list) の部分は nil を返します) には、1 つの要素 (3 行目の (car args_list)) を返します。
  • リストの中に複数の要素がある場合には (つまり 2 行目の (cdr args_list) がnil を返さなかったら)、リストの最初の要素 (4 行目を見てください) と、(cdr args_list) の結果をパラメーターとして使って再帰的に concat_recursive をコールした結果 (5 行目を見てください) とを (concat2 を使って) 連結した結果を返します。

'("ho" "wd" "y" " h" "o") というリストをパラメーターとして渡したとすると、出力は次のように行われます。

  • 初めて 2 行目に達した時には if 文は偽であり、「ho」と「(concat_recursive '("wd" "y" " h" "o"))」 を引数として concat2 がコールされます。
  • 2 回目に 2 行目に達した時には、if 文はまたも偽であり、「wd」と「(concat_recursive '("y" " h" "o"))」を引数として concat2 がコールされます。
  • 3 回目に 2 行目に達した時には、if 文はまたも偽であり、「y」と「(concat_recursive '(" h" "o"))」を引数として concat2 がコールされます。
  • 4 回目に 2 行目に達したときには、if 文はまたも偽であり、「 h」と「(concat_recursive '("o"))」を引数として concat2 がコールされます。
  • 5 回目は、再帰が終わる魔法の時です。今度は 2 行目の if 文は真であり、単純に「o」が返されるからです。この再帰を「巻き戻し」してみると、次のようになります。
    • 4 回目: 「 h」と「o」が連結されて返されます。
    • 3 回目: 「y」と「ho」が連結されて返されます。
    • 2 回目: 「wd」と「y ho」が連結されて返されます。
    • 1 回目: 「ho」と「wdy ho」が連結され、そして最終的な結果として返されます。

そして、これでできあがりです。次のように、最終的に「howdy ho」が返されます。

COMMON-LISP-USER>
(my_new_lisp_project:concat_recursive '("ho" "wd" "y" " h" "o"))

"howdy ho"

これで、Cusp 開発の兵器として再帰を追加できました。次にデバッガーを試します。


Cusp を使ってデバッグする

concat_recursive が処理に失敗し、デバッガーが役立つような入力条件を考えてみてください。そうした条件の 1 つとして、ある数字をストリングの中に混在させて送信し、何が起こるかを調べてみましょう。concat2 を使った連結には 2 つのストリングが必要なことを思い出してください。そのため、数字があると、この関数は再帰の中で処理が中断します。

コマンドとして (my_new_lisp_project:concat_recursive '("ho" "wd" "y" 55 " h" "o")) と入力します。二重引用符で囲まれていない数字 55 はストリングではなく、これによってデバッガーが表示されることに注意してください (図 8)。

図 8. デバッガーを起動する
デバッガーを起動する

デバッガーを起動する主なエラーが、(55 " ho") というリストに対して concat2 をコールできないというエラーである点に注目してください。また、エラーがトリガーされる前に「 h」と「o」が既に連結されていたことにも注目してください。

デバッガーのウィンドウには、==Backtrace== も表示されています (図 8)。その下にある各行 (この場合は 0 から 19) は、Send をクリックした時から発生している障害までの詳細なトレースを表示しています。このバックトレースでは、障害のトリガーとなった数字の 55 までさかのぼって再帰を調べ、追跡することができます。

追跡が終了したら、今度は何をするのでしょう。上記のケースでは、デバッガーの終了方法と、関数への入力の変更と検証の方法として、3 つの選択肢があります。コマンドを強制終了して通常の REPL ウィンドウに戻る方法、(テストによって) 接続を閉じる方法 (この方法を選択した場合には Eclipse をリブートして Lisp プロセッサーをリスタートする必要があります)、あるいは単純にデバッガーを強制終了して通常の REPL ウィンドウに戻る方法、の 3 つです。デバッガーを終了するために一番良い方法としては、必ずコマンドを強制終了して通常の REPL ウィンドウに戻ることです。

これで完了です。再帰関数を Lisp で実装することができました。


まとめ

Eclipse の Cusp プラグインを使った、この Lisp による開発を無事に完了することができました。なぜ Lisp が強力なのか、これでよく理解できたことと思います。Lisp では単純な再帰文を使うことで、記号とデータのリストの強力な処理を容易に行うことができるのです。また Cusp は Lisp の機能を補完してくれます。その際に使用するのは、組み込みの Cusp デバッガーや、プロジェクト管理機能を持つ安定した GUI、対話型の Lisp エディター、そしてコマンドを入力でき、コードをテストできる、Lisp プロセッサーとのコマンドライン・インターフェースなどがあります。さらに詳しくは「参考文献」を参照してください。


ダウンロード

内容ファイル名サイズ
Cusp article sample codeos-eclipse-lispcusp.code.zip28KB

参考文献

学ぶために

製品や技術を入手するために

議論するために

  • Eclipse に関する質問を議論するための最初の場所として、Eclipse Platform newsgroups があります (このリンクをクリックすると、デフォルトの Usenet ニュース・リーダー・アプリケーションが起動し、eclipse.platform が開きます)。
  • Eclipse newsgroups には、Eclipse を利用し、拡張することに関心を持つ人達のために、さまざまなリソースが用意されています。
  • developerWorks blogs から developerWorks のコミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=267261
ArticleTitle=Eclipse の Cusp プラグインを使って Lisp アプリケーションを開発する
publish-date=10092007