2012年3月16日金曜日

SLIME REPLからFinderを開くには


SLIMEからCommon Lispを使っているとき、Finderでディレクトリを開きたいことがよくあります。SLIME REPLのShortcutを使ってそれを実現してみます。

SLIME REPLのShortcut機能
SLIME REPLにはShortcutというコマンドセットがあります。Shortcutを呼び出すには、REPLプロンプトで","を押してからShortcut名を入力します。

Shortcutには、カレントディレクトリの変更などのコマンドが定義されていますが、残念ながらOS側でディレクトリを開くコマンドは定義されていません。そこで、Shortcutを独自定義して、それを使ってFinderでディレクトリを開けるようにしてみます。

Shortcutの独自定義
SLIME REPLのコードは、slime/contrib/slime-repl.elにあります。この中で、Shortcutは、defslime-repl-shortcutというマクロを使って定義されています。これを使って、ディレクトリを開くShortcutを定義することにします。

slime/内のファイルを変更したくないので、.emacsに以下のコードを追記します。

;; SLIME open-directory short cut
(defun slime-open-directory (directory)
  "open DIRECTORY with Finder"
  (interactive (list (read-directory-name "Directory: " nil nil t)))
  (let ((dir (expand-file-name directory)))
    (call-process "open" nil nil nil dir)
    (message "opened: %s" dir)))

(defslime-repl-shortcut nil ("open-directory" "open")
  (:handler 'slime-open-directory)
  (:one-liner "Open a directory with Finder"))

これで、SLIME REPLから"," + openで、任意のディレクトリをFinderを使って開くことができるようになります。

--

2012年1月2日月曜日

GHCにおいてモジュールを相互再帰させるには


ソフトウェアの設計において、モジュールを相互参照させたい状況があります。論理的にはモジュールを細かく分ければ相互参照が起きないようにできる場合でも、意味的に考えた場合にそれらを分割したくないようなときです。

このエントリでは、GHCでHaskellのコードをコンパイルする際にモジュールを相互参照させる方法を紹介します。

The Haskell 98 Reportにおける記述
Haskellの言語仕様である"The Haskell 98 Report"では、モジュールは相互再帰をしても良いとされています。
"5. Modules" in The Haskell 98 Report
... Modules may be mutually recursive. ...
ところが、GHCでHaskellのコードをコンパイルする場合、そのままではモジュールを相互参照させることができずエラーとなります。

そうご参照させたモジュールをGHCでコンパイルする場合、追加の記述が少しだけ必要になります。

GHCで相互再帰モジュールをコンパイルするには
GHCは相互再帰モジュールをサポートしていますが、それをコンパイルするには、インポートグラフの循環参照回避のために、以下が必要となります。
  • SOURCEプラグマ
  • hs-bootファイル
SOURCEプラグマは、import宣言においてのみ使われるプラグマです。インポートグラフが循環しないようにコンパイラにヒントを与えるためのものです。

hs-bootファイルは、対応する.hsファイルのモジュール宣言や型宣言のみを抽出して記述したファイルです。.hs-boot拡張子を与えてプログラマが用意します。上述のSOURCEプラグマが付与されたモジュールをインポートする場合、インポートされる側のモジュールについては、.hsファイルではなく.hs-bootファイルから生成される情報を参照することになります。

具体的にどのように実装するかについては、GHCユーザガイドの4.7.9. How to compile mutually recursive moduleにて詳しく記述されています。

--