08 Mercoledí
Settembre 2004

言語としてのEmacs Lisp

長月 09/08 (水) 10:51 [Permalink]

Emacs Lispをひさびさに使ってみた。だいたいemacs使うから一番手軽な環境ではあるわけだけど、やっぱemacs lispそのものは大変ちいさい言語だしテキストやバッファ処理に特化してるのでいろんなことが面倒。実際のelisperはわりと関数型でなくばりばりsetqやwhileを使うらしい。しかも、実装もわりとばりばりsetq使ってたり。そのほうがはやいし。あと、再帰かけても、標準のままだとスタックすぐあふれる。ぐえー。するなら末尾再帰で書いたほうが良いかもしれん。

guileを使っているがわからみるとfuncallがいるとか高階な操作ではまったりするし。mapはmapcarがあるから良いけど、reduceやfilterは無い(?)ぽいし。pythonでいうrangeみたいな1,...,10とかを生成する関数もなさげだし。

よくあるのはリストの各要素についてある操作を行い結果を得るってやつで、pythonだと内包表記(list comprehension)かmap/filterで以下のようにかくやつ。

% python
>>> [x**2 for x in range(10) if x%2==0]
[0, 4, 16, 36, 64]
>>> filter(lambda x: x%2==0,map(lambda x: x**2, range(10)))
[0, 4, 16, 36, 64]
>>>

これをelispでどうかくのか?mapはmapcarで良いとして毎回filterをどうすんのか、filterを自前でかくのか、うんぬん。guileだとsrfi-1のリストライブラリにこの類の処理はあるんでたとえば以下のように書く(わたしは)。

% guile
guile> (use-modules (srfi srfi-1))
guile> (filter (lambda (x) (zero? (remainder x 2))) (map (lambda (x) (* x x)) (iota 10)))
(0 4 16 36 64)

まあ、elispだとたいていはsetqとwhileで書かれている気もするし、guileの実装もlist-tabulateなどsrfi-1.scmをみたらわりとdo文とかで書かれてたから、やるこた同じなわけだけど。

と、とあることに気づいた。emacsには"Common Lisp Extensions"というおまけがついてくる(詳しくは勝手に入るinfoみてください)。ファイルはcl.el。これを使えば、かなりCLぽくなるので言語的にいろんなことができる。あのあやしげloopも使える(ic) set operationsも使える(ic)

(require 'cl)
(let* ((val (loop for x from 0 to 9 collect x))
       (mylist (mapcar (lambda (x) (* x x)) val)))
  (remove-if (lambda (x) (not (zerop (% x 2)))) mylist))

loopマクロを入れてスクリプト言語みたくかくのが案外使いやすかったりして(^_^;

上は一応map/filterもどきな使いかただが、じつは、結局pythonのときの内包記法みたく、loopマクロでできる。結果、以下がelispで一番短くかける方法(^_^;

(loop for x to 9
       if (zerop (% x 2)) collect (* x x))
全1ページ [1] :: トップを見る / このカテゴリ「lisp」を見る