2008年9月30日火曜日

ほぼ日刊xyzzy新聞

タイトルはホッテントリメーカーから。日刊とか無理。

非同期って恐いねというお話。

まずは関数を3つ用意

(defun process-list ()
  "バッファプロセスのリスト."
  (remove-if-not #'processp
                (mapcar #'buffer-process (buffer-list))))

(defun running-process-exist-p ()
  "動作中のプロセスがあるか."
  (some #'(lambda (pid)
            (case (process-status pid)
              (:run t)
              (:exit nil)))
        (process-list)))

(defun kill-all-subprocess ()
  "バッファプロセスをすべて殺す."
  (every #'kill-process (process-list)))

次に何かxyzzyからプロセスを走らせる(M-x: shell とか)

で、ここで上の関数を使って動作中のプロセスをすべて消したいわけです。 別にタイミングを気にしなければ (kill-all-subprocess) だけでも良いんだ ろうけど、ちょっと時間差が気になるコードを書いていたのでこんなS式を書 いてみた。

これならloopフォームを抜けたときには動作しているプロセスが完全になくな っているはず。

(loop (if (running-process-exist-p)
          (kill-all-subprocess)
        (return t)))

意気揚々と実行(C-x C-e)。確かにプロセスは消えた。そこまではいいけど...

何故かxyzzy本体まで落ちた。

...

あるえー(・3・)

とりあえず次ので解決したことにしておく


(loop (if (running-process-exist-p)
       (and (kill-all-subprocess)
            (sleep-for 0.5))
     (return t)))

第18回CL勉強会@Lingrセルフ反省会

仮眠のつもりがぐっすりとか、どんだけだよ。

ということで過去ログを見ながらの勉強会参加でした。
お題はakaさんによる、CLのパーシステンス(persistence)のお話。

こういう概念、それをソフト・ハードウェアで実現する方法があるということを知 ることができたことが自分にとっての収穫でしょうか。リアルタイムじゃなかった のは残念だけど、勉強になりました。OSのハイバネーションとか、へー。 途中出てきた単語の"OO"って"Object-Oriented"(オブジェクト指向)の略かな?

あと、Schemeの継続はパーシステンスの一種なのかなと思った。 OnLispでの解説くらいでしか継続の知識無いからよく分からないけど。

後半のCLOS、AllegroCacheのあたりは正直さっぱりです。勉強します。

30分枠で勉強会の進行役か…話せるネタが無い…

2008年9月22日月曜日

xyzzyでarglist関数っぽいの


(defun arglist (symbol)
  "シンボル関数の引数をリストで返す."
  (if (symbolp symbol)
      (let* ((fn (symbol-function symbol))
             (cl (and (si:*closurep fn) (si:closure-body fn))))
        (cond ((si:*builtin-function-p fn)
               (get symbol 'si::builtin-function-argument))
              ((eq (car cl) 'lambda)
               (cadr cl))
              ((eq (car fn) 'macro)
               (cadr fn))))
    (error "not symbol: ~S" symbol)))

(arglist 'nth)            ; =>(lisp::n list)
マクロ使えば関数引数(arglist #'car)とかにも使えそうだけど、組み込み関数からのシンボルの取り出し方が分からない。

2008-09-25T19:36:19+09:00 [追記]

マクロで無理やり書き直してみた。見た目ほとんど変わってない。

(defmacro arglist (x)
  (let* ((fn (coerce (if (eq (car x) 'lambda)
                         x (cadr x))
                     'function))
         (cl (and (si:*closurep fn) (si:closure-body fn))))
    (cond ((si:*builtin-function-p fn)
           `(get (cadr ',x) 'si::builtin-function-argument))
          ((eq (car cl) 'lambda)
           `(cadr ',cl))
          ((eq (car fn) 'macro)
           `(cadr ',fn)))))
これで関数シンボルとかラムダ式とかにも使えるはず。

# マクロの側面しか見てない使い方だなあ…

2008-10-01T08:28:28+09:00 [追記の追記]

NANRI さんのコメントを受けてもう一度関数で書き直す。

横幅が狭いので多少インデントに無理があるのはご愛嬌ということで。

(defun arglist (x)
  (let* ((fn (or (and (consp x) (eq (car x) 'macro) x)
                 (coerce x 'function)))
         (cl (and (si:*closurep fn) (si:closure-body fn))))
    (cond ((si:*builtin-function-p fn)
           (labels ((symbol-builtin-function-name-p (sym)
                      (and (fboundp sym)
                           (si:*builtin-function-p 
                            (symbol-function sym))
                           sym))
                    (builtin-function-name (f)
                      (when (string-match "#<function: \\(.+\\)>"
                                          (princ-to-string f))
                        (match-string 1))))
             (get (some #'symbol-builtin-function-name-p
                        (find-all-symbols
                         (builtin-function-name fn)))
                  'si::builtin-function-argument)))
          ((eq (car cl) 'lambda)
           (cadr cl))
          ((eq (car fn) 'macro)
           (cadr fn)))))
;;; テスト
;;; 関数オブジェクト (組み込み、普通の、ラムダ)
(arglist #'car)                 ; (list)
(arglist #'arglist)             ; (x)
(arglist #'(lambda (n) (1+ n))) ; (n)
;;; シンボル (組み込み、普通の、マクロの)
(arglist 'car)                  ; (list)
(arglist 'arglist)              ; (x)
(arglist 'when)                 ; (lisp::test &body lisp::body)
;;; コンスセル (ラムダ式、マクロ)
(arglist '(lambda (n) (1+ n)))  ; (n)
(arglist #'when)                ; (lisp::test &body lisp::body)

いい感じです。

問題は実用性が無いことかな。

第17回CL勉強会@Lingrセルフ反省会

CommonLisp開発環境の話でした。

9/20第17回慢性的CL勉強会@Lingr 8時だョ!全員集合まとめ

以下、自分的に気になった点。

  • Linux使い多いなあ。Windowsじゃあまともに開発しにくいのはわかるが。
  • 1.括弧は最初に対で入力する派?2.先から書いて行く派?
    結構2が多くてびっくり。自分1です。 ()→(defun hoge)→(defun hoge (lst))という順番 手動で括弧を入れるから、たまにShiftキー離すタイミングがずれて"(9"とか入力してしまう罠。 ↓先から書いて行く派の方の意見
    # 最後のカッコをどりゃーっと入れていると爽快感がある。
    # なんていうか綴じ括弧を連続で入れてるとテンションが上がってくるんですよww
    なるほど。。。
  • onjoさんによるCommonLisp環境紹介@GoogleDocs
    コレ見てSLIMEに少し興味を持った。今使っているxyzzy環境の便利なところといえば
    • 関数、変数リファレンス (ldoc,funsig,info-modoki,hyperspec)
    • シンボル補完 (lisp-complete-symbol)
    の部分が大きいから(あと起動の早さ)、SLIMEでもこれらが使えるならEmacs環境もありかもしれないと思った。
  • CLISPの引数表示
    引数が見えにくいのは最適化されているから、らしい。 これはCLISPをソースからビルドする必要がありそう。
    (arglist 'nth)
    =>(#:ARG0 #:ARG1)
    ; マクロだと見える?
    (arglist 'defun)
    =>(SYSTEM::FUNCTION-NAME SYSTEM::LAMBDA-LIST &BODY SYSTEM::FORMS)
    # Ω kosh
    # CLISPごった煮のおかげでarglistが便利になりそうな予感w
    # Ω g000001
    # arglist機能は、30年前のLispマシンからある機能で、
    # これがない開発環境とか、むしろ30年前以前w
    ごめんなさい、ただの勘違いでした。 でもGCL(ANSI,CLtL1)にはarglist関数がなぜか無い
    [GCL]>(fboundp 'arglist) => NIL
    別の関数があるのかな…?
  • sbclも便利そう

2008年9月19日金曜日

文字列を分割する

NANRIさんとこのコードを参考にsplit-stringを繰り返しでやってみた。

# position関数内の:test関数の挙動がよく分かってませんが


(defun split-string (string &optional (separator #\space)
                            omit-nulls)
  (labels ((pos (str sep)
             (position sep str
                       :test #'(lambda (x y)
                                 (find y x :test #'char=)))))
    (let ((sep (string separator))
          (acc '()))
      (do* ((str string (subseq str (1+ n)))
            (n (pos str sep) (pos str sep)))
           ((null n)
            (nreverse (if omit-nulls
                          `(,str ,@acc)
                        (remove "" `(,str ,@acc)
                                :test #'string=))))
        (push (subseq str 0 n) acc)))))

(split-string "C:/home/xyzzy/xyzzy.exe" #\/)
=>("C:" "home" "xyzzy" "xyzzy.exe")
(split-string "system::typespec-alist" #\:)
=>("system" "typespec-alist")
(split-string "system::typespec-alist" ":" t)
=>("system" "" "typespec-alist")

グチャグチャになってしまった。
xyzzy/Emacsにはsplit-string関数があるけど、CLにはないから結構便利そう。

関数書いてから気づいたんだが、split-stringって正規表現使えるのね

(split-string "Soup is good food" "o*")
=>("S" "up is g" "d f" "d")

視点の問題、切り返しの問題

ちょっと感心した話。

その発想はなかったわ。 おばさん視点を書いたのはたぶん本人じゃないと思うけど、自分の言いたいことが相手に伝わらないことってよくあるよね、って思った。

いやそこまで深い話じゃないんだけどね。

自分の場合、伝えたいことが頭の中でとろけてしまって形にならないことがしばしばあって困る…

2008年9月17日水曜日

文字列に含まれる単語の最初の文字を大文字にする (LL Golf Hole 2)

どう書く?orgより LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする

kozimaさんの書いたコードを改造してみた。たぶん処理系依存でなくなったと思う。

(defun cap (str)
  (labels ((fn (x y)
             (if (and (upper-case-p x)
                      (lower-case-p y))
                 x
               y)))
    (map 'string #'fn
         str
         (string-capitalize str))))
(cap "LL day and night") ; =>"LL Day And Night"

やっていることといえば、

①元の文字列と②string-capitalizeした文字列の各文字をそれぞれ比べて、①の大文字部分が②で小文字に変わっていたら①の文字を、そうでなければ②の文字を選択しているだけ。

下のを縦読みするとなんとなく分かるかもしれない。

"LL day and night"        ; ①str
"Ll Day And Night"        ; ②(string-capitalize str)
------------------
"LL Day And Night"        ; 結果

そもそもstring-capitalizeの実装ってどうやるんだろう?

2008年9月15日月曜日

CommonLispでOpenID

取りあえずネタ投下。

OpenID Libraries for Common Lisp (CL-OpenID)

ちなみにBloggerではOpenIDが使えるとのこと。

初投稿

冷やし中華よろしくブログ始めました。

xyzzyを使い始めて、Lispに関する疑問やら何やらが溜まってきたのでこのブログに投げてメモしておこうかなという感じです。

"xyzzy"って何?という人は下のリンクをたどればいいと思うよ。