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 |

2009-09-29

CLでClojureのキーワードが関数(マクロ)になってる風(2)

| 23:20 | CLでClojureのキーワードが関数(マクロ)になってる風(2) - わだばLisperになる を含むブックマーク はてなブックマーク - CLでClojureのキーワードが関数(マクロ)になってる風(2) - わだばLisperになる

前回のエントリーのコメント欄で、ローカルのsetf関数は普通にfletで書けることをquekさんに教えて頂きました。

自分も試したつもりだったのですが、どうも入れ子にする括弧の数か引数の取り方を間違えていたようです…。

HyperSpecにもちゃんと書いてあるしちゃんと確認すれば良かったなと('-'*)

滅多に使わなそうですが、ローカルのsetf関数は書けるんですねー。

(FLET (((SETF HELLO) (VAL &OPTIONAL VAR)
         (LIST 'HELLO VAL)))
  (SETF (HELLO) 'WORLD))
;⇒ (HELLO WORLD)

(LABELS (((SETF HELLO) (VAL &OPTIONAL VAR)
           (LIST 'HELLO VAL)))
  (SETF (HELLO) 'WORLD))
;⇒ (HELLO WORLD)

ということで関数版も書いてみました。

(IMPORT 'KMRCL:FLATTEN)

(DEFMACRO WITH-KEYWORD-FUNCTION (&BODY BODY)
  (LET ((KEYS (COLLECT-KEYWORD-SYMBOL BODY)))
    `(FLET (,@(MAPCAN (LAMBDA (K)
                        (COPY-LIST
                         `((,K (HASH-TABLE &OPTIONAL DEFAULT)
                               (GETHASH ,K HASH-TABLE DEFAULT))
                           ((SETF ,K) (NEW-VALUE HASH-TABLE)
                            (SETF (GETHASH ,K HASH-TABLE) NEW-VALUE)))))
                      KEYS))
       ,@BODY)))

(DEFUN COLLECT-KEYWORD-SYMBOL (LIST)
  (REMOVE-DUPLICATES
   (REMOVE-IF-NOT #'KEYWORDP (FLATTEN LIST))))
  • 動作
(LET ((TAB (MAKE-HASH-TABLE)))
  (SETF (GETHASH :FOO TAB) 0
        (GETHASH :BAR TAB) 0
        (GETHASH :BAZ TAB) 0)
  (WITH-KEYWORD-FUNCTION
    ;; 値を再度設定
    (SETF (:FOO TAB) 11
          (:BAR TAB) 22
          (:BAZ TAB) 33)
    ;; 値を確認
    (LIST (:FOO TAB)
          (:BAR TAB)
          (:BAZ TAB))))
;⇒ (11 22 33)

CLでClojureのキーワードが関数(マクロ)になってる風

| 00:10 | CLでClojureのキーワードが関数(マクロ)になってる風 - わだばLisperになる を含むブックマーク はてなブックマーク - CLでClojureのキーワードが関数(マクロ)になってる風 - わだばLisperになる

Clojureでは、ハッシュのキーが値を取り出す関数のような振舞いをするのが便利ですが、仕事帰りの電車でぼーっとしていたら、そういう感じに書けるようなマクロが思い浮かんだので書いてみました。

大雑把に、見付けたキーワードには全部関数を詰めています。

できれば、fletでローカル関数にしたかったのですが、setfで便利に展開してくれるのでmacroletにしときました。

ローカルのsetf関数を書く方法ってあったりするんでしょうか。

(IMPORT 'KMRCL:FLATTEN)

(DEFMACRO WITH-KEYWORD-FUNCTION (&BODY BODY)
  (LET ((KEYS (COLLECT-KEYWORD-SYMBOL BODY)))
    `(MACROLET (,@(MAPCAR (LAMBDA (K)
                             `(,K (HASH-TABLE &OPTIONAL DEFAULT)
                                 `(GETHASH ,',K ,HASH-TABLE ,DEFAULT)))
                          KEYS))
       ,@BODY)))

(DEFUN COLLECT-KEYWORD-SYMBOL (LIST)
  (REMOVE-DUPLICATES
   (REMOVE-IF-NOT #'KEYWORDP (FLATTEN LIST))))
  • 動作
(LET ((TAB (MAKE-HASH-TABLE)))
  (SETF (GETHASH :FOO TAB) 0
        (GETHASH :BAR TAB) 0
        (GETHASH :BAZ TAB) 0)
  (WITH-KEYWORD-FUNCTION
    ;; 値を再度設定
    (SETF (:FOO TAB) 66
          (:BAR TAB) 77
          (:BAZ TAB) 88)
    ;; 値を確認
    (LIST (:FOO TAB)
          (:BAR TAB)
          (:BAZ TAB))))
;⇒ (66 77 88)

2009-09-28

Smalltalkのブロック風

| 01:01 | Smalltalkのブロック風 - わだばLisperになる を含むブックマーク はてなブックマーク - Smalltalkのブロック風 - わだばLisperになる

Smalltalkの

[:x | x + 1]

のようなブロックを見て、ふとマクロを思い付いたので書いてみました。

(DEFMACRO BIND (&BODY BODY)
  (DO ((BODY BODY (CDDR BODY))
       (BINDS () (DESTRUCTURING-BIND (VAR VAL &REST IGNORE) BODY
                   (DECLARE (IGNORE IGNORE))
                   (PUSH `(,(INTERN (SYMBOL-NAME VAR)) ,VAL) 
                         BINDS))))
      ((NOT (KEYWORDP (CAR BODY)))
       `(LET (,@(NREVERSE BINDS))
          ,@BODY))))
(BIND :X 10 :Y 20 :Z NIL
  (LIST X Y Z))
;⇒ (10 20 NIL)

ただ単に、変数束縛部とボディを分けるのにシンボルの種類の違いで分けられるなという思い付きでございました。

リーダーマクロを使って [:x (+ 1 x)] ⇒ (lambda (x) (+ 1 x))というのもありかもしれません。

というかこのエントリーのタイトルからするとこっちが本筋ですね…。

2009-09-27

map-accum

| 20:12 | map-accum - わだばLisperになる を含むブックマーク はてなブックマーク - map-accum - わだばLisperになる

map-accumって何者だということで、動作を理解すべくmap-accumを作ってみました。

名前そのまんまで説明になってないですが、mapにアキュムレータが付いたものなんですね。

たまに使いたくなる時がありそう。

ちなみにここ数日、electric-shift-lockモードを導入してコードを大文字で書いてみています。

大文字で書くと何か面白い発見があるかと思いましたが、今のところ何の発見もありません…。

;; 再帰でLIST版
(DEFUN MAP-ACCUM (F SEED &REST LISTS)
  (LABELS ((FROB (F SEED ANS LISTS)
             (IF (SOME #'ENDP LISTS)
                 (VALUES ANS SEED)
                 (MULTIPLE-VALUE-BIND (A ACC)
                     (APPLY F (APPEND (MAPCAR #'CAR LISTS) (LIST SEED)))
                   (MULTIPLE-VALUE-BIND (RES ACC) 
                       (FROB F ACC (APPEND ANS (LIST A)) (MAPCAR #'CDR LISTS))
                     (VALUES RES ACC))))))
    (FROB F SEED () LISTS)))
;; 総称関数版
(DEFGENERIC MAP-ACCUM (F SEED SEQUENCE &REST REST))
(DEFMETHOD MAP-ACCUM ((F FUNCTION) SEED (SEQUENCE SEQUENCE) &REST REST)
  (LET ((MIN-LEN (APPLY #'MIN (LENGTH SEQUENCE) (MAPCAR #'LENGTH REST))))
    (DO ((ACC SEED)
         TEM
         (IDX 0 (1+ IDX))
         (SEQS (CONS SEQUENCE REST))
         (RES (MAKE-SEQUENCE (CLASS-OF SEQUENCE) MIN-LEN)))
        ((= IDX MIN-LEN) (VALUES RES ACC))
      (SETF (VALUES TEM ACC)
            (APPLY F (NCONC (MAPCAR (LAMBDA (A) (ELT A IDX))
                                    SEQS)
                            (LIST ACC))))
      (SETF (ELT RES IDX) TEM))))
(MAP-ACCUM (LAMBDA (X Y Z ACC) 
             (VALUES (LIST ACC X Y Z) (1+ ACC)))
           0
           '(A B C E E)
           '(F G H I)
           '(J K L))
;⇒ ((0 A F J) (1 B G K) (2 C H L)),
;   3

(MAP-ACCUM (LAMBDA (X Y ACC) 
             (VALUES (IF (CHAR< X Y) X Y)
                     (1+ ACC)))
           0
           "abCd"
           "ABcD")
;⇒ "ABCD",
;   4

2009-09-25

バリューセルにも関数

| 23:32 | バリューセルにも関数 - わだばLisperになる を含むブックマーク はてなブックマーク - バリューセルにも関数 - わだばLisperになる

「#'とか付けるのだるい」「美しくない」という声を良く聞くのですが、目的のシンボルのバリューセルに関数を詰めれば、#'を付けなくても、まあ、大体似たことはできるんですよね。

ということで、fvletというfletでローカル関数を定義しつつ、関数のシンボルのバリューセルにも関数を詰めるというマクロを書いてみました。

「ああ、なんかバリューセルが潰れて損した気がする」と思った貴方は、心の底からLISP2の人です。

(DEFMACRO FVLET ((&REST SPECS) &BODY BODY)
  (LET ((SYMS (MAPCAR #'CAR SPECS)))
    `(FLET (,@SPECS)
       (LET (,@(MAPCAR (LAMBDA (X) `(,X (FUNCTION ,X)))
                       SYMS))
         ,@BODY))))
(IMPORT 'KMRCL:COMPOSE)

(FVLET ((FOO (X) (* 2 X))
        (BAR (X) (LIST X X)))
  (MAPCAR (COMPOSE BAR FOO) 
          '(1 2 3 4)))
;=> ((2 2) (4 4) (6 6) (8 8))

※追記

正確にはバリューセルを使うにはletの変数をスペシャルにしないといけないとzicさんより指摘がありました。

まったくその通りで、上記fvletの中でfooやbarをsymbol-valueするとどういうことかが分かります。

上記のコードだとletで作ったレキシカル環境を操作することになります。

2009-09-21

electric-shift-lock-mode

| 23:52 | electric-shift-lock-mode - わだばLisperになる を含むブックマーク はてなブックマーク - electric-shift-lock-mode - わだばLisperになる

70年代後半位までLISPのソースは大文字で書かれているものが多いのですが、70年代後半に登場したLispマシンのエディタ(ZWEI/Zmacs)にも、そんな時代を反映した、Electric Shift Lockという機能があります。

これは、CAPSキーをオンにしてくれるようなモードで、Shiftを押さない状態が大文字、逆にShiftを押すと小文字というモードです。

気が効いているのは、文字列やコメント等、大文字と小文字を区別する必要がある場所では、通常通りShift押下で大文字になるというところ。

;; foo
(DEFUN FOO (N)
  "foo"
  (LIST N))

こんな感じのがすらすら簡単に書けます。

以前からEmacs上で自作してみたかったのですが、連休中にちょっと挑戦してみようと思いたちました。

しかし、既に前に同じものがあったら嫌だなあと思い、念の為ググってみたら、ずばりを見付けてしまいました(笑)

John Paul Wallingtonさんが、去年の5月に作られていたようです。こんなニッチすぎるところに目をつけるとは…。世界は狭い。

しかし、どうもWallingtonさん作の挙動は、Shiftを押しても小文字は出ず、全部大文字になるようです。

連休中は、ぼーっとこの辺りをLispマシン風の挙動に変えてみたいです。

いまどき大文字でコードを書くということも少ないですが、気分を変えて大文字ベースで書いてみるのも一興かもしれません。

SQLでなんとなくこのモードが使えるかと思ったりもしますが、微妙な気もします。

2009-09-20

LISP処理系のTwitterアカウント

| 22:05 | LISP処理系のTwitterアカウント - わだばLisperになる を含むブックマーク はてなブックマーク - LISP処理系のTwitterアカウント - わだばLisperになる

ふと、Franz社のページを久し振りに見たところFranz社のTwitterのアカウントが付いていました。

なるほど、広報活動もTwitterを活用する時代。

LispWorks等もやってないかと探しましたが、今のところ無いようです。

適当に探したら、Franz以外には、Clojure、CLISP等がみつかりました。

no title

no title

no title

Franz以外は、発言数も少ないようです。

ちなみに、Shibuya.lispは、こちらです。

no title

2009-09-11

続・lisp-modeと表示の畳み込み

| 00:09 | 続・lisp-modeと表示の畳み込み - わだばLisperになる を含むブックマーク はてなブックマーク - 続・lisp-modeと表示の畳み込み - わだばLisperになる

前回、outline-modeについてつらつらと書いたところ、

Chaton CL部屋でd:id:lequeさんに

S 式の折り畳みなんですが hs-minor-mode はどうでしょう

とhs-minor-modeを教えてもらいました。

hs-minor-modeは畳み込み専用のモードらしく、色々カスタマイズもできるようです。

これは良さそうな予感!

早速、minor-modeなので、slimeと共存させてみます。

(defun foo ()
 :foo)

というところで、

M-x hs-toggle-hiding

すると、

...

となります。

…あれ、

(defun foo ...

みたいになるということでしたが…。

ちょっとググってみたところでは、この現象は、自分が利用しているEmacs 23.50.1のバグらしいことが判明しました。

ということで、最新のCVS版をインストールして試してみたところ

(defun foo ()...)

という風に良い感じに表示されるようになりました。

これより以前のhs-minor-modeでは、

(defun foo ...

と表示されていたということなので、今回のバグフィックスのついでに改善されたのかもしれません。

また、

というものも見つけたので、これも併用。

左端に折り畳める印が出て、これをマウスでクリックすると折り畳みを開閉できます。

  • 開いた状態

http://gyazo.com/16cafe3296882bc0f82656cbf043f797.png

  • ポチッと閉じる

http://gyazo.com/2db10ec9d97703711d04c226109b37c6.png

2009-09-07

lisp-modeとoutline-modeの併用

| 04:55 | lisp-modeとoutline-modeの併用 - わだばLisperになる を含むブックマーク はてなブックマーク - lisp-modeとoutline-modeの併用 - わだばLisperになる

今日ぼんやりとGoogle Code Archive - Long-term storage for Google Code Project Hosting.を眺めていたのですが、この最後のバッファローカルの変数を設定しているところで

;; Local Variables: **
;; mode:lisp **
;; outline-regexp: ";;; " **
;; End: **

となっているのに気付きました。

なるほど、outline-modeで、;;;を目印に設定すれば上手く畳めるのかもしれません。

ということでページが見つかりませんでした – bookshelf.jp等を参考にしつつちょっと試してみました。

;; slime-modeへフック
(add-hook 'slime-mode-hook
          (lambda () 
            (setq outline-regexp ";;; ")
            (outline-minor-mode t)))

;; superキーに割付け
(define-key slime-mode-map [(super ?a)]
  'show-all)

(define-key slime-mode-map [(super ?d)]
  'hide-subtree)

(define-key slime-mode-map [(super ?t)]
  'hide-other)

と設定してみる。

コードを書いて試してみる

;;; foo
(defun foo ()
  :foo)

;;; bar■
(defun bar ()
  :bar)

;;; baz
(defun baz ()
  :baz)

と書く。

hide-otherで畳んでみる

;;; foo
;;; bar■
(defun bar ()
  :bar)
;;; baz

なるほど、なるほど。

畳み込み表示のための専用のelispがあったような気もしますが、outline-minor-modeの利用も手軽かもしれません。

他にもっとLISPを書く際に便利で簡単な畳み込みの方法をご存知でしたら是非教えてください!

2009-09-04

エントリ再利用 (1)

| 03:26 | エントリ再利用 (1) - わだばLisperになる を含むブックマーク はてなブックマーク - エントリ再利用 (1) - わだばLisperになる

引きこもっている時にはどしどし更新していたこのblogですが、やはり仕事をするようになると何かと疲れたりしてしまいblogのネタを捻出する気力もなくなりがちです。

どうにかして楽をしてブログを更新できないかなと思ったのですが、去年や2年前の今頃は何を書いてたのかを振り返ってみるという安易な方法を考えつきましたので早速試してみたいと思います。

去年(2008年)の8月末から9月始め

そういえば、LingrでCL勉強会をやっていまいした。よくも毎週やっていたものです。そして今思えば、毎週参加して頂いた皆さんには感謝ですね。

Chaton CL部屋になってから一回やってみようと思いましたが、ネタの応募が集まったらという開催条件がネックになり未だ開催されていません。とりあえず開催するのが吉だったかも。

そういえば、*Lispのチュートリアルをやってみているのでした。開始から2年近く経つのですが、進みが遅いので全然終わりません。ただ内容を写経してるだけなのに…。

2007年の8月末から9月始め

このcadrグループを作ったのは確か、2007年の11月頃だと思ったので、これは、はてダのエントリーを引っ越してきたものですね。

日課練習と称して何故かTAOのマニュアルを元にマクロや関数を延々をCL上に作っていました。

この日は、loopマクロですが、CLのloopとは全く別物です。TAOには面白い構文が沢山あるので是非マニュアルを眺めてみて下さい。

TAO/ELISマニュアル

2006年の8月末から9月始め

CADRのエミュレータが新しくなって喜んでいました。

Bolio形式で書かれたLispマシンのマニュアル(CADRエミュの配布物の中に埋もれています)をHTMLにして眺めたりLispマシンに執心でしたが、この頃LISPはまったく書いてないし、その前に書けませんでした。

そもそも自分は、レトロコンピューティングが好きで、それでLispマシンに興味が行き、そこからLispに興味が移ったのでした。Lispマシン万歳!

今後もっとレトロコンピューティングやレトロLISPをネタにエントリーを書いてみたいところです。