« 2009年5月 | メイン | 2009年8月 »

2009年6月21日

Factorに入門する(20) inlineそのいち

「特定のディレクトリにあるjpgファイルのリスト」を得る用事(用事?)があって、factorで書いてみたらけっこう苦労しました。

USING: io.directories io.pathnames kernel sequences io ;
IN: filelist

<PRIVATE
: filter-quot ( str -- quot ) [ file-extension ] swap [ equal? ] curry compose ; inline
PRIVATE>

: filelist ( path ext -- seq ) 
    dupd [ directory-files ] dip filter-quot filter 
   [ dupd "/" swap 3append ] map nip ;

最初は、filer-quotのinline指定なしで書いてみました。そうすると、filelistのコンパイルに失敗します。曰く、

Got a computed value where a literal quotation was expected

filter-quotで生成したquotationを、filterに渡しているところでこのエラーが発生しているようです。filterはliteralのquotationじゃないと受け付けないと。それじゃ全然quotation使えないじゃん!

と悩むこと30分。inline指定しておけばよいことがわかりましたが...これは「optimizing compiler」でのみ効くとのこと。つまり、optimizing compilerを使わなければinline指定しなくても動くはずとのこと。

まだよくわからないので、続きます。

2009年6月 1日

Factorに入門する(19) wordの定義: パース時、ランタイム

Factor入門1ヶ月以上あきました。第19回。まだ景色が見えてないところがたくさんあるのに、息切れしてきました。

今日はwordを定義する方法について調べます。普通のword定義はこういうふうにします。

: myword ( x y -- z ) dup * + ;

ほぼ意味のないwordですが、x + y * 2を計算します。mywordは名称。( x y -- z )はstack effectの宣言。: からはじまって、;で終わるまでがwordの定義です。これは、ソースコードのパース時に読み込まれ、定義が実行されます。

ランタイムでwordを定義することもできるそうで、それがdefine。

( scratchpad ) DEFER: foo
( scratchpad ) \ foo [ dup * + ] define
Attempting to define foo outside of a compilation unit

Type :help for debugging help.
( scratchpad ) [ \ foo [ dup * + ] define ] with-compilation-unit
:errors - show 1 compiler errors
( scratchpad ) :errors

==== <Listener input>

<Listener input>

Asset: foo

Missing stack effect declaration
word foo
:errors - show 1 compiler errors
( scratchpad ) [ \ foo [ dup * + ] (( x y -- z )) define-declared ] with-compilation-unit
( scratchpad ) 3 4 foo .
19

defineだとstack effect declarationがない、って怒られてしまいました。用途としては、既に定義されているwordの中身を置き換えるもの、のように見えます。いきなり定義するにはdefine-declaredを使う必要があるようです。いずれにせよ、wordとして用意しておかなくてはならないので、DEFER:を使わなくてはなりません。DEFER:はランタイムじゃなくてパースタイムだよな。ランタイムにwordを作る方法はやっぱりよく分かりません。

あと、with-compilation-unitが必要とのことですが、compilation-unitの詳細もよく分かっていません。要調査。