2011/04/02

xyzzy の C-k (kill-line)



職場の xyzzy は入れてからずいぶん経つので、自分にはかなり枯れてきている。


対して家のは全然そこまで行ってなくて、同じ感覚で使っていると「ムムム」と思うことがよくある。


まぁ、家の xyzzy は lisp 練習器 なので lisp-mode が適当に動いてくれれば問題ないんだが、これはさすがにどうか。


xyzzy のデフォルトでは C-k しても kill-ring に入ってくれないのか。


ある1行を移動させるときは、行頭で C-k して、別の場所で yank するということを頻繁にやる。


職場のはたぶん適当になにか書いて済ませたと思う。家でもう一度それを書くのもダルい。


誰か書いてないかな?・・・あった。


http://d.hatena.ne.jp/negation/20090218/1234908800


kill-ring に入ってくれるだけでよかったが、Windows のクリップボードと同期してくれるそうで、これは助かる。


ありがたく拝借させていただく。





lisp 再帰ドリル



dolist もいいけど、もうちょっと lispっぽく行きたい。

そういうことなら、まずは再帰だ。そもそも体が再帰を考えることに慣れてないと自覚したので、ココを見て練習してみる。

1. まずは恒例の n! を求めるやつ。n! = 1 * 2 * 3 * ... n 。

(defun my-fact (n)
(if (= n 0)
1
(* n (my-fact (1- n)))))

;; test
(my-fact 3)
6


よし、つぎ。

2. m の n 乗を出す。m の n 乗 = m * m * m * ... m (m は n個)。

(defun my-expt (m n)
(if (= n 0) 1
(* m (my-expt m (1- n)))))

;; test
(my-expt 2 10)
1024


OK。どんどん行こう。

3. リストの要素数を求める。

(defun my-length (lst)
(if (eq lst '())
0
(1+ (my-length (cdr lst)))))

;; test
(my-length '(a b (x y z) c d))
5


ノッてきた。

4. 数値リストの要素の合計を求めるやつ。

(defun my-sum-list (lst)
(if (eq lst '())
0
(+ (car lst) (my-sum-list (cdr lst)))))

;; test
(my-sum-list '(1 2 3 4 5 6 7 8 9 10))
55


よしよし。これくらいなら行けるぞ。

5. リストから指定した要素を除いたリストを返すにはどうする?

(defun my-remove (lst e)
(if (eq lst '())
'()
(if (eq e (car lst))
(my-remove (cdr lst) e)
(cons (car lst) (my-remove (cdr lst) e)))))

;; test
(my-remove '(a x b c x x d x e f) 'x)
(a b c d e f)


・・・ちょっと苦しかったな。気を取り直して、つぎ。

6. リストの指定した要素の位置を返すやつ。 (位置はゼロ始まり)

(defun my-epos (lst e)
(if (eq lst '())
'()
(if (eq (car lst) e)
(append (my-epos (cdr lst) e) (list (1+ (length lst))))
(my-epos (cdr lst) e))))

;; test
(my-epos '(a b x c d x x e f x) 'x)
(2 5 6 9)


なんとかいけたけど結構 try and error を繰り返した。



まぁ、やるまえよりは再帰が身についたと思う。

今の自分にできるアプローチとしては、最初のやつ

(defun my-fact (n)
(if (= n 0) 1
(* n (my-fact (1- n)))))


を基本パターンとして書いてみて、それをちょこっと変更することを考えてみるって感じだろうか。

そんなのしなくても、慣れればズババーと書けるんだろうけど、いっぺんにそこまで到達するのは無理っぽい。

「これは再帰でいけるかな?」と考える癖だけでもつけておくことにしよう。




2011/04/01

xyzzycli.exe に 関連づけたファイルをダブルクリックすると・・・



だいぶ前に .l を xyzzycli.exe に関連づけてたんだが、それをダブルクリックすると、


f:id:gnrr:20110402031729p:image


が出る。


load-path に問題ありそうってことで、



(push "D:/work/lisp" *load-path*)


を .xyzzy の先頭に追加したら出なくなった。


いろんな lisp package を、net-installer 使わずに D:/work/lisp に直接入れてるのがまずかったようだ。でも直ったからいいか。





lisp-mode で インデントをスペースにする



今ごろ気づいたんだが。


xyzzy はデフォルトの状態では、lisp-mode のインデントがタブ文字になっているようだ。



(setq *lisp-indent-tabs-mode* nil) ;; use spaces for indentation


としとけば、タブじゃなくてスペースでインデントしてくれる。


lisp-interacion-mode にも効く。





dolistって



たとえば、あるリストの要素をループで回して処理したいことがよくある。それこそ頻繁に。

今まで、そんなときは while 一本やりで通してきた*1。たとえばこんな感じ。



(let ((lst '(11 22 33 44 55)))
(while lst
(dbg-msgbox (car lst))
(setq lst (cdr lst))))


要素1つを取り出すのに car したり、ループの末尾で cdr を リストにセットし直したり、めんどいなぁとは思っていた。


dolist はこういうときにうってつけ。下記のように書ける。



(let ((lst '(11 22 33 44 55)))
(dolist (e lst)
(dbg-msgbox e)))


すっきりした気分だ。


実は dolist は Emacs を使ってたときから存在だけは知っていた。しかし書き方が複雑そうで敬遠していたのだった。でも使ってみたらすごくシンプルで、while で回すよりも数段 LISPっぽい。場面はぜんぜん違うが、On Lispの



そうしないとLispに逆らってプログラムを書くことになるからだ.


http://www.komaba.utmc.or.jp/~flatline/onlispjhtml/functionalProgramming.html

の一文を思い出した。


LISPっぽいといえば、上の例は mapcar で一発だったりする。



(mapcar #'(lambda (x) (dbg-msgbox x)) '(11 22 33 44 55))


本当は、



(mapcar #'dbg-msgbox '(11 22 33 44 55)) ;; not work


と書きたいけど、ダメっぽい。よくわからん。マクロは関数じゃないから mapcar には渡せないのかな。


まだまだ精進が足らんようだ。




*1:「なんとかの一つ覚え」も10年ほどやっていると、python の i += 1 みたいに「一貫性がある」とか思えてくるから不思議。