Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-01-19

cl-serializer

| 05:31 | cl-serializer - わだばLisperになる を含むブックマーク はてなブックマーク - cl-serializer - わだばLisperになる

今回は、cl-serializerを試してみます。

シリアライズって何ですか?という私なのですが、調べてみたところ、処理系内部のオブジェクトデータの外部へ入出力するためのものなんですね。

パッケージ名cl-serializer
本拠地サイトcl-serializer
ClikiCLiki: cl-serializer
ASDF-INSTALL

インストール

asdfに対応はしているのですが、依存するパッケージがことごとく、Clikiに登録されておらず、darcで引っ張ってこないといけません。これが、結構手間です。

自分は、darcで引っ張ってきて、tarボールにまとめ、asdf-installをしました。


$ cd /var/tmp
$ darcs get http://common-lisp.net/~loliveira/darcs/babel                   
$ darcs get --partial http://common-lisp.net/project/cl-def/darcs/cl-def    
$ darcs get http://common-lisp.net/project/stefil/darcs/stefil              
$ darcs get http://common-lisp.net/project/defclass-star/darcs/defclass-star
$ darcs get http://common-lisp.net/project/cl-serializer/darcs/cl-serializer

$ tar zcvf ....

(asdf-install:install "http://cffi-net.accela.net/releases/cffi-grovel-r2.tgz")
(asdf-install:install "/var/tmp/babel.tar.gz")
(asdf-install:install "/var/tmp/cl-def.tar.gz")
(asdf-install:install "/var/tmp/stefil.tar.gz")
(asdf-install:install "/var/tmp/defclass-star.tar.gz")
(asdf-install:install "/var/tmp/cl-serializer.tar.gz")

試してみる


(require :cl-serializer)

