2010/10/29

Emacs Lisp : complement

述語を反転させるアレですね。(complement equal) とやると (lambda args (not (apply equal args))) が返るような高階関数です。

Scheme を書いている時によく使います。定義も簡単なので、無ければすぐ書けます。たまたま今日は Emacs Lisp で自前の関数を書いている時に complement が欲しかったので、書こうとしたらしばらくハマりました。。無ければ無いでよかったんですが、この際自前の Emacs Lisp 関数を定義したファイルに書き加えておいても良いかなと思い、書くことにしたのです。

デフォルトがダイナミックスコープである点にやられました。やはりデフォルトはレキシカルスコープでスペシャル変数や fluid-let などを用意してある方が良いなぁと思うわけです。慣れなんでしょうけどね。
(defun complement (f)
  (lexical-let ((f f))
    (lambda (&rest args)
      (not (apply f args)))))

(defun not-equal (x y)
  (funcall (complement #'equal) x y))

(funcall #'not-equal "" "a")
;; -> t

追記

検索したら素敵なページがあった!complement だけでなく fold や compose も再帰ではなく反復で定義してあるし、any, every, filter, take-while などなど Schemer 歓喜!

自分でちくちく書く必要はなかったようです。

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

0 件のコメント:

コメントを投稿