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-02-19

UtiLispでL-99 (P15 各要素を任意の回数複製)

| 15:52 | UtiLispでL-99 (P15 各要素を任意の回数複製) - わだばLisperになる を含むブックマーク はてなブックマーク - UtiLispでL-99 (P15 各要素を任意の回数複製) - わだばLisperになる

何でか知りませんが、急にUtiLispでも書いてみたくなりました。

;; UtiLisp
(defun repli (lst times)
  (mapcan lst #'(lambda (x) (make-list times x))))

(defun make-list (n (elt nil))  
  (and (0> n) (err:argument-type n 'make-list))
  (do ((n n (1- n))
       (res () (cons elt res)))
      ((0= n) res)))

UtiLispならでは、っぽいところ

  1. map系の引数の順番が逆
  2. 0=は、zerop(zeropもある)
  3. 0>は、minusp、同様に0<はplusp
  4. (do (a b c) (t) )という書き方はNG。(do ((a) (b) (c) ) (t) )ならOK。
  5. ラムダリストでは、括弧で囲めば、オプショナル引数となり、デフォルト値の指定も可能
  6. error系が素朴でMacLISPっぽい。

ArcでL-99 (P15 各要素を任意の回数複製)

| 15:02 | ArcでL-99 (P15 各要素を任意の回数複製) - わだばLisperになる を含むブックマーク はてなブックマーク - ArcでL-99 (P15 各要素を任意の回数複製) - わだばLisperになる

前回は2つずつにするというお題でしたが、今回は、ちょっと発展して任意の回数繰り返したリストを返せというお題です。

(repli '(a b c) 6)
;=> (a a a a a a a b b b b b b b c c c c c c c)

(def repli (lst times)
  ((afn (lst acc cnt)
     (if no.lst
	 rev.acc
	 (if (is 0 cnt)
	     (self cdr.lst (cons car.lst acc) times)
	     (self lst (cons car.lst acc) (- cnt 1)))))
   lst () times))

;; 繰り返しで
(def repli (lst times)
  (mappend [newlist times _] lst))

(def newlist (n (o elt nil))
  (let acc ()
    (repeat n (push elt acc))
    acc))

LISPとリフレクション

| 02:20 | LISPとリフレクション - わだばLisperになる を含むブックマーク はてなブックマーク - LISPとリフレクション - わだばLisperになる

久々に2chのLispスレを眺めていて、3-LISPという処理系があるということを知りました。

3-LISPって一体何物と思って調べてみたら、リフレクションという概念が1982年にBrian Smith氏によって提唱された時に、その処理系として登場したとのこと。

とりあえず、面白そうだったので、処理系が公開されていないか探してみましたが、ぱっとしたものは見付からず。

それ以前にリフレクションが何だか分からなかったので、調べてみたところ、自己反映機能とも呼ばれていて、処理系自身で機能を拡張したり、実行速度を改善したりする機能のこと、とのこと。また、マクロはコンパイル時のリフレクションとも考えられる、という記述も。

何がなにやら、という感じでしたが、適当にリフレクションでヒットする論文を読んでみたところ、Common Lisp的に身近なところでは、eval-when等やコンパイル時に最適化する機構もリフレクションの一種らしいです。あと、CLOSの機能の一部とか。

例えば、define-compiler-macroはまさにそういう感じで、コンパイル時の状況によって最適化したりするのに使うようです。

(defun plus (&rest args)
  (apply #'+ args))

(define-compiler-macro plus (&whole form &rest args)
  (case (length args)
    (0 "引数がないので関数は呼び出さないで0に置き換えたいところ")
    (1 (car args))
    (t form)))

(defun foo (n)
  (plus n 3))
;=> 6

(defun bar ()
  (plus))

(print (bar))
;=> "引数がないので関数は呼び出さないで0に置き換えたいところ"

これは、CLtL2のコード例ですが、上記ではコンパイル時に引数が0か1個と判定できるならば、関数を呼びださないで、即値に置き換えてしまいます。

何となく面白いと思ったので、自分でも馬鹿っぽい例を考えてみました。

かなり無理矢理なのですが、実行結果が速く出る方を選択するdef-fasterというものを定義して、fib-slowと、fib-fastという、2種類のfibから速い方をfibという名前で呼び出せるようにする、というものです。

こういうのもリフレクションと呼べるのでしょうか…。

工夫すれば、何だか色々できそうです。

それはさておき、3-LISPがどういうものだったのか知りたい!

;; 動作
(defun fib-fast (n &optional (a1 1) (a2 0))
  (cond ((zerop n) 0)
	((< n 2) (values a1 'fast))
	('T (fib-fast (1- n) (+ a1 a2) a1))))

(defun fib-slow (n)
  (if (< n 2)
      n
      (+ (fib (1- n))
	 (fib (- n 2)))))

(def-faster fib 
    (fib-slow 30) (fib-fast 30))

(fib 10)
;=> 55, FAST

;; 定義
(defmacro run-time (fn)
  `(+ (- (get-internal-run-time)) 
      (progn
	,fn
	(get-internal-run-time))))

(defmacro def-faster (name x y)
  `(setf (symbol-function ',name)
	 (if (< (run-time ,x) (run-time ,y))
	     #',(car x)
	     #',(car y))))

ゲスト



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