Archive for the ‘紹介’ Category

Puppy Linux に newLISP をインストールする...または libffi の導入

 Puppy Linux は 4.X.X 系の日本語版を使っていましたが、5.X.X 系も日本が版が出ています。古い機種は 4.X.X 系と相性がいいですが、新しいハードウェアには 5.X.X 系の方が良さそうです。
 そこで、5.X.X 系を使ってみることに、、、ついでに懸案だった libffi の導入にも取り組みました。

1.Puppy Linux の導入
 http://openlab.jp/puppylinux/ から Lupu-528JP本体と開発環境を lupu_devx_528jp.sfs ダウンロードして、インストールする。インスト-ル方法は、http://openlab.jp/puppylinux/ を参照してください。

2.libffiをインストールする。
 http://sourceware.org/libffi/ から libffi-3.0.12.tar.gz をダウンロードして適当なフォルダーに展開。
 例えば、


/usr/local/source/

 あたりに。
 展開されたディレクトリ(/usr/local/source/libffi-3.0.12)に入り、


./configure

 して


make

 する。成功したら、


make install

 してから、ffi.hとffitarget.hを /usr/include にコピーする。
 (4.X.X 系でインストールでしても newLISP を make できなかったのは、これに気づかなかったから、、、)

3.newLISPをインストールする
 http://www.newlisp.org/ から newlisp-10.4.6.tgz をダウンロードして適当なフォルダーに展開
 例えば、


/usr/local/source/

 あたりに。
 展開されたディレクトリ(/usr/local/source/newlisp-10.4.6)に入り、


make

 する。
 これは、


make -f makefile_linux_utf8_ffi

 と同じ。
 ffilib をインストールしていないなら、


make -f makefile_linux_utf8

 を実行する。
 makeに成功したら、


make install

 する。

 これで完了です。ここで気づかれた方もいるかもしれませんが、コンパイル・オプションを変更していません。それでも、make できるのです!
 改めて、makefile_linux_utf8_ffi の中をのぞくと、


