kiyoka.2009_07_21 RSSPLAIN

Related pages: !kiyoka.blog.list !kiyoka.blog.2009_07
555555555555555555555555555555555555555555555555555555545555555555555555555555555555555555555555455
5

[Nendo] Rubyとの連携を考える(3)

5

私がRubyで書いているLisp方言、 Nendoの開発状況続き。

5

Rubyの世界へのアクセス手段として引きつづき .(ドット)オペレータを実装してみた。 

5

3724069044_ae409ab32e_o

5
 (ここに書いた仕様はおそらく後日変わると思うので注意)
5

 

5

実際にコードを書いてみると何か違う

5

(. a b) は Rubyのa.bという式に起きかえられるという単純なルールにしてみた。

5

以下は、実際の動作。

5
nendo> (macroexpand '(. Kernel open))
5
Kernel.open
5
nendo> (macroexpand '(. a size))
5
a.size
5
nendo> (macroexpand '(. (. a size) to_s))
5
a.size.to_s
5
nendo> (macroexpand '(. (. a size) to_s (. to_s to_i)))
5
a.size.to_s.to_s.to_i
5
nendo> (set! str "str")
5
"str"
5
nendo> (. str size)
5
3
5
nendo> str.size
5
3
5
nendo> (+ (. str size) 1)
5
4
5

 

5

何が問題か

5

問題は . (ドット)の第一引数にインスタンスが指定できないこと。

5

 

5
nendo> (define a "str")
5
"str"
5
nendo> a
5
"str"
5
nendo> (. a size)
5
3
5

 

5

ここまでは良い。が、

5

symbolまたは (. symbol symbol ...) しか受けつけない様にしているので

5

例えば、次のようなコードは書けそうで書けない。

5
nendo> (. "str" size)
5
dot-operator requires symbol, but got str
5
        from ./init.nnd:292
5
        from ./init.nnd:267:in `initialize'
5
        .
5
        .
5
       (略)
5

 

5
nendo> (. 3 to_s)
5
dot-operator requires symbol, but got 3
5
        from ./init.nnd:292
5
        from ./init.nnd:267:in `initialize'
5
        .
5
        .
5
       (略)
5

 

4

Rubyを知っている人は、文字列などのリテラルを第一引数に指定したくなるだろうなあ。

5

制限がきつすぎるのかな。もうちょっと考えてみよう。

5

 

5

with-openを実装してみた

5

早速、 . (dot-operator)でRubyのライブラリを呼びだす例として、with-openを作ってみた。

5

使いかたは (with-open 手続き ファイル名) または、 (with-open 手続き ファイル名 openメソッドのオプション) と言う形式で記述する。

5

イメージはSchemeの with-input-from-file でいう with-系のユーティリティで、オープンしたRubyのFileオブジェクトを引数として手続きpredを呼びだす。

5

また、手続きpredの呼出後に、ファイルをクローズしてくれる。

5
(define (with-open pred . lst)
5
  (let1 len (length lst)
5
        (let1 f (cond
5
                 ((= 1 len)
5
                  (Kernel.open (car lst)))
5
                 ((< 1 len)
5
                  (Kernel.open (car lst) (cadr lst)))
5
                 (else
5
                  (error "with-open requires 1 or 2 arguments")))
5
              (let1 result (pred f)
5
                    (f.close)
5
                    result))))
5

 

5

実際に動かした。 

5

t.txtにはこんなテキストデータが入っている場合、

5
bash-3.2$ cat t.txt
5
line1_A line1_B line1_C
5
line2_A line2_B line2_C
5
line3_A line3_B line3_C
5

 

5

このコードを実行すると

5
(with-open
5
 (lambda (x)
5
   (map
5
    (lambda (x)
5
      (x.chomp.split.to_list))
5
    (x.readlines.to_list)))
5
 "t.txt")
5

 

5

結果はこうなる。

5
(("line1_A" "line1_B" "line1_C") ("line2_A" "line2_B" "line2_C") ("line3_A" "line3_B" "line3_C"))
5

 

5

それにしても .to_list が毎回必要なのがカッコワルイか。

4

それと、引数の順番は (with-open ファイル名 手続き openメソッドのオプション) の方がいいかもしれない。

5

 

5

...comment disabled...