Emacs
.emacsDay 18

Emacsのモダンなライブラリ4+1選 (2013年版)


概要

この記事は.emacs Advent Calendar 2013の記事です。

(遅刻してすみません…)

自分は、最近出てきた新しいライブラリを紹介していこうと思います。

紹介するライブラリは以下の4+1つです。

ライブラリ
説明

dash.el
リスト API

s.el
文字列 API

f.el
ファイル・ディレクトリ API

ht.el
ハッシュテーブル API

Cask
バッケージ依存管理のプラグイン

このライブラリ群はEmacsに不足している名前がわかりやすい関数、他の言語では提供されているデータ構造を操作する便利な関数を提供してくれます。このライブラリを使うと、プラグインや、スクリプトを作るのがすごく楽になります。

+1の部分であるCaskは、ライブラリというよりプラグインなので別にしてます。

それぞれどんなライブラリか、かいつまんで紹介します。


dash.el

dash.elは、Emacsのリスト操作APIを提供するライブラリです。このライブラリは、かなりEmacsのリスト操作を分かりやすく、補完してくれるライブラリになっています。

リスト操作に関連してか、


  • Clojureのスレッディングマクロ

  • On Lispで紹介されているアナフォリックマクロ

  • バインドという機能

  • 木構造の操作のAPI

など様々なものを提供しています。

メリットとしては、


  • もっと関数型言語っぽく書ける

  • リスト操作が簡単に書ける

こんな点があげられます。

関数の名前はHaskel(またはClojure)ライクです。-filterとか-map-flatten-drop-take-whileとかがそれっぽいです。

アナフォリックマクロについてはここ

スレッディングマクロについてはここ

がどんなものか参考になるかも。


コード例

導入方法はこうやります。

;;; Installation

