★データ解析備忘録★

ゆる〜い技術メモ

Rおじさん、Lisperへの道 (Common Lisp環境設定編)

はじめに

Twitter上でこんなやりとりがあって、Lispをちゃんと勉強しようかなと思った次第。これまでEmacsを使って設定ファイルも(汚いけど)それなりに書いてきたので基礎を知ってるくらいなので、ここは一つCommon Lispをちゃんとやっておきたいなというのが主な動機です。

ところで、このブログは「データ解析周りを中心に、プログラミング全般について書く」と明言してるわけですがこれからやるCommon Lispがどのくらい役に立つかは未知数。

Common Lisp の環境設定

PCはMacのMojaveを使ってます。

Roswellで処理系としてはSBCLを使い、EmacsでSLIMEの環境を作るところまでを目指します。

用語整理

Common Lispについて調べているといくつか混同しそうなワードが出てきたので整理。

  • SBCL, CLISP, Clozure CL: Common Lispの処理系。Common Lispは、一つの公式の実装が存在するわけではなく、ANSIで規定された規格で規定された機能を実装したものはすべてCommon Lispを名乗ることがきるらしい。
  • Roswell: Common Lisp処理系マネージャ。Pythonでいうところのpyenv的なやつ
  • Quicklisp: パッケージマネジャ。Pythonでいうところのpipみたいなやつ。
  • SLIME: エディタをIDEっぽくするやつ。

Roswell

このあたりを参考に。 Homebrewで簡単に。と思いきや後のSBCLのインストールで詰まったので注意です。

ここを参考に

brew install --HEAD roswell

のように最新バージョンをきちんと明示してやらないとだめでした(私の環境では。)

Roswellはそれ自身、コア以外の部分にCommon Lisp処理系を必要とします。以下のコマンドを叩くことで、Common Lisp処理系を取得し、roswellの設定の初期化やパッケージマネージャ (quicklisp) のインストールが行われ、完全に機能するようになります。

ros setup

Quicklisp

この項は必要なし(コメント参照)

curl -O https://beta.quicklisp.org/quicklisp.lisp
ros run
(load "./quicklisp.lisp")
(quicklisp-quickstart:install)

Emacs×SLIME

Emacsの設定。

ターミナルで

ros install slime

sbcl を起動し(ros runコマンド)、

この処理は必要なし(コメント参照)

(ql:quickload :quicklisp-slime-helper)

続いてEmacsを起動し、 M-x package-install で以下を入れる

  • slime
  • slime-company

~/.emacs.d/init.el に以下を記述

;; 拡張子関連
(add-to-list 'auto-mode-alist '("\\.lsp$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.lisp$" . lisp-mode))
(load (expand-file-name "~/.roswell/helper.el"))

;; SLIMEのロード
;; 以下3行は(load (expand-file-name "~/.roswell/helper.el"))の時点で設定される
;; (require 'slime)
;; (require 'slime-autoloads)
;; (slime-setup '(slime-repl slime-fancy slime-banner))
;; SLIMEからの入力をUTF-8に設定
(setq slime-net-coding-system 'utf-8-unix)

(eval-after-load "slime"
   '(slime-setup '(slime-fancy slime-banner)))
(global-set-key "\C-cs" 'slime-selector)

;; M-x my-slime: 分割したウィンドウでslime起動
;; C-c C-r: 選択範囲をslime-replへ送って評価
(defun my-slime (&optional command coding-system)
  "Run slime and split window."
  (interactive)
  (if (< (count-windows) 2)
      (split-window-vertically)
  )
  (slime command coding-system)
  (other-window 1)
  )
(defun slime-repl-send-region (start end)
  "Send region to slime-repl."
  (interactive "r")
  (let ((buf-name (buffer-name (current-buffer)))
        (sbcl-buf (get-buffer "*slime-repl sbcl*")))
    (cond (sbcl-buf 
           (copy-region-as-kill start end)
           (switch-to-buffer-other-window sbcl-buf)
           (yank)
           (slime-repl-send-input "\n")
           (switch-to-buffer-other-window buf-name))
          (t (message "Not exist *slime-repl sbcl* buffer!")))
    ))
(global-set-key "\C-c\C-r" 'slime-repl-send-region)

;; LISPモードで新しくファイルを開いたらウィンドウが上下に分割して下にREPL
(add-hook 'lisp-mode-hook
           (lambda ()
             (global-set-key "\C-cH" 'hyperspec-lookup)
             (cond ((not (featurep 'slime))
                    (require 'slime)
                    (normal-mode)))
             (my-slime)))

SLIME周りの設定 - もうカツ丼はいいよな を参考にしました。