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

俺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))