LoginSignup
66
61

More than 5 years have passed since last update.

(少し)Java使い向け、簡単なClojure入門

Posted at

暇を持て余しているJava廃人はClojureで遊ぼう

準備

Light Table 動作確認

  • プロキシ環境の場合、環境変数HTTP_PROXYとHTTPS_PROXYを事前に設定
  1. 新しいファイルを作成
  2. ctrl-space
    • コマンドバーが開く
  3. syn
    • Syntax設定
  4. clo
    • Clojure選択
  5. エディタで適当にコード入力
    • (map - (range 10))
  6. ctrl-enter (cmd-enter)
    • コード実行

スクリーンショット 2014-05-08 14.38.46.png

スクリーンショット 2014-05-08 21.33.14.png

  • 関数実行を止めたいときは、ctrl-space後、cancelかdisconnectでコマンド探す

基本のデータ型

  • 有理数のリテラルがある(2/3など)
  • 基数(radix)として2〜36まで指定できる数値リテラルがある(2r101、36rxyZなど)

スクリーンショット 2014-05-08 14.48.24.png

  • 整数はLong、浮動小数点数はDoubleになる
  • NをつけるとBigI n t、MをつけるとBigDeci m al

スクリーンショット 2014-05-08 14.55.08.png

  • 項目はスペースで区切る。カンマはスペースと同じ
  • 文字列の連結はstrで。\aなどで文字を表す

スクリーンショット 2014-05-08 15.35.13.png

  • 特殊な文字として\return \newline \tab \space \backspace \formfeedがある
  • defで変数定義(Clojureは基本的にイミュータブルなので変更されないけど)
  • 文字列の一致比較は=でできる

スクリーンショット 2014-05-08 15.29.28.png

  • 文字列と似て非なるものとしてキーワードがある(Rubyにあるシンボルのようなもの)。:abcのようにコロンを先頭につける
  • 文字列と違い、連結や切り出しはできない。また文字列は文字のシーケンスとして扱えるが、キーワードはシーケンスではない

スクリーンショット 2014-05-08 15.42.44.png

シーケンス、コレクション

  • リスト(LinkedListのようなもの)
    • (1 2 3)
  • ベクタ(ArrayListのようなもの)
    • [2 3 4]
  • マップ(HashMapのようなもの。LinkedHashMapではない)
    • {:a 1 :b 2}
  • セット(HashSetのようなもの。LinkedHashSetではない)
    • #{:a :b :c}

 

  • これらはシーケンスという抽象化した構造として様々な関数で統一的に扱うことができる。
    • マップはclojure.lang.MapEntryのシーケンスとなる。MapEntryはclojure.lang.IPersistentVectorであるためベクタでもあり、java.util.Map.Entryでもある

スクリーンショット 2014-05-08 17.17.45.png

  • なお、Iterableもシーケンスとして扱える

シンボルとクオート、評価

  • リストは中身が1つ以上のときに評価されると、先頭の要素が関数として扱われるため(1 2 3)のようなリストを実行(評価)すると例外が発生する

スクリーンショット 2014-05-08 17.45.01.png

  • 例外を発生させないためにはクオートをつけて、評価を1回行わないようにすることができる

スクリーンショット 2014-05-08 17.52.18.png

  • (str :a :b)のようなコードのstrの部分はシンボル(clojure.lang.Symbol)であり、シンボルが関数として評価されると現在の環境から解決された(特定された)関数が実行される

  • クオートをつけると、その部分全体の評価が行われないので(def v 9) '[1 v]の結果は、[1 9]ではなく[1 v]になるというところに注意

スクリーンショット 2014-05-08 19.33.12.png

変数と関数の定義

  • 関数はdefnで定義できる
  • :pre:postで複数個の事前条件と事後条件(%が戻り値を表す)を指定できる

スクリーンショット 2014-05-08 20.02.22.png

  • 関数では複数の引数定義を行える
  • &の後ろは可変長引数を表す

スクリーンショット 2014-05-08 20.45.48.png

  • privateな関数はdefn-で、privateな変数はdef ^:privateで定義できる
  • 関数内のローカル変数はletで定義できる

スクリーンショット 2014-05-08 20.13.32.png

Javaメソッド呼び出し

  • (Math/pow 2 3)のようにjava.langパッケージにある(Clojure 1.6.0ではJava 6に存在する)クラスのstaticメソッドはimportなしに呼び出せる
  • インスタンスメソッドはメソッド名の前に.をつけて呼び出せる
  • importをするとjava.lang以外のパッケージのクラス名を(パッケージ名つけずに)使える
  • クラス名の後に.をつけるか、newを使うことで新しいオブジェクトを構築できる

スクリーンショット 2014-05-08 22.49.36.png

  • インスタンスメソッドは.を使っても呼び出せる
  • ..を使うとメソッド呼び出しを連鎖できる
  • dotoを使うと同じオブジェクトに対する複数回メソッド呼び出しが簡単にできる

スクリーンショット 2014-05-08 23.46.45.png

filter, map, reduce, for

  • filterremoveは逆の動作をする
  • fnで無名関数を作れる

スクリーンショット 2014-05-09 12.54.13.png

  • #(...)の形式でも無名関数を作れる。%または%1が第一引数、%2が第2引数、%&は残りの引数を表す
  • keepmapと似ているが、値がnilとなる結果は含まれない。

スクリーンショット 2014-05-09 13.03.00.png

  • reduceには初期値を与えることもできる
  • reduceを途中で止めたい場合はreducedを使える
  • ifwhenなどの条件で"真"と判定されるのはfalsenil以外のすべて

スクリーンショット 2014-05-09 13.17.39.png

  • 多重ループ的な処理をしたい場合は、forが便利
  • :whileは入れる場所によって動作が変わるので注意

スクリーンショット 2014-05-09 14.08.37.png

  • 結果をベクタにするfilterv, mapvもある

スレッディングマクロ

  • ->>, ->, as->などを用いることで、深いネスト構造の式をフラットに記述することができる

スクリーンショット 2014-05-09 18.10.55.png

スクリーンショット 2014-05-09 18.15.52.png

副作用と遅延シーケンス

  • 関数本体やlet本体など、複数の式が書ける場所ではprintlnなどの副作用がある式をそのまま挟み込める
  • doを使えば、どこにでも副作用がある式を入れられる。(do全体の結果は最後の式の結果となる)

スクリーンショット 2014-05-09 15.19.05.png

  • printlnによってConsoleには以下のような表示がされる

スクリーンショット 2014-05-09 15.20.12.png

  • Javaのオブジェクトに対する操作をするときもそうだが、Clojureのオブジェクトでもatom, ref, with-local-varsなどを用いて副作用がある操作をすることがある
  • Light Tableで式の途中の値が知りたい場合は、Watchの機能が使える

スクリーンショット 2014-05-09 17.04.19.png

  • mapfilterなどの関数では結果は遅延シーケンスとして返されるため、スレッドローカルな値を扱う関数と組み合わせると期待した値にならないことがある

スクリーンショット 2014-05-09 17.29.17.png

  • 遅延シーケンスを即時評価するにはdoallを使うか、ベクタやマップに変換するなどの手が使える

スクリーンショット 2014-05-09 17.32.07.png

  • 副作用だけが必要な場合はdoallの代わりにdorunが使える
  • 無限(遅延)シーケンスを評価するときにはtakeなどでその一部を取得する

スクリーンショット 2014-05-09 17.44.00.png

分配束縛

  • letdefnなど変数に値を束縛するところでは分配束縛ができる
  • :asを使うとそのベクタ全体の値を束縛できる。(defn直下のベクタでは:asは使えない)

スクリーンショット 2014-05-09 19.11.48.png

  • :keysを使うとキーワード引数のような関数呼び出しを扱える。:orでデフォルト値を指定できる

スクリーンショット 2014-05-09 19.29.33.png

  • :keysの代わりに:strs:symsで文字列とシンボルも扱えるがあまり使われない(?)

スクリーンショット 2014-05-09 19.36.45.png

ネームスペース

  • nsでネームスペースを定義できる。:requireでClojureのネームスペースを利用。:importでJavaのパッケージを利用

スクリーンショット 2014-05-09 20.54.43.png

入出力と正規表現

  • spitslurpで文字列の書き込み、読み込みができる
  • :appendなどのオプションを指定できる。:encodingでエンコーディング指定可能(デフォルトはUTF-8)

スクリーンショット 2014-05-10 11.45.36.png

  • clojure.java.ioのwriterreaderを使うとBufferedWriter, BufferedReaderでの処理ができる
  • 確実にcloseするために、with-openを使用している
  • line-seqは遅延シーケンスを返すため、with-openの外まで遅延したまま持って来れないことに注意

スクリーンショット 2014-05-10 11.47.43.png

  • re-findre-seqで正規表現マッチができる。
  • 大文字小文字の区別を排除するには(java.util.regex.Patternで定義済みの)(?i)などの埋め込みフラグ表現を使う

スクリーンショット 2014-05-10 12.12.51.png

マクロ

  • 制御構造の操作を伴う処理をしたい場合などにマクロを定義する
  • マクロの本体にシンタックスクオートをつけ、マクロの引数にアンクオート~をつけるのがまずは簡単な作り方

スクリーンショット 2014-05-10 2.08.08.png

  • マクロの展開結果を知りたいときは、macroexpand-1などを使う
  • Light Tableのkeymapに"ctrl-e" [(:eval.custom "(macroexpand-1 '__SELECTION__)")]などを登録すると選択箇所のマクロ展開に便利

スクリーンショット 2014-05-10 2.16.53.png

  • マクロ本体で変数を使う場合、変数名の後に#をつけてユニークな名前にする。(gensymされる)
  • スプライシングアンクオート~@を使うとリストが展開されてからアンクオートされる

スクリーンショット 2014-05-10 3.05.44.png

Leiningenの使用

  • REPLの起動
    lein repl
    • (doc map)(source filter)でドキュメントやソースを表示
    • Light Tableでソース見たいときはkeymapに"alt-s" [(:eval.custom "(with-out-str (clojure.repl/source __SELECTION__))" {:verbatim true})]などを登録すると便利
  • プロジェクトの作成
    lein new app myproject1
    • lein new テンプレート名 プロジェクト名の形式。テンプレート名は省略するとデフォルトのテンプレート(ライブラリ用?)が使用される。appはアプリケーション用
    • 生成されたproject.cljの:dependenciesで依存するライブラリを記述(Maven, Clojarsリポジトリから自動ダウンロード)
  • standalone.jarの作成
    lein uberjar
    • (Clojureのjarも含む)すべての依存ライブラリをまとめた単独実行可能なjarファイルを作成する
  • ヘルプ
    lein help lein help new lein help uberjar ...

よく使う関数

よく使う関数で説明をあまりしてないものはこんなところでしょうか。

  1. apply
  2. cond, if-let, when-let
  3. some, every?
  4. first, second, last
  5. cons, concat, list*
  6. mapcat, map-indexed, keep-indexed
  7. repeat, repeatedly, cycle
  8. interleave, partition
  9. identity, comp, partial
  10. take, take-last, drop, drop-last

他にもよく使う関数あるけど、まず取っ掛かりとしてこれだけわかればClojureで簡単なプログラム書けるでしょう〜

66
61
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
66
61