;; データ
(defvar obj '(a (b c) a b (d e (f g (h i)))))

;; 書き出し
(let ((sr (cl-serializer:serialize obj)))
  (with-open-file (out "/var/tmp/ser.dat" :direction :output :if-exists :supersede
		       :element-type 'unsigned-byte)
    (series:collect-stream out (series:scan sr) #'write-byte)))

;; 読み込み
(with-open-file (in "/var/tmp/ser.dat" :element-type 'unsigned-byte)
  (pprint (cl-serializer:deserialize (coerce (series:collect (series:scan-stream in #'read-byte)) 'vector))))
;=> (A (B C) A B (D E (F G (H I))))

serializeでシリアライズして、deserializeで戻し。

なるほど、なるほど。

私には用途が思い付きませんが、きっと凄いものなのでしょう(´▽`*)

俺Arc祭り 2008冬 (5)

| 03:05 | 俺Arc祭り 2008冬 (5) - わだばLisperになる を含むブックマーク はてなブックマーク - 俺Arc祭り 2008冬 (5) - わだばLisperになる

12. Data Types

データの型について

  1. シンボル
  2. 数(Common Lispと同じ)
  3. コンス
  4. 文字
  5. 文字列
  6. 配列
  7. クラス、オブジェクト
  8. データベース(ハッシュ/連想リスト)
  9. 関数
  10. マクロ
  11. その他

だそうです。マクロってのが光ってはいますね。

13. Compounds = Functions on Indices

複合したデータをインデックス付きの関数とみなす試みとのこと。

これも無理目なので、funcallみたいな、obcallというものをでっち上げて代用することにしてみました。


;; 動作
(obcall "hello" 2) 
;=> #\l

(obcall '(foo bar baz) 1)
;=> bar

(map #'pr '(3 4 1 2))
;=> 3412

(map "carpet" '(3 4 1 2))
;=> (#\p #\e #\a #\r)

;; ---- 定義 
(defun obcall (obj index)
  (elt obj index))

(defun map (fn &rest args)
  (if (functionp fn)
      (apply #'cl:mapcar fn args)
      (apply #'cl:mapcar (fn (x) (obcall fn x)) args))) ;複数の引数の場合は?

14. Strings Work Like Lists

文字列をリストに見立てるとのこと。TAO/ELISって文字列をリストとして扱えたらしいというのをどっかで読んだ記憶があるのですが、こういうこともできたんでしょうか。マニュアルには載ってないので、記憶違いかもしれませんが…。

色々と夢が広がりまくりなのですが、適当にできそうなものだけ作ってみました。

bol

俺Arc祭り 2008冬 (4)

| 02:22 | 俺Arc祭り 2008冬 (4) - わだばLisperになる を含むブックマーク はてなブックマーク - 俺Arc祭り 2008冬 (4) - わだばLisperになる

Lisp系言語には繰り返し構文が色々ありすぎる位ですが、Arcでも新しい構文を導入するようです。

10. Iteration

  • for, each, to, while

Common LispのDOはわかりづらい!とのこと。自分は、DO大好きなので、全然そう思わないのですが、多分少数派なんでしょう。そういう意見しか目にしたことないし…。繰り返し機構が付いたLETだと思えば、そんなに難解でもないと思うんですが、どうなんでしょう。あと、LOOPは色々話題にのぼるんですが、DOって話題になるとしても「気持ち悪い」で終わることが多いですね(笑)

さっと見た感じでは、ArcではCというかPerlの機構を取り入れてみたようです。どうもこの時のArcは、思い切りPerlの方向に進んでいるような。すべての言語はLispに向かうんじゃなかったのか!

11. Iteration Captures

繰り返し時にsumとか、keepとかitに値を束縛するという試み。加えてwhileは、itを束縛するとのこと。

loopのsum、collect、Perlの、$_とか、そういう感じでしょうか。

keepはリストに蓄え、sumは数を合計します。どうしてかは知りませんが、keepと、sumは二者択一だそうです。

下記のコードはCommon Lispと俺Arcの組み合わせで記述していることもあいまって非常にごちゃごちゃしています。

しかし、どうも括弧の足りないcondは好きになれないな…。


;; 動作
(for (= i 0) (< i 10) (++ i)
  (pr i))

;-> 123456789
NIL

(each x '(1 2 3 4 5) 
      (pr x)
      (sum x))

(each x '("al" "bob" "joe")
   (if (> (len x) 2) (keep x)))
;=> ("bob" "joe")

(to x 5
  (sum x)
  (pr x))
;->01234
10

(let i 0
   (pr (while (< (++ i) 10) (pr i) (keep i)))))
;123456789(1 2 3 4 5 6 7 8 9)

;; 定義

;; for
;;predが受け付けるのは、任意の式なのか、決まった形式か分からないので、
;;predの変数多重評価問題放置
(macro for (init pred then . body) 
  (with (tag (gensym))
    `(do ,init
	 (block nil
	   (tagbody 
	      ,tag
	      (unless ,pred
		(return))
	      ,@body
	      ,then
	      (go ,tag))))))

;; ++
(shadow 'incf)
(shadow '++)
(macro ++ body
  `(cl:incf ,.body))

;; to
(macro to body
  `(with-keep-or-sum to1
     ,.body))

(macro to1 (var limit . body)
  (with (/limit (gensym) /tag (gensym))
    `(let ,/limit ,limit
	  (do (= ,var 0)
	      (block nil
		(tagbody 
		   ,/tag
		   (unless (< ,var ,/limit)
		     (return))
		   ,@body
		   (++ ,var)
		   (go ,/tag)))))))

;; each
(macro each body
  `(with-keep-or-sum each1
     ,@body))

(macro each1 (var obj . body)
  (with (/i (gensym) /obj (gensym))
    `(with (,/obj (coerce ,obj 'vector) ,var nil)
       (to1 ,/i (length ,/obj)
	 (setq ,var (aref ,/obj ,/i))
	 ,@body))))

;; while
(macro while body
  `(with-keep-or-sum while1
     ,.body))

(macro while1 (pred . body)
  (let tag (gensym)
       `(block nil
	  (tagbody
	     ,tag
	     (if ,pred
		 (do ,.body
		     (go ,tag))
		 nil)))))

(macro with-keep-or-sum (fn . body)
  (with (s (x-finder 'sum body) k (x-finder 'keep body))
    (cond (and s k) (error "SUMとKEEPはどちらかでお願いしたい。")
	  s `(with-sum
	       (,fn ,.body))
	  k `(with-keep
	       (,fn ,.body))
	  `(,fn ,.body))))

(macro with-keep body
  (let /tem (gensym)
       `(let keep (list ())
	     (declare (ignorable keep))
	     (let ,/tem keep
		  (cl:macrolet ((keep (var) 
				  `(rplacd (cl:last ,',/tem) (list ,var))))
		    ,@body))
	     (cl:cdr keep))))

(macro with-sum body
  `(let sum 0
     (declare (ignorable sum))
     (cl:macrolet ((sum (var) `(++ sum ,var)))
       ,@body)
     sum))


俺Arc祭り 2008冬 (3)

| 00:55 | 俺Arc祭り 2008冬 (3) - わだばLisperになる を含むブックマーク はてなブックマーク - 俺Arc祭り 2008冬 (3) - わだばLisperになる

だんだん疲れて来てしまいました。俺Arc祭り。段々恥ずかしい駄目駄目なコードを晒すのも恥ずかしくなってまいりました。

実際のところは駄目なところが分からないのと、恥ずかしいところが分からない自分が恥かしいのですが。

それはさておき、

9. Binding

  • with, let

Arcの変数束縛機構ですが、letは、変数を一組しかとらないことにするみたいです。Gaucheのlet1と同じ感じ。

複数の場合には、withを使用するとのこと。

また、(let x 3 (foo x))は((fn (x) (foo x) ) 3)に展開されるんだそうです。letがlambdaに展開されるってことでしょうか。

色々深いんだと思いますが、単にletに展開するだけにしました。


;; 動作
(with (x 'a y 'b)
  (list x y))
;=> (A B)

(let x 'a
     (cons x 5))
;=> (A . 5)

;; 定義
(cl:defmacro with ((&rest spec) &body body)
  `(cl:let ,(cl:do ((s spec (cddr s)) res)
		   ((endp s) (nreverse res))
		   (push `(,(car s) ,(cadr s)) res))
	   ,@body))

(shadow 'let)
(cl:defmacro let (var val &body body)
  `(cl:let ((,var ,val))
	   ,@body))

俺Arc祭り 2008冬 (2)

| 00:18 | 俺Arc祭り 2008冬 (2) - わだばLisperになる を含むブックマーク はてなブックマーク - 俺Arc祭り 2008冬 (2) - わだばLisperになる

だらだら続いております。俺Arc祭り。

自分の書いているものが、非常に読み辛く、また書いてても良く分からなくなって来たので、小分けにして行くことにしました。

8. Functions and Macro

  • fn

lambdaは、fnと書くそうです。


(macro fn body
  `(cl:lambda ,@body))

非常に安直に…。(funcall (fn (x) (+ x 3)) 3)としないと動きません…。

((fn (x) (+ x 3) ) 3)みたいにして動くようにする簡単な方法ってあるんでしょうか。

  • rfn

labels(再帰可能なローカル関数定義)は、rfnと書くとのこと。

rfnは、多分トップレベルでも使えるんだろうとは思いますが、色々大変そうなので、doに埋め込むことにしました。

段々と定義するのにパッケージを指定するのが面倒になってきたので、my-arcパッケージを定義するために、my-arc-defというパッケージを作成し、そこからインポートすることにしてみます。

  • no

doの例で出てきたので、nullの一般化されたものと勝手に解釈して適当に定義。

st
  • マクロはファーストクラスオブジェクト

局所マクロを作るのは単に変数に束縛するだけ。

これは無理なのでスルー。

しかし、マクロがファーストクラスオブジェクトだとどういう風にプログラミングスタイルが変わるんでしょうね。

例示されているmacroの例なんですが、


(macro (test . body)
  `(if ,test (do ,.body))) 

;; when?
(macro when (test . body)
  `(if ,test (do ,.body)))

;; 動作
(when 33
  'foo 'bar 'baz it)
;=> 33

これってタイポでwhenが抜けてるんですかね? whenだと合点が行くのですが…。

ひたすら続きます…。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20080119