2008年11月30日日曜日

xyzzy を再起動させる

新しいネタを提供する気力がないので手元にある既存のものを。

(defun reboot-xyzzy (&optional cleanup)
  "xyzzyを再起動する."
  (interactive "P")
  ;; ついでに初期化する
  (when cleanup
    (delete-file (si:dump-image-path) :if-does-not-exist :skip)
    (let ((siteinit (find-load-path "siteinit")))
      (and siteinit
           (string-match "\\.lc$" siteinit)
           (delete-file siteinit))))
  (cond ((modified-buffer-exist-p)
         (error "保存をしよう、な!"))
        ((running-process-exist-p)
         (error "サブプロセスが走ってるで")))
  (and (call-process (merge-pathnames "xyzzy.exe" (si:system-root))
                     ;; 環境変数の設定
                     :environ `(("XYZZYHOME" . ,(si:system-root))
                                ;; 設定ファイル (xyzzy.ini等) のディレクトリ
                                ("XYZZYCONFIGPATH" . ,(user-config-path)))
                     :no-std-handles t
                     :exec-directory (si:system-root)
                     :show t
                     :wait nil)
       (kill-xyzzy)))

(defun modified-buffer-exist-p ()
  "保存する必要のあるバッファがあるか."
  (remove-if-not #'need-buffer-save-p (buffer-list)))

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

使い方:

  • 再起動させる M-x: reboot-xyzzy

  • 再起動のついでに、ダンプファイルと siteinit.lc を削除して再ダンプさせるようにする。 C-u M-x: reboot-xyzzy

注意:

保存していないバッファがあったりサブプロセスが走っていたりすると、「いいの?」って質問されて止まっちゃうのでそこはエラーにしてます。保存関係は (save-some-buffers) 使ってもいいかも。

あと、自分は xyzzy.ini ファイルを $XYZZY/usr/ ディレクトリ直下に置いてあるで、普通に使ってる人は ("XYZZYCONFIGPATH" . ,(user-config-path)) の部分を削除して下さい。

紙一重で動いてるスクリプトな気がするのでご使用は各自の責任でお願いします。

2008年11月28日金曜日

ネット断食

この間の日曜日未明からルータの調子がおかしかったのかネットワークから遮断された生活を送っていました。

今日の夕方からようやく回復。しかし原因は不明。

まあ、あれだ。
ネットがなくても生きていけることを身を以て知ることができただけ良しとしようか。

2008年11月22日土曜日

CL のライブラリを眺める [Metatilities]

今日行われる CL勉強会@Lingr の予習を少し。

生 REPL くらいしか触ったことがないから CL のライブラリを見るのは今回が初めて。 そんな CLer 初心者なのでパッと見た感じの感想だけ書いておきます。 勉強会はおとなしく ROM かな。

  • Metatilities はユーティリティライブラリ
  • CL のライブラリを読み込ませる方法が分からない
  • インストールは ASDF Linux のパッケージシステム(RPM とか YaST とか)、xyzzy の NetInstaller みたいなもの?
  • かろうじて分かったもの
    • anaphoric.lisp (OnLisp からアナフォリックマクロ)
    • graham.lisp (こちらも OnLisp から)
    • source-compare.lisp (diff?)
    • dates-and-times.lisp ($XYZZY/lisp/timestmp.l みたいなの)
  • #.(concatenate 'string *debug-doc-string*) debugging-utils.lisp より READ 時に解析して DOCSTRING を生成する方法
  • (defun (setf ~)) って何者?
  • C 言語で #ifdef を使い分けるのと同じくらい CL には #+#- が多い気がする

2008年11月20日木曜日

2008年11月18日火曜日

[xyzzy] newLISP 環境を構築してみたい

※一応 Emacs 版もあります。

newLISP に付属のエディタが使いにくい。

やっぱり使い慣れたエディタがいいよね、ということで xyzzy から newLISP シェル (REPL) を操作する簡単な xyzzylisp を書いてみた。

(defvar *newlisp-exe*
  (merge-pathnames "newlisp.exe" (si:getenv "NEWLISPDIR")))

(defun run-newlisp ()
  (interactive)
  (let ((*eshell* (format nil "~A -C -w ~A"
                          *newlisp-exe* (default-directory)))
        (*shell-mode-hook*
         (list #'(lambda ()
                   (rename-buffer "*newLISP*"))))
        ;; プロセス間通信は UTF-8
        (*default-process-encoding* *encoding-utf8n*)
        ;; なくても多分動く
        (*default-fileio-encoding* *encoding-utf8n*))
    (shell)))

;;; elisp ならこんな感じか
(defun run-newlisp ()
  (interactive)
  (let ((default-process-coding-system '(utf-8 . utf-8)))
    (run-lisp (format "C:/PROGRA~1/newlisp/newlisp.exe -C -w %s"
                      (expand-file-name default-directory)))))

ただし複数行の式を書くときは [cmd]~[/cmd] タグを使うことに注意。これは仕様だから仕方ない。
Evaluating newLISP expressions - newLISP v.9.4.5 Users Manual and Reference

書いていて気づいたが、 newLISP では日本語処理に難があるので UTF-8 が使えるバージョンを入手する必要がある。
http://www.newlisp.org/downloads/UTF-8_win32/

;; 比較
;; win32 で標準インストールされる newlisp.exe
> (explode "はろー")
("\227" "\129" "\175" "\227" "\130" "\141" "\227" "\131" "\188")
> (length "はろー")
9
;; UTF-8 の使える newlisp.exe
> (explode "はろー")
("は" "ろ" "ー")
> (length "はろー")
9
> (utf8len "はろー")            ; UTF-8 用 length
3

でも reverse 関数には日本語が使えないので泣く泣く次のように書く必要がある。 メンドクサ

> (apply append (reverse (explode "はろー")))
"ーろは"

さーて、何をしようか。

トラックバックはじめました

HaloScan のサービスを使わせてもらうことに。 HaloScan.com - Weblog Commenting, Ratings and Trackback

参考にした記事 GoogleBlog(Blogger)におけるTrackBackの方法

気をつけるべき点は、 Sineup した後で

Members->Settings
---
Time Zone を "(GMT + 9:00) Osaka, Sapporo, Seoul, Tokyo"
Character Encoding を "UTF-8"

の設定を忘れないことくらいか。まだ使ってないから知らないけど。

さっそく参考にさせてもらった記事の方にトラックバックpingを送りつけようと思ったらトラックバックURLが見つからない罠。


2008-11-18T22:27:12+09:00 [追記]

ブログのテンプレートいじくってたら元に戻らなくなったw なんでテンプレのアップロードがエラーになるんだろう…


2008-11-19T22:50:22+09:00 [追記]

アップロードエラーはログインし直したらいつの間にか直った。

で、HaloScan にはトラックバックの他に投票(はてなスターみたいなの)とかコメント管理の機能もあるらしいんだけど、コメントは Blogger のものを使うことに。

テンプレのいじり方は以下を参考に

Blogger beta に HaloScan をとりつける - クリボウの Blogger Tips

これでコメントリンクの横に "Trackback(#)" の文字が表示された。

NoScript(Firefoxアドオン)使っている場合は"haloscan.com"を許可しないと見えないかも。

まだ使ってないんで、トラックバック失敗するようならコメントの方でお願いします...

ないないない

newLISP なる LISP 処理系に手を出してみた。 付属のデモを眺めてみた感じ、LISP というよりもスクリプト言語という印象。

しかし困った点がいくつか...

  • Common Lisp との挙動の違い
    以前の記事で書いた通り。これは慣れるしかない、か。
  • 日本語のドキュメントが少ない
    検索で見つかる日本語の記事が少ないのです。 ただでさえ少ない(と思われる)LISP人口で、newLISP を使う日本人がどれだけいるのか。 自分が newLISP を知るきっかけになった方の記事はまだ続いてるみたい。参考にさせてもらってます。
  • サンプルコードが少ない
    日本語ドキュメント以上にこれは正直キツイ。 インストールディレクトリにもサンプルはいくつかあるのだが、どうしてだろう、コードがすごく見づらい。 全部タブインデントとか、束縛していない変数に代入とか。 開発者の中に Emacs 使いはいないのだろうか?
  • 付属の GUI 開発環境が使いにくい
    newLISP(win32) をインストールするとデスクトップとスタートメニューに newLISP-GS なるショートカットが出来上がる。 これを実行するとエディタ兼 newLISP 実行環境の GUI が立ち上がるのだが、Emacs キーバインドに飼い馴らされた自分には使いにくいことこの上ない。
  • 何ができるかよく分かっていない
    自分の問題です。すいません。

あと自分の記事をみて newLISP に興味を持ってくれた方がいて軽く吹いた。 http://cadr.g.hatena.ne.jp/mokehehe/20081111/newlisp

2008年11月14日金曜日

なにこれ・・・

ニコニコ動画にアップロードされている動画を音声ファイル(mp3)に変換するWebサービス「nicomimi」が、えらく混雑している。キャプチャは昨日の 22:30 くらいの。

同じサービスを運営しているこっちが現在メンテナンス中(08/11/13 2:00 ~ 08/11/14 17:00)ということもあるのだろうが、ユーザも少しは自重しろと言いたい。

2008年11月11日火曜日

newLISP と CL/Scheme の比較

意訳、省略を含むので参考程度に眺めることを推奨します。

ところで newLISP ってなに?


Comparison to Common Lisp and Scheme

このページでは newLISP と他の標準な Common Lisp, Scheme とのいくつかの違いを明らかにする。newLISP 特有のアプローチを知りたいなら About を読んで下さい。

  1. CL と異なり、newLISP と Scheme は式のオペレータ部分を(引数に適用する前に)評価する。
  2. ラムダ式は自身を評価する。それらはリストの副タイプであり、他のリスト同様に扱えるファーストクラス・データオブジェクトである。

    newLISP ではラムダ式の自由変数の束縛はラムダ式の適用時にのみ行われる。

    newLISP のラムダ式は関数定義の後いつでも処理できる。
    (last (lambda (x) (+ x x))) => (+ x x)
    See the page: Scheme のクロージャと newLISP のコンテキストの比較
  3. 変数、関数の名前空間を共有している (Lisp-1)。 シンボルは大文字小文字を区別する。
  4. 全ての変数は基本的に動的スコープ。 けれども自身のコンテキスト内で定義することにより、静的/レキシカルスコープが得られるし、変数捕捉を避けることができる。
  5. ドット対が存在しない。代わりにセルがリストの一部ならば、そのセルは一つのオブジェクトと他のオブジェクトへのポインタを含む。ゆえに cons の挙動が他の LISP 処理系と異なる。
    ;; Common Lisp and Scheme
    (cons 'a 'b) => (a . b)         ; ドット対
    
    ;; newLISP
    (cons 'a 'b) => (a b)
    
    ;; LISP cells in Common Lisp and Scheme
    (cons '+ (cons '2 (cons '3 (cons (cons '* (cons '4 (cons '3 nil))) nil))))
    => (+ 2 3 (* 4 3))
    
    ;; LISP cells in newLISP
    (cons '+ (cons 2 (cons 3 (cons (cons '* (cons 4 3))))))
    => (+ 2 3 (* 4 3))
  6. ユーザ定義の関数の引数は全てオプショナルである。 代入されなかった引数は関数内部では nil と仮定される。
    ((lambda (x y z) (list x y z)) 'foo 'bar) => (foo bar nil)
  7. 必然的に、未束縛の変数は存在しない。 そのようなシンボルは最初の構文解析時に生成されて、現在の名前空間に nil として束縛される。
    (list foo bar baz) => (nil nil nil)
  8. ブール定数は nil/true 。 CL では nil はリストの終端という役割もある:
    ;; Common Lisp
    (cons 'x nil) => (x)
    
    ;; newLISP
    (cons 'x nil) => (x nil)>
    Scheme のブール定数は #t/#f が真/偽。
  9. シンボルとコンテキストを除く全てのオブジェクトは一度だけ参照される。 (ORO: Only Referenced Once) このルールにより CL, Scheme で使われる伝統的なガベージコレクションアルゴリズムなしに、自動的で、スタックベースなメモリ管理が出来る。
  10. マクロは引数を評価しない関数のようなもの。 結果としてマクロは組み込まれた基本関数のように振舞う。
    (define-macro (my-setq x y) (set x (eval y)))
    ;; もしくは変数捕捉を避ける衛生的なマクロとして
    (define-macro (my-setq) (setq (args 0) (eval (args 1))))
    変数を明示的に展開する組み込み関数として expand, letex がある:
    (let ((z 2))
      (expand (fn (x y) (* x y z))   ; fn は lambda の略記
              'z))
    => (lambda (x y) (* x y 2))
    
    (define (raise-to power)
      (expand (fn (base) (pow base power)) 'power))
    
    (define square (raise-to 2))
    (define cube (raise-to 3))
    
    (square 5) => 25
    (cube 5)   => 125
  11. 等価条件の判定は = のみ。 newLISP では値をコピーして渡すスタイルをとっている。
  12. インデックス機能 (implicit indexing)
    (let ((myList '(a b c (d e) f g))
          (v '(3 1)))
      (list (nth 2 myList)          ; using nth
            (myList 2)              ; using implicit indexing (1)
            (myList -3 0)           ; using implicit indexing (2)
            (myList v)              ; with address vector
            (1 2 myList)            ; implicit rest, slice
            ))
    ;=>(c c d e (b c))

newLISP の内部についての詳細は以下を参照のこと:


Change Log

  • 2008-11-11 訳してみたので公開
  • 2008-11-30 加筆修正
    高階関数 (higher-order function) とファーストクラスオブジェクト (first-class object) はどう見ても別物です。なに勘違いしてるんだ自分…

2008年11月3日月曜日

CLISP on Cygwin が使えない

半年くらい前からだろうか、cygwin にインストールした clisp が起動と同時にエラーになる症状に陥った。

$ clisp
  i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
  I I I I I I I      8     8   8           8     8     o  8    8

*** - Internal error: statement in file
       "/usr/src/clisp/clisp-2.46-1/src/clisp-2.46/src/stream.d"
      , line 5658 has been reached!!
      Please see <http://clisp.cons.org/impnotes/faq.html#faq-bugs> for bug
      reporting instructions.
Break 1 [3]> nil
NIL
Break 1 [3]> (car '(1 2 3))
1
Break 1 [3]> :q

[/usr/src/clisp/clisp-2.46-1/src/clisp-2.46/src/eval.d:573] reset() found no driver frame (sp=0xdacc70-0xd90580)
Floating point exception (core dumped)

動かないわけではないけれど、デバッガから抜けると落ちる。

まあ win32 バイナリの clisp の方が使えるから問題はないが。けど気持ち悪いなあ。 解決法がわからないから今のところ放置中。

2008年11月2日日曜日

[xyzzy] EDICT とべんりすぷ

なんとなく xyzzy の辞書ファイルを更新しようとしたらちょっと驚いた。 なんでかというと、その辞書ファイルの元となる EDICT ファイルが現在も更新されていたから。

xyzzy で辞書を使う方法は XyzzyWiki か $XYZZY/etc/README.gendic を参照のこと。 2008-11-02 現在、 Wiki の edict へのリンクは切れてます。 編集したいけどページが凍結されている…

辞書ファイル配布元: The Monash Nihongo ftp Archive http://ftp.monash.edu.au/pub/nihongo/00INDEX.html トップページから "edict.gz" を検索すれば見つかるはず。大分上の辺り。

で、少し古くても構わないのならば同じ辞書ファイルは sdic (Emacs 用辞書引きメジャーモード) の作者さんである土屋さんのページからも入手できる。

[利用・配布条件] を見ると 1998 年のものらしい。 http://www.namazu.org/~tsuchiya/sdic/

二つの辞書ファイルを比較すると (比べたのは edict ファイル本体のみ)

更新時間        サイズ          行数
---             ---             ---
2008-10-31      9.1M            160,090行
1998            2.5M             64,152行

すごく大きいです。 当然ながら出来上がる辞書ファイル xyzzy{dic,e2j,idi,jrd} も大きくなった。

しかし更新したのは良いけれど、その違いがわかるほど辞書を使いこなしていない自分にがっかりした。

辞書ファイル作成、辞書引きまで全部 LISP で作れないかなあ。


[おまけ] 自分の使っている便利 LISP 紹介


;;; バッファの代わりにポップアップ表示で辞書引き
(defun lookup-current-word ()
  (interactive)
  (let ((msg (save-window-excursion
               (lookup-e2j-dictionary-selection)
               (prog2
                   (set-buffer "*dictionary*")
                   (buffer-substring (point-min) (point-max))
                 (delete-buffer "*dictionary*")))))
    (popup-string (string-trim (string #\LFD) msg) (point))))

(global-set-key '(#\C-c #\e) 'lookup-current-word)
こんな感じになる。