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 |

2011-01-18

マクロ 99問 P02

| 21:31 | マクロ 99問 P02 - わだばLisperになる を含むブックマーク はてなブックマーク - マクロ 99問 P02 - わだばLisperになる

P01に引き続いてやってみました。M-99 P02

INC1を作成せよ
テーマ:変数の補足

(let ((x 0))
  (inc1 x)
  x)
≡ (let ((x 0))
     (setq x (+ x 1)))
;=> 1

inc1(x)というのを、x = x + 1という風に展開しろというお題です。

inc1のようなものは、CLでは、関数ではできないことの1つで、マクロにする必要がありますが、他の言語も大体同じかなと思います。

早速チャレンジ。まずは、CL

Common Lisp
(defmacro inc1 (var)
  `(setq ,var (1+ ,var)))

(let ((x 0))
  (inc1 x)
  x)
;=> 1

31秒でした。

次にGauche(Scheme)

Scheme (Gauche)
(define-syntax inc1
  (syntax-rules ()
    ((_ var) (set! var (+ 1 var)))))

(let ((x 0))
  (inc1 x)
  x)

こちらは57秒。

今回のお題ならば、Dylanでも可能なので、Gwydion Dylanで

Dylan
module: p02
synopsis:
author:
copyright:

define macro inc1
 { inc1(?var:expression) }
    => { ?var := ?var + 1 }
end macro inc1;

define function main(name, arguments)
  let var = 1;
  format-out("var => %=\n", var);
  inc1(var);
  format-out("var => %=\n", var);
  exit-application(0);
end function main;

// Invoke our main() function.
main(application-name(), application-arguments());
var => 1
var => 2

4分かかりました。

REPLがないとなかなか辛いです。今後問題は、複雑になりますが、Dylanではマクロ展開とかどうやって確認するのやら…。

GOO
(ds inc1 (,arg)
  `(set ,arg (+ 1 ,arg)))

goo/user 0<=  (let ((x 0))(inc1 x)x)
goo/user 0=> 1

30秒。

Arc
(mac inc1 (arg)
  `(= ,arg (+ 1 ,arg)))

arc> (let x 0 (inc1 x) x)
1

32秒

GOOもArcも似たようなものです。

どうもinc1一番簡単で無難な問題に思えてきました。

2011-01-16

マクロ 99問 P01 補足

| 14:02 | マクロ 99問 P01 補足 - わだばLisperになる を含むブックマーク はてなブックマーク - マクロ 99問 P01 補足 - わだばLisperになる

M-99の前回の回答ですが、コメント欄にて色々と教えて頂きました。ありがとうございます!

lkozima2011/01/15 23:31
こんな書き方もできますね。慣れてないと読めなそうですが。
(defmacro listq (&rest args) `',args)

なるほど!、確かにこちらの方が簡潔です。

解釈としては、

`(quote ,'(a b c d))

となっていて、quoteされた式をunquoteした中身でquote式を作成する、という感じです。

前回の自分の回答は、

`(list ,@(mapcar (lambda (x) `(quote ,x)) '(a b c d))))

というような感じで、(list 'a 'b 'c 'd)を作成しています。

defmacroの&restが毎回新規にリストを作成するならばどちらも同じことな気もしますが、ちょっと追い切れていません。

SaitoAtsushi2011/01/16 09:17
syntax-rules だと再帰的にしなくても出来ますよ。
(define-syntax listq
  (syntax-rules ()
    ((_ arg ...) (list 'arg ...))))

なるほど、パターンマッチで全部解決できるのですね!。これは勉強になります。

ついでなので他のLISP方言でもやってみました。

Dylan

DylanのシンボルのLISP風解釈が良く分からず挫折。

具体的には、変数の名前をシンボルに変換することが可能なのかどうか分かりませんでした。

また、Dylanでは、シンボルは、foo:や、#"foo"と表記できますが、quoteは必要なかったりします。

しかし、実はできたりするのかもしれません。

GOO
(ds listq (,@args) `',args)

(ds listq (,@args)
  `(list ,@(map (op list 'quote _)
                args)))
Arc
(mac listq args `',args)

(mac listq args
  `(list ,@(map [list 'quote _] args)))

GOOもArcも伝統マクロなのでCLと同じになります。

色々試してみるとシンボルの扱いがからんできていて割とLISPのマクロを前提とした問題な気がしてきました。

第1問目としてはあまり良くないかもしれないですね。

2011-01-15

マクロ 99問 P01

| 19:44 | マクロ 99問 P01 - わだばLisperになる を含むブックマーク はてなブックマーク - マクロ 99問 P01 - わだばLisperになる

思い付きで作ってみたM-99ですが、果して役に立つのかまったく分からないので自分で問いてみることにしました。

時間を計測したら燃えるかと思い時間を測ってみましたが、結果は、52秒。

多分、マクロを書いたことがある方なら1分以内で解けるんじゃないでしょうか。

引数をクォートについてがテーマなのですが、1問目にしては難しいテーマなのかもしれません。

(let ((ut 0))
  (defun start ()
    (setq ut (get-universal-time)))
  (defun check ()
    (- (get-universal-time) ut)))

(start)
;=> 3504076885

;; 与えられた引数を全てQUOTEしてリストとして返すLISTQを作成せよ
;; テーマ:引数のクォート

(listq a b c d e)
≡ (list 'a 'b 'c 'd 'e)
;=> (A B C D E)

(defmacro listq (&rest args)
  `(list ,@(mapcar (lambda (x)
                     `(quote ,x))
                   args)))

(check)
;=> 41
;; テストするの忘れてた…

(listq a b c d)
;=> (A B C D)

(check)
;=> 52

ついでにGaucheでも

;; gauche
(use srfi-19)

(define *ct* 0)

(define (start)
  (set! *ct* (current-time))
  (time-second *ct*))
(define (check)
  (time-second (time-difference (current-time) *ct*)))

(start)
;=> 1295090821

(define-syntax listq
  (syntax-rules ()
    ((_) (list))
    ((_ arg rest ...)
     (cons (quote arg)
           (listq rest ...)))))

(listq a b c d e)
;=> (a b c d e)

(check)
223

(listq)
;=> ()

define-syntaxに慣れてないので使い方間違ったりして223秒かかりました。

ちなみに、Dylanもやってみようかなと思ったのですが、手元の開発環境が動かなくなっておりました…。