トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

Clojureの文法

[Clojure]

文法

  制御構文

if
if-elseを書きたい場合はこれがよい
if-let
when
when-let
case
cond
condp

  コレクション操作

Ruby
見慣れた形、データが先で関数で回す
# listの中身をトレース
[1, 2, 3].each do |n|
    puts n
end

# mapの中身をトレース
{ 1 => "a", 2 => "b", 3 => "c" }.each do |k, v|
    puts "#{k}, #{v}"
end
Clojure
Lispなのでデータが後で関数が先
# listの中身をトレース
(map #(println %) [1 2 3])
(map #(prn %) [1 2 3])

# mapの中身をトレース(doseqでやる、これはなんかいまいち…)
(doseq [[k v] {1 "a" 2 "b" 3 "c"}] (prn k v))

# mapの中身をトレース(reduce-kvでやる、こっちは関数名は良いがinit値(=0)を挟まなきゃいけないのがかっこ悪い)
(reduce-kv #(println %2 %3) 0 {1 "a" 2 "b" 3 "c"})

  Javaとの連携・移植

Java
JavaでMD5をとってみる
import java.util.Arrays;
import java.util.StringJoiner;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class prog {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        byte[] bytes = md5.digest("password".getBytes());
        StringJoiner joiner = new StringJoiner("");
        joiner.setEmptyValue("");
        for (byte b : bytes) {
            joiner.add(String.format("%02x", b));
        }
        // Java8でもbyte[]にはStreamが使えない?
        // Arrays.stream(bytes).forEach(s -> joiner.add(String.format("%02x", s)));
        System.out.println(joiner.toString());
    }
}
Clojure
がんばってClojureに移植
(import java.util.Arrays)
(import java.util.StringJoiner)
(import java.security.MessageDigest)
(import java.security.NoSuchAlgorithmException)

; letでMessageDigestのインスタンスをmd5に束縛
(let [md5 (MessageDigest/getInstance "MD5") joiner (new StringJoiner "")]
  (. joiner setEmptyValue "")
  ; ここで map を使うと遅延評価されてうまくいかない
  (doseq [eb (. md5 digest(.getBytes "password"))] (. joiner add(format "%02x" eb)))
  (println (. joiner toString)))
Clojure - クラスインスタンスのメソッドを呼ぶ
(. obj method) の形式、引数が無い時は (.method obj) でもいけるっぽい
Clojure - クラスメソッド(staticメソッド)を呼ぶ
(Class/method) の形式

  ビルド

  • requireをちゃんと書いてやらないと、依存関係の解決ができてないように見える

  イディオム

お名前: コメント: