2012年9月22日土曜日

Haskell入門書的クイックソート

Haskellの入門書に乗っていそうなクイックソートをClojureとCommon Lispで書いてみます。

- Clojure
;; defnやletで分配束縛ができます
;; group-byで関数を適用した結果の値によってグループ分けができます
;; ハッシュテーブル(map)は指定されたキーに対応する値を取得する関数にもなります
(defn qsort [cmp [piv & rst :as coll]]
  (if (empty? coll) []
    (#(concat (qsort cmp (%1 true)) [piv] (qsort cmp (%1 false)))
     (group-by #(boolean (cmp %1 piv)) rst))))

- Common Lisp
;; remove-if-not (filter)
(defun qsort-1 (cmp lst)
  (when lst
    (destructuring-bind (piv &rest rest) lst
      (flet ((f (x) (funcall cmp x piv)))
 (append (qsort-1 cmp (remove-if-not #'f rest))
  (list piv)
  ;; (remove-if-not (complement #'f) rest)
  (qsort-1 cmp (remove-if #'f rest)))))))

;; loopマクロ
(defun qsort-2 (cmp lst)
  (when lst
    (loop
       :with piv = (first lst)
       :for x in (rest lst)
       :if (funcall cmp x piv)
       :collect x into lesser
       :else
       :collect x into greater
       :finally (return
    (append (qsort-2 cmp lesser)
     (list piv)
     (qsort-2 cmp greater))))))

2012年9月10日月曜日

Clojure+leiningen+Apache POI

いつか業務でこっそり使うことを夢見てExcelをいじってみます。

1. leiningenでプロジェクト作成
 lein new poitest

2. 作成されたプロジェクトのディレクトリのproject.cljを編集
(defproject poitest "0.1.0-SNAPSHOT"
  :description "Apache POI Test"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [org.apache.poi/poi "3.8"]
                 [org.apache.poi/poi-ooxml "3.8"]]
  :main poitest.core)

3. 依存解決
 lein deps

4. コードを書く
(ns poitest.core
  (:gen-class))

(import '(org.apache.poi.xssf.usermodel
          XSSFSheet
          XSSFWorkbook
          XSSFRow
          XSSFCell)
        '(org.apache.poi.ss.usermodel
          WorkbookFactory))

(import '(java.io
          FileInputStream
          FileOutputStream))

(defn load-workbook [path]
  (-> path FileInputStream. WorkbookFactory/create))

(defn rows [^XSSFSheet  sheet]
  (let [nrows (.getPhysicalNumberOfRows sheet)]
    (letfn [(f [i]
              (if (<= nrows i)
                nil
                (cons (.getRow sheet i)
                      (lazy-seq (f (inc i))))))]
      (f 0))))

(defn create-9x9 [path]
  (let [wb (XSSFWorkbook.)
        sh (.createSheet wb)]
    (dorun
     (for [y (range 9)]
       (.createRow sh y)))
    (dorun
     (for [x (range 9) y (range 9)]
       (-> (.createCell (.getRow sh y) x)
           (.setCellValue (str (* (inc x) (inc y)))))))
    (.write wb (FileOutputStream. path))))


(defn -main
  "9x9を書き込んだExcelファイルを作成->ファイルを読み込み3列目の要素を表示"
  [& args]
  (create-9x9 "test.xlsx")
  (let [wb (load-workbook "test.xlsx")
        sh (.getSheetAt wb 0)]
    (dorun 
     (for [r (rows sh)]
       (println (-> (.getCell r 2) .getStringCellValue))))))

5. 実効したりコンパイルしたり
 lein run
 lein uberjar
※ 9/22 追記
こちらのほうがシンプルそう
(defn rows [sheet]
  (keep #(.getRow sheet %)
        (range
         (.getFirstRowNum sheet)
         (inc (.getLastRowNum sheet)))))

2012年9月9日日曜日

Clojure + Emacs環境を作る

いつのまにかすごく簡単にできるようになってました。

leiningen のインストール。Clojure本体もダウンロードしてくれるらしいです。
  1. leiningenのスクリプト(lein or lein.bat)をダウンロードしてくる
  2. 実効パスの通った場所に置いて、実効権限付与(chmod u+x)
  3. leinスクリプトを実行する。(lein self-install)(要 curl or wget)
 Emacs の設定。swank-clojureのGithubのページに、新しいユーザはnreplかRitzを使うと良い、と書いてあるので、nrepl.elを入れてみます。
  1. package.elのレポジトリとしてmarmaladeを登録する
  2. package-list-packagesでパッケージ一覧を表示する
  3. clojure-modeとnreplをインストールする
  4. M-x nrepl-jack-in  でemacsの中でleiningenのreplが起動

※9/9追記

clojure-modeのバッファでeldocを有効化

(add-hook 'clojure-mode-hook
   (lambda ()
     (nrepl-eldoc-enable-in-current-buffer)))