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

(funcall #'foo) vs (funcall 'foo)

| 19:51 |  (funcall #'foo) vs (funcall 'foo) - わだばLisperになる を含むブックマーク はてなブックマーク -  (funcall #'foo) vs (funcall 'foo) - わだばLisperになる

Twitterでもぶつぶつ言っていたのですが、(FUNCALL 'FOO)と、(FUNCALL #'FOO)では色々と意味が違ってきます。

基本的に、(FUNCTION FOO)を使った場合は、関数オブジェクトを扱っているような感じかなと思いますし、(QUOTE FOO)の場合は、SYMBOL-FUNCTIONを実行時に呼ぶという感じかなと思います。

他にもなんやかんやとありますが、インライン展開でも違いがあることがあるというのをみつけたので記念にメモ。

元はといえば、SBCLのFUNCTIONのところのコメントに書いてあったことなのですが、インライン展開にも違ってくるようです。

どういうことかというと、

(declaim (inline bar))
(defun bar ()
  "こんにちは")

と定義しておいて、それを呼び出す側で、 (quote)と (fuction)のものを比較してみます。

quoteを使う

(defun foo ()
  (funcall 'bar))
(foo)
; disassembly for FOO
; 079DBA04:       BA18000000       MOV EDX, 24                ; no-arg-parsing entry point
;       09:       488B05A0FFFFFF   MOV RAX, [RIP-96]          ; #<FDEFINITION object for BAR>
;       10:       B908000000       MOV ECX, 8
;       15:       FF7508           PUSH QWORD PTR [RBP+8]
;       18:       FF6009           JMP QWORD PTR [RAX+9]
;       1B:       CC0A             BREAK 10                   ; error trap
;       1D:       02               BYTE #X02
;       1E:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       1F:       54               BYTE #X54                  ; RCX

当然かもしれませんが、インライン展開されません。

functionを使う

(defun foo2 ()
  (funcall #'bar))
(foo2)
; disassembly for FOO2
; 083A0BC4:       488B15A5FFFFFF   MOV RDX, [RIP-91]          ; "こんにちは"
                                                              ; no-arg-parsing entry point
;       CB:       488BE5           MOV RSP, RBP
;       CE:       F8               CLC
;       CF:       5D               POP RBP
;       D0:       C3               RET
;       D1:       CC0A             BREAK 10                   ; error trap
;       D3:       02               BYTE #X02
;       D4:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       D5:       54               BYTE #X54                  ; RCX

展開してみると埋め込まれていることが分かります。

大抵の場合においてFUNCTIONを使っておけば良いかなというところで、あえてFUNCTIONを使わないのだという場合には、むしろ(FUNCALL (SYMBOL-FUNCTION 'FOO))と書いた方がわかりやすいかもしれません。まあ、(FUNCALL 'FOO)の方が(FUNCALL #'FOO)より見た目が短かくて簡潔なのですが…。

lambdaの形とletの形

| 18:35 | lambdaの形とletの形 - わだばLisperになる を含むブックマーク はてなブックマーク - lambdaの形とletの形 - わだばLisperになる

letはlambdaを変形すれば作ることができるというのはよく知られているかと思います。

ふとmap系の関数もlambda系な配置なので、これをlet系に変形したらどうかなと思い、

(defmacro mlet ((&rest binding) &body body)
  `(mapcar (lambda (,@(mapcar #'car binding))
             ,@body)
           ,@(mapcar #'cadr binding)))

のようなものを書いてみました。

(mlet ((x '(1 2 3 4 5))
       (y '(a b c d e)))
  (list x y))
;=> ((1 A) (2 B) (3 C) (4 D) (5 E))

dolistの複数回せるdolistsというマクロを良くみますが、それがリストの返り値を返すものというところでしょうか。

これは絶対他の人も考えてるだろうなと思ったのでmletとかlmapとかmaplet等色々な組み合わせで検索してみたところ、そのものずばりなErann Gatさん作のmapletをみつけました。

(defmacro maplet (bindings &body body)
  `(mapcar (fn ,(mapcar #'car bindings) ,@body)
           ,@(mapcar #'second bindings)))
(maplet ((x '(1 2 3 4 5))
         (y '(a b c d e)))
  (list x y))
;=> ((1 A) (2 B) (3 C) (4 D) (5 E))

mapletという名前の方が良いですね。

mapcarとmapletの違いですが、mapletは構文にする必要があるのでマクロになるため、APPLYに渡す、ということができなくなったりします。また、無名関数以外を渡すときに逆に引数を書いてやらないといけない手間が増えたりしますが、無名関数を書くのが面倒ということの方が多い気がするのでmapletも結構便利かもしれないと思いました。

ちなみに、似たようなところでは、TAOのimageがあり

(image i '(1 2 3 4) (* 2 i))
;=> (2 4 6 8)

という風に括弧が少ない版のmapletという感じです。dolistの括弧が少ない版とも考えられるかもしれません(ボディ部は1つの式しか取れないようです。)

また、これを拡張した、imagenというのがあり、mapletの括弧が少ない版という感じです。

(imagen (i '(1 2 3 4))
        (j '(a b c d))
        (list i j))
;=> ((1 A) (2 B) (3 C) (4 D))

lambda <=> let で色々変形を試してみると思わぬ発見があるやもしれません。

オブジェクト指向コンピューティング

| 18:20 | オブジェクト指向コンピューティング - わだばLisperになる を含むブックマーク はてなブックマーク - オブジェクト指向コンピューティング - わだばLisperになる

昨年に復刊して驚いた「Common Lisp オブジェクトシステム」もCLOSを知る上では良いかなと思うのですが「CLOSCLOS MOPを知るには良い本」的な紹介を良く耳にする気がしています。

この本についての個人的な感想は以前にも書いたのですが、

どちらかというと言語の実装者向けかなあと思っています。

それでタイトルの本なのですが、オブジェクト指向のシステムの解説の一つとして40ページ程のボリュームでCLOS MOPが取り上げられていて、実際にコードの例も示されているという、日本語の本にしては珍しい本です。

また、オブジェクト指向を解説する本としても、かなりマニアックで、Smalltalkあり、リフレクションあり、並列分散オブジェクト指向言語のABCLなども取り上げられつつ、という感じです。

先日の米澤教授の最終講義で並列分散オブジェクト指向のABCLって面白そう!と思った方にもお勧めかなと思います。

それで現在この本は絶版のようなのですが、以前からAmazonでウォッチしているところでは、何十円だったり一万円を越えたりという感じです。(現在衝撃の48円)

ゲスト



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