ラベル LOL の投稿を表示しています。 すべての投稿を表示
ラベル LOL の投稿を表示しています。 すべての投稿を表示

2010/09/23

先日書いた defmacro! がバグっていたので

先日書いたものがバグっていたので、修正しようとしましたが解決できず・・・。
バグは、defmacro! で可変長引数が取れないというものです。
例えば、
(defmacro! (sum . args) ...
とした時に args を filter して o! シンボルを g! シンボルに置き換えようとするところで、args がまだシンボルのままであるためエラーになるというものです。よって、その処理を書く場所に気をつけて評価順序を制御すれば良いだろうと思って修正を試みていたのですが、なかなかうまくいかず。。悔しいれす(^p^)



猫好きながら猫アレルギーにより鼻水ダラダラを理由に今日は一旦諦めます。。

追記

勘違いだったようです。というか見当違いでした。filter の引数に非リストを渡していたからっぽい。全然見当違いの修正を数時間やってました。。ご飯食べてお風呂入って、再度コードを見たらあっけなく・・・。




LET OVER LAMBDA Edition 1.0

2010/09/15

LOL defmacro!

LET OVER LAMBDA Edition 1.0 の defmacro! を scheme(Gauche)で書きました。
基本的に同じものですが、実験的に g! や o! を変更できるようにしています。
Un-Common Lisp の defmacro* がプレフィックスに g!, o! をつけるのでなく、サフィックスに #, % を付けるスタイルなのを見て、切り替えられるようにしてみても良いかなぁと。切り替え方が不細工ですが、まぁお試しということで。

使用例はこんな感じ。


以下 defmacro! のコード。


追記

defmacro! に可変長引数が受け取れないバグがありました。修正しました。

LET OVER LAMBDA Edition 1.0

2010/09/14

On Lisp のユーティリティをいくつか

いくつか Gauche で書きました。写経がてら。前回読んだ時にあまり書いてないので、揃えておいた方が良いなぁと。
ざっくり書いただけなので、動かないところがあるかもしれません。

LET OVER LAMBDA Edition 1.0On Lisp を再読しているので、こういうのを揃えていこうと考えています。書きたいものがあるときにすぐに書き始められる状態を作っておかないといけないなぁと思った次第です。

以下コード。


On LispLET OVER LAMBDA Edition 1.0

2010/09/09

syntax-rules, defmacro: define-cxr, define-cxr*

caaaar とか cadadadar などを定義するマクロ。LET OVER LAMBDA Edition 1.0 にもありました。

取りあえず書いてみました。
組み合わせて作っていく感じ。car + car で caar を作る、みたいな。
以下コード。


自分なりに考えてみたもの。もといし、効率も悪いけど意図通り動きます。
こちらは (define-cxr caar) とされたら a と d を car と cdr として手続きを組み立てる感じ。でも入力を制限していないので、my-caaar が caaar 相当の手続きに、ashitahadounaru? が caaadar 相当の手続きになります。。


追記

下のコード貼り間違えてました。修正。

追記2

map-accum でなくてもよかったですね。fold-right でよさそうです。
(define (cxr->ad-fun-lis sym)
  (fold-right (lambda (e acc)
                (let1 p (coalesce ((eq? e 'a) car)
                                  ((eq? e 'd) cdr))
                  (if p
                      (cons p acc)
                      acc))) '() (symbol->list sym)))

LET OVER LAMBDA Edition 1.0

2010/09/08

syntax-rules: dlambda

今日は、Twitter のタイムラインで LET OVER LAMBDA Edition 1.0 の話題が出ていました。
私も読みましたが、詳細はすでに記憶の彼方です。。再読したいところです。

記憶に残っている dlambda を scheme の syntax-rules で書いてみました。たぶん同じように動くと思います。

マクロを書く前に・・・
;; image
(define count-test
  (let ((count 0))
    (dlambda
     (:reset ()(set! count 0))
     (:inc (n)(inc! count n))
     (:dec (n)(dec! count n))
     (:bound (lo hi)
             (set! count (min hi (max lo count)))))))

;; expand image
(define count-test
  (let ((count 0))
    (lambda (key . args)
      (case key
        ((:reset)(apply (lambda ()
                          (set! count 0)) args))
        ((:inc)(apply (lambda (n)
                        (inc! count n)) args))
        ((:dec)(apply (lambda (n)
                        (dec! count n)) args))
        ((:bound)(apply (lambda (lo hi)
                          (set! count
                                (min hi (max lo count)))) args))
        (else key)))))

(count-test :reset)
;; 0
(count-test :inc 100)
;; 100
(count-test :inc 1)
;; 101
(count-test :inc 2)
;; 102
(count-test :bound -10 10)
;; 10
(count-test :reset)
;; 0
(count-test :inc 1)
;; 1

以下マクロのコード


LET OVER LAMBDA Edition 1.0

2010/05/10

『Schemeのマクロは変数衝突を「自動的に回避する」』

Schemeのマクロは変数衝突を「自動的に回避する」と書きましたが、一体どうやって 回避してるんでしょうか。
ローカル束縛(arithmetic-ifにおける変数var)の衝突の回避については、 マクロ展開ルーチンがマクロが挿入する変数varを衝突しないようにリネーム してやることで回避できます。gensymをマクロシステムが自動的にやってくれると 言っても良いでしょう。
これは・・・
syntax-rules syntax-case で defmacro!, dlambda, alambda, plambda ?



あと、これも。togetter を貼りつけてみたいというのもあったので。

勝手にトゥギャりました。誰でも編集できるにしているので、自由に編集してください。

LET OVER LAMBDA Edition 1.0プログラミングGauche


2010/04/24

LOL defmacro!


defmacro!。これを書いておかないと何も始まりませんね。LET OVER LAMBDA Edition 1.0は。

まだslimeの使い方がよくわかりません。C-c C-cはコンパイルで、C-x C-eがreplに読み込む、ということくらいでしょうか。その時、コード中に見つからないシンボルがあるとアンダーラインで示してくれるなど(↑画像)、ありがたいです。

schemeにもそういうのないのかな。quack.elにはたぶんないんですよね。


Gaucheのshiroさんも以下のようにおっしゃっているので、きっとslimeって多機能なんだろうなぁ。
shiro: うーむCL+slimeで作業してるとやっぱりgauche+quackは物足りなく感じるなあ。 http://bit.ly/b35LjH

LET OVER LAMBDA Edition 1.0

2010/04/13

LOL tree-leaves

これはtree-leaves%%までで十分だと思いましたが、どうなんでしょう。
予測できる使い方の範囲では、これが最も直感的で贅肉のない方法だと思う。
らしい。個人的には、むしろ直感的でなくなっているように思いますが・・・。


ところで、Gaucheで書くにあたり、何の気なしにfold-rightで書きましたが、これだとLOLに書かれているようなドットリストではうまくいきませんね。
fold-rightは関係ないですね。

このtree-leavesのところで「アナフォラ」という単語が出てきました。アナフォリックマクロ楽しみです。


LET OVER LAMBDA Edition 1.0

2010/04/11

LOL flatten

これもLOLより(というよりOn Lispより?)。Gaucheで書いてみましたが、これも探せばどこかにありそうですね。

fold-rightで書いてみましたが、大丈夫かな。なんか怪しいような気もする。もしかするとfoldでreverseな方が良いかな。いやfold-rightで大丈夫か。


追記

LOLより。Common Lispのlabelsはschemeのletrecみたいなもの、と考えて良いんだろう、きっと。なんかCLの方が美しい気がする(labelsに限らず)。


プログラミングGaucheLET OVER LAMBDA Edition 1.0On Lisp

2010/04/10

LOL mkstr, symb, group

mkstr, symb, groupはLet Over Lambdaで必要になるユーティリティ関数です。On Lispよりのものだそうです。On Lispは見事に積読中。
LOLはあの調子ですから読むのはサクサクなのですが、書くのが全然追いつきません。

internってなんぞ。symbの最後がvaluesなのもなぜだろう。わからないけど取り合えず放っておきます。以下コードはOn Lispより。

Gaucheで。(util.listに、groupと同等のslicesがあるそうです)

call-with-string-output-port・・・ってどこにあるんだろう。


(cut cons (+ a 1) <>) ≡ (lambda (x2) (cons (+ a 1) x2))
(cut list 1 <> 3 <> 5) ≡ (lambda (x2 x4) (list 1 x2 3 x4 5))
(cut list) ≡ (lambda () (list))
(cut list 1 <> 3 <...>)
≡ (lambda (x2 . xs) (apply list 1 x2 3 xs))
(cut <> a b) ≡ (lambda (f) (f a b))
部分適用便利だなー!

参考


追記

internの解説を教えていただきました。

プログラミングGaucheLET OVER LAMBDA Edition 1.0On Lisp

2010/04/06

defmacro: LOL nif

LET OVER LAMBDA Edition 1.0
マクロを使えば、他の言語では全く不可能なことが可能になる。 --Doug Hoyte
define-syntaxの書き方や仕組みも良くわかっていないのですが、取り合えずトライ。

define-syntaxの方はexprに副作用があっても1回しか評価されてない、ということで良いのかな。あれ、「,g」を「, g」と書いてるがそれは良いのか?

追記

展開してみれば良いのか。


プログラミングGaucheLET OVER LAMBDA Edition 1.0

defmacro: LOL nlet

マクロは、Lispが1つのプログラミング言語として有する唯一最大の強みであり、いかなるプログラミング言語においても唯一最大の強みである。  --Doug Hoyte
著者のLisp(のマクロ)マンセーっぷりがすごい。
(Gaucheで書いてみてます)


プログラミングGaucheLET OVER LAMBDA Edition 1.0

2010/01/27

ダイナミックスコープ

ってこういうものだったんですか。

 

SBCL

(defvar temp-special)

(setq temp-special 1)

(defun temp-special-returner ()
  temp-special)

(temp-special-returner)
; ->  1

(let ((temp-special 2))
  (temp-special-returner))
; -> 2

(temp-special-returner)
; -> 1

 

schemeだとこうはならんですね。常にレキシカルスコープ(こういう言い方していいのか知りませんが)ということですかね。

(define temp-special 0)

(set! temp-special 1)

(define temp-special-returner
  (lambda ()
    temp-special))

(temp-special-returner)
; -> 1

(let ((temp-special 2))
  (temp-special-returner))
; -> 1

 

dynamic-windを使うと同じようなことができるそうな。

 

funcall とか function とか #' とか・・・、今のところとても面倒でややこしい印象。まともに Common Lisp さわるの初めてです。

 

LET OVER LAMBDA Edition 1.0