;; M-x package-install dash
(require 'dash)

1つ目は、dash.elで、Emacs Lispで提供されていないflattenや、 リストに対してのconcatなどの関数が提供されています。

(-flatten '((1))) ;; => '(1)

(-flatten '((1 (2 3) (((4 (5))))))) ;; => '(1 2 3 4 5)
(-flatten '(1 2 (3 . 4))) ;; => '(1 2 (3 . 4))

(-concat '(1)) ;; => '(1)
(-concat '(1) '(2)) ;; => '(1 2)
(-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)

またいくつかの関数では--mapという風にするとアナフォリックマクロにできます。

(-map #'(lambda (x) (* x x)) '(1 2 3)) ;; => '(1 4 9)

(--map (* it it) '(1 2 3)) ;; => '(1 4 9)

スレッディングマクロはどんどん処理が入れ子になる場合に書き方楽にすることができます。スレッディングマクロは->, ->>, -->の3つが用意されています。

;; 一つ前の結果が、第一引数の部分に挿入される

(-> '(2 3 5)) ;; => '(2 3 5)

(-> '(2 3 5) ;; => '(2 3 5)
(append '(8 13))) ;; => (append '(2 3 5) '(8 13))
;; => '(2 3 5 8 13)

;; 一つ前の結果が、引数の最後に挿入される
(->> '(1 2 3) ;; => '(1 2 3)
(-map 'square) ;; => '(-map 'square '(1 2 3))
(-remove 'even?)) ;; => '(-remove 'even? (-map 'square '(1 2 3)))
;; => '(1 9)

;; アナフォリックなスレッディングマクロ
(--> "def" (concat "abc" it "ghi")) ;; => "abcdefghi"

(--> "def" (concat "abc" it "ghi") ;; => "abcdefghi"
(upcase it)) ;; => (upcase "abcdefghi")
;; => "ABCDEFGHI"


補足

dash.elはEmacs Lispをさらに関数型言語っぽく書くためのdash-functional.elというものもがあります。このパッケージでは-partial, -compose, -flip, -constなどが使えます。


s.el

2つ目は、s.elで、Emacsの文字列操作APIのライブラリです。Rubyライク(?)のわかりやすい文字列操作関数が定義してあります。Emacs Lispでは自分で定義しないとなかったような関数が使えるのは良いです。


コード例

導入方法はこうやります。

;;; Installation

;; M-x package-install s
(require 's)

関数名はRubyライク

str = "trim   "

str.trim # "trim"

(s-trim "trim  ") ;=> "trim"

str = "a|bc|12|3"

str.split #=> ["a", "bc", "12", "3"]

(s-split "|" "a|bc|12|3") ;; => ‘("a" "bc" "12" "3")




s.elだと、だいぶ書きやすく覚えやすくなってます。

;; (mapconcat function sequence separator)

(mapconcat 'identity '("abc" "def" "ghi") "+") ;; => "abc+def+ghi"
(mapconcat 'identity '("abc" "def" "ghi") "\n") ;; => "abc\ndef\nghi"

;; s.elでやる場合
;; (s-join separator strings)
(s-join "+" '("abc" "def" "ghi")) ;; => "abc+def+ghi"
(s-join "\n" '("abc" "def" "ghi")) ;; => "abc\ndef\nghi"

s-matchに関しては使い方が調べてもいまいち使い方がわからないmatch-stringをラップしてくれるので、これだけのために使うのも有りじゃないかと思います。

;;match-stringは使い方がわからないのでいつか書きます。

;; s.elの場合
(s-match "^def" "abcdefg") ;; => nil
(s-match "^abc" "abcdefg") ;; => '("abc")
(s-match "^/.*/\\([a-z]+\\)\\.\\([a-z]+\\)" "/some/weird/file.html")
;; => '("/some/weird/file.html" "file" "html")

s.elに関してはこんな感じです。


f.el

3つ目は、f.elで、Emacsのわかりにくいファイル処理を楽にしてくれるライブラリです。基本Emacsのファイル処理関数は名前が長く、他の言語と名前の共通点があまりないです。なのでかなり覚えにくいです。

このライブラリは、RubyやShellコマンドと共通点が多いのでかなり覚えやすいと思います。


コード例

導入方法はこうやります。

;;; Installation

;; M-x package-install f
(require 'f)

f.elの関数の例はこんなのです。"f-"から始まる関数がf.elでは提供されています。

;; 拡張子を取得する

(file-name-extension "path/to/file.ext") ;; => "ext"
;; f.el
(f-ext "path/to/file.ext") ;; => "ext"

;; 拡張子なしのパスを取得する
(file-name-sans-extension "path/to/file.ext") ;; => "path/to/file"
;;f.el
(f-no-ext "path/to/file.ext") ;; => "path/to/file"

;; ファイルのベースネームを取得する
(file-name-sans-extension
(file-name-nondirectory (directory-file-name "path/to/file.ext")))
;; => "file"
;;f.el
(f-base "path/to/file.ext") ;; => "file"

この例としてあげた関数ではかなり処理が分かりやすくなっています。

他にもファイルを移動させるf-moveやディレクトリを作るf-mkdirなどの関数もあります。


ht.el


説明

4つ目は、ht.elで、Emacsのハッシュテーブル操作APIを提供してくれるライブラリです。

素のEmacs Lispでハッシュテーブルを使おうとすると


  • 関数の名前に馴染みがなくて使うときに戸惑う

  • 引数が直感的じゃない

なのでそれを補ってくれるので、ハッシュテーブルがすぐ使えるようになります。


コード例

導入方法はこうやります。

;;; Installation

;; M-x package-install ht
(require 'ht)

ハッシュテーブルの作成はだいぶわかりやすくなっています。

;; ハッシュテーブルの作成

;; 普通のやり方の場合
(setq hash (make-hash-table :test #'equal))

;; ht.elの場合
(setq hash (ht-create))

;; ハッシュテーブルにデータを挿入する

;; 普通のやり方の場合
(setq hash (make-hash-table :test #'equal))
(progn
;; (puthash key value hash-table)
(puthash 1 "apple" hash)
(puthash 2 "banana" hash))

;; ht.elでやる場合
;; マクロで定義する
(setq hash2 (ht (1 "apple") (2 "banana")))

;; ht-setで挿入する
(setq hash2 (ht-create))
(progn
(ht-set hash2 1 "apple")
(ht-set hash2 2 "banana"))

以上が4つのライブラリ紹介になります。


パッケージの依存管理について

ここで+1としたCaskついてです。実際ライブラリを使って開発・配布しようと思ったらRubyのbundlerみたいなものがほしいと思います。そのためのプラグインで、パッケージ依存管理のCaskというものが最近上がってきています。作者がかなりアピールしてるっぽく、それなりに開発が盛んで、導入例も多いので広まるかもしれません。

パッケージ依存管理をするならこれがいいかもしれません。


終わりに

モダンなライブラリということで



  • dash.el - リスト API


  • s.el -
    文字列 API


  • f.el - ファイル・ディレクトリ API


  • ht.el - ハッシュテーブル API


  • Cask - パッケージ依存管理

の5つを紹介しました。

5選ということであまり詳しく書けていませんが、どのライブラリも「これは使いたい!」と思えるようなものだと思うので使ってみてください。それぞれの詳しい使い方や昨日は各ライブラリのリンクで調べて下さい。詳しい使い方がわかりにくいht.elの方はtestsディレクトリの中を覗けば良いです。

次は@dageziさんです。

–> さらばいとしのlexical-let

追記

この記事を参照先として利用してもらいありがとうございます。

Emacsパッケージ特集