パスワードを忘れた? アカウント作成
509241 journal
スラド

t-nissieの日記: admire 4

日記 by t-nissie
admire [アドマイア] vt. …にあこがれる、敬服する、見とれる

LispとかPrologとかはぼくにとってはあこがれの的なのですが
http://practical-scheme.net/trans/icad-j.html に書いてある

(defun foo (n)
    #'(lambda (i) (incf n i)))

Lispのすごさをあらわす何かだそうですが、何がしたいかさっぱりわかり
ません。Lisperの方、教えてください。Emacs Lisp だと#は要らなくて

(defun foo (n)
    '(lambda (i) (incf n i)))

でよいのでしょうか。fooをどうやって実行するとすごさがわかるのでしょうか。

オシエテオシエテ}λλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλ...
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • (defun foo (n) #'(lambda (i) (incf n i)))



    (define foo (lambda (n) #'(lambda (i) (incf n i))))

    と等価なので、これを評価すると引数をひとつ取る foo という関数ができる。つまり、

    foo => (lambda (n) #'(lambda (i) (incf n i)))

    ということになる。で、これを使うには例えば、

    (defvar bar (foo 5))

    を評価すると

    bar => #'(lambda (i) (incf 5 i))

    という、5 を初期値とした bar というアキュムレータができて、

    (funcall bar 3)

    を評価すると 8 が返り、かつ副作用として

    bar => #'(lambda (i) (incf 8 i))

    になっている(incf は最初の引数の先を書き換えちゃうから)。その後でまた

    (funcall bar 7)

    とすると、15 が返り、

    bar => #'(lambda (i) (incf 15 i))

    になっている……

    …………って考えればいいんでしたっけか? (←ブランク長いんで全っ然自信無し)

    ;; SBCL を落してきて、
    ;; 一応そういう風に動いてるように見えるのは確認しましたけど。
    • etsavさん、詳しい解説ありがとうございます。

      > という、5 を初期値とした bar というアキュムレータができて、

      なるほど。「アキュムレータジェネレータ」の意味がやっと判りました。

      悲しいかな、sbcl-1.0 は、Linux kernel の NPTL threading を使うらしく、
      今使っているちょっと古めのLinux Boxにはインストールできませんでした。

      で、Emacs Lispで試してみたのですが、またまた悲しいかな、ダメでした:
      ; accumulator generator
      (defun foo (n)
          '(lambda (i) (incf n i)))
      => foo

      (symbol-function 'foo)
      => (lambda (n) (quote (lambda (i) (incf n i))))

      (defvar bar (foo 5))
      => bar

      (symbol-function 'bar)
      => (lambda (quote (foo 5)))

      (bar 5)
      => Error
      *scratch*バッファでC-jを押したとき出てくるものを=>の後ろに書いてます。
      --
      love && peace && free_software
      t-nissie
      親コメント
      • incf が無いようなので、 とりあえず

        (defmacro incf (n i) (list 'setq n (list '+ n i)))

        で代用。 function の省略形 #' は使えるみたい(これは quote の省略形 ' とは別物なのです)。

        これで後は同じようにできるかなと思ったんですが、

        (setq bar (foo 5))

        に対して

        bar => (lambda (i) (incf n i))

        となってしまって、

        (funcall bar 3)

        で (incf n 3) を評価しようとして、 変数 n が定義されてないと言われちゃいます。 バインドの仕方が違うのかなぁ……

        ;; と言うか、この使い方だと incf の定義もかなり怪しい気がする。

        ;;; <ecode> って <blockquote> になっちゃうのか……

        親コメント
    • $ irb
      irb(main):001:0> def foo(n)
      irb(main):002:1> lambda {|i| n += i}
      irb(main):003:1> end
      => nil
      irb(main):004:0> bar = foo(5)
      => #<Proc:0x40222a3c@(irb):2>
      irb(main):005:0> bar.call(3)
      => 8
      irb(main):006:0> bar.call(7)
      => 15
      irb(main):007:0> qux = foo(1)
      => #<Proc:0x40222a3c@(irb):2>
      irb(main):008:0> qux.call(2)
      => 3
      irb(main):009:0> qux.call(3)
      => 6
      irb(main):010:0> bar.call(1)
      => 16 (barとquxとは独立)

      --
      love && peace && free_software
      t-nissie
      親コメント
typodupeerror

あつくて寝られない時はhackしろ! 386BSD(98)はそうやってつくられましたよ? -- あるハッカー

読み込み中...