default: $(OBJS)
$(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -lffi -o newlisp # for UBUNTU Debian
# $(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -ltermcap -o newlisp # slackware
# $(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -lncurses -o newlisp # other Linux Dist
# $(CC) $(OBJS) -m32 -g -lm -ldl -o newlisp # without readline support
strip newlisp

 5.X.X 系は 4.X.X 系とカーネルが違うから?
 まっ、動くんだから問題はありません(笑)。この実行ファイルが 4.X.X 系で動くことはないでしょうけど、、、
 さて、よく見るとコメントアウトされた行に libffi を含める -lffi がありません。たぶん忘れたのでしょうね。


default: $(OBJS)
$(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -lffi -o newlisp # for UBUNTU Debian
# $(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -ltermcap -lffi -o newlisp # slackware
# $(CC) $(OBJS) -m32 -g -lm -ldl -lreadline -lncurses -lffi -o newlisp # other Linux Dist
# $(CC) $(OBJS) -m32 -g -lm -ldl -lffi -o newlisp # without readline support
strip newlisp

 とすべきところでしょう。

 以上、如何でしょうか?
 あっ、JAVA のダウンロードとインストール方法は http://java.com/ja/download/ でどうぞ。

newlisp-utility.lsp と onnewlisp.lsp

 既にお気付きと思いますが、本 blog で度々使っている defun や labels 等が定義されている newlisp-utility.lspAbout と同じように、この Web サイトのページにしました。最上部のタブをクリックすれば開きます。以前の場所にも、置いてありますが、以降は、こちらをお使い下さい。
 また、“On newLISP” でよく使う関数やマクロで newlisp-utility.lsp に無いものは、 同様にページ化した onnewlisp.lsp の方に追加していきます。
 あわせてお使い下さい。

以上、ご報告まで。

init.lsp と include について

(この blog は、“short short story または 晴耕雨読な日々”に掲載したものの再掲です。スクリプトも含め、一部加筆修正してあります。)

newLISP の起動時、起動ディレクトリに init.lsp があると、それを読み込みます。
つまり、 init.lsp を用意することで、お好みの newLISP に変身させられます(笑)。
私が使っている init.lsp は、次のようになっています。

(context 'MAIN:include)
; http://www.newlisp.org/index.cgi?page=Code_Snippets
(define error "")
(define modules '())
(define (include:include mfile)
    (unless (find mfile modules)
      (when (catch (if (file? mfile) (load mfile) (module mfile)) 'error)
        (push mfile modules -1))))

(context 'MAIN:type-of)
; http://static.artfulcode.net/newlisp/util.lsp.src.html
(define types '("boolean" "boolean" "integer" "float" "string" "symbol" "context"
                "primitive" "primitive" "primitive" "quote" "list" "lambda" "macro"
                "array"))
(define (type-of:type-of x)
  (let (type (types (& 0xf ((dump x) 1))))
    (if (and (= "list" type) (context? (first x)))
          (name (first x))
          type)))
(context MAIN)
(include "macro.lsp")
(include "newlisp-utility.lsp")

このように、この blog で紹介するスクリプトの先頭で使っている、あるいは、使うことになる関数include は、私の場合、init.lsp で定義しています。
関数include は、Common Lisp の require に相当します
ここで定義している関数include は、引数として与えられたファイル名のファイルがあれば、それを load し、なければ、環境変数NEWLISPDIR下の modulesディレクトリから load します。
どちらにもなければ、nil を返します。つまり、戻り値を見ることで、正常に読み込まれたかどうかを判定できます。エラー内容は、文字列変数include:error に入ります。
ロードしたファイル名は、リスト変数include:modules に入っています。
また、関数tyoe-of は、文字通り、引数の型を返します。newLISP組込みで入っていても良さそうですが、ArtfulCode の Module: util に定義してあるのを使わせてもらっています。デバック時に重宝します。
あとは、おなじみ、macro.lsp日本語訳) と拙作newlisp-utility.lsp を include しています。
これだけ init.lsp で用意しておけば、以降の blog で紹介するスクリプトがすんなり動きます。(笑)
便利な init.lsp ですが、何らかの事情で、読み込みたくない時は、

newlisp -n

で、起動すれば、素の newLISP が立ち上がります。

以上、如何でしょうか?

何故、newLISP なのか?。。。または、多値を実装してみる

前にも書いていますが、改めて書いておきたいと思います。
折しも、newLISP の生みの親、Lutz Mueller 氏のインタビュー記事で次の言葉を読んで得心しました。

Less code, less errors, less memory, less CPU cycles, less energy, less resources.

newLISP のコンセプトは、この言葉につきますね。
さて、Lisp の優位性は、Paul Graham 氏が“On Lisp”や。“ハッカーと画家”で書いている通りだと思います。
そして、Lisp の代表格 Common Lisp でできることは、大抵 newLISP でもでき、優位性もそのまま当てはまります。
その確証として、“On newLISP” を書いてきました。いや、書いていく予定です。
かたや、300Kバイトに満たない実行ファイルに400弱の組込関数を持つ newLISP。
そして、Mバイトサイズの実行ファイルに1000個以上もある関数を持つ Common Lisp。
どちらを選びます?
私は、newLISP を選びました。私のやりたい事に、前述の newLISP のコンセプトが合っているから。
Common Lisp で、できないという訳ではないです。

要するに、私にとって重要なのは、Lisp なのか、Lisp でないのかではなく、
私がやりたい事に使えるか使えないのかなのです。

さて、Common Lisp と newLISP には、決定的な違いが三つあります。
細かいことを言えば、ぜんぜん違うものかもしれません。
“newLISP は Lisp ですらない”、という人もいるでしょう。
構いません(笑)、あくまでも私の見方です。

一つ目は、ドット対の有無。
二つ目は、レキシカル・スコープとダイナミック・スコープ。
三つ目は、戻り値に多値が使えるかどうか。

ドット対がどうしても必要で、どんな場合でもレキシカル・スコープ状態でなくてはならず、多値が使えなんて考えられない、という人は Common Lisp か Scheme ということに。もっとも、Scheme ですら Lisp でないという人もいるでしょうけど。

さて、ドット対がどうしても必要というのは、どういう状況でしょうか?
私の浅はかな考えでは、ドット対を前提に書かれたスクリプトがあるからしか思いつきません(汗)。
長年 Lisp や Scheme を使ってきた人にとってドット対のないことは、とんでもなことかもしれませんが、Lisp や Scheme を知らない人にとっては、どうでもよいことかもしれません。
ちなみに私は、Common Lisp から newLISP に乗り換えましたが、 newLISP の方が迷わずに済みました(笑)。
逆を言えば、Common Lisp を使っていた時は、ドット対には悩まされました(汗)。

二つ目、newLISP はダイナミック・スコープですが、context を使って部分的にレキシカル・スコープを実現できます。また、ダイナミック・スコープといっても、C 言語と同様に大域変数と局所変数は区別されます。
つまり、必要に応じてレキシカル・スコープを使うことができるということ。

三つ目、戻り値の多値。Lisp は、リストを戻り値にできるのに、何故多値が必要なのか?私には、判りません(汗)。ただ、関数truncate のように、ふつう必要なのは整数部分のみで、時々、切り捨てた小数部分を取り出すのに、別の関数を使わずに済むという意味では、使い易いのかもしれません。
リストの中身をインデックス機能で簡単参照できる newLISP では、ただリストを返せばよいだけのような気がしています。それで、前の“On newLISP”では、単にリストを返す仕様にしていました。
とはいえ、newLISP で多値が実装できないわけではありません。

(context 'MAIN:multiple-value-bind)
(define-macro (multiple-value-bind:multiple-value-bind)
  (letex (_var (args 0)
          _val (args 1)
          _body (cons 'begin (2 (args))))
	  (local _var
      (setq values:mv-set true)
      (map set '_var _val)
      (setq values:mv-set nil)
      _body)))

(context 'MAIN:values)
(define-macro (values:values)
  (letex (_item (args 0)
          _lst  (cons 'list (args)))
    (if mv-set _lst _item)))
(context MAIN)

前は実装しない、いや、できませんでしたが(汗)、今ならできます。
試しに、多値を返す関数truncate を用意して、

(define (truncate number)
  (let (num (if (< number 0) (ceil number) (floor number)))
    (values num (sub number num))))

multiple-value-bindを試すと、

> (multiple-value-bind (i f) (truncate 26.8175) (println i " "  f))
26 0.8175
0.8175
> (multiple-value-bind (i f) (values 1 2) (println i " "  f))
1 2
2

このように、values 単独でも使えます。
ちなみに、関数truncate は、

> (truncate 26.8175)
26

リストの第一項目のみを返しています。トップレベルで多値を返す、とまではいきませんが(汗)。
前述の関数truncate の使い方であれば、これで十分のような気がします。
ちなみに、多値の第二項目以降を見るには、multiple-value-list を使います。

> (multiple-value-list (truncate 26.8175))
(26 0.8175)

multiple-value-list の実装は、以下の通り

(context 'MAIN:multiple-value-list)
(define-macro (multiple-value-list:multiple-value-list)
  (letex (_val (args 0))
    (let (_lst)
      (setq values:mv-set true)
      (setq _lst _val)
      (setq values:mv-set nil)
      _lst)))
(context MAIN)

これで、newLISP でも、どうしても必要なら、多値が使えます。
私は、“On newLISP”以外で使うことは、まず無いでしょうね(笑)。

以上、如何でしょうか?

ブログ開始にあたって

newLISP は、いわゆる LISP の方言の一種です。
newLISP と他の LISP との違いは、”Comparison to Common Lisp and Scheme” にあります。
日本語で読みたい方は、KOSH さんの“舌足らずなブログ”にあります。こちらからどうぞ。

私は、Paul Graham 氏の “On Lisp” (もちろん翻訳本)を読んで、Lisp を始めました。
そして、newLISP に出会い、本格的にスクリプトを書き始め、ブログ“short short story または 晴耕雨読な日々”にカテゴリ “LISP” と “On newLISP” で投稿してきました。

しかし、newLISP 関する部分を忘備録として使い易そうなここ(Word Press)で書くことにしました。
書きためたスクリプトや newLISP マニュアルの翻訳(現在、guiserver を翻訳中)等を紹介していく予定です。
また、newLISP のバージョンアップに合わせた “On newLISP” の書き直しも予定しています。

以上、如何でしょうか?