38
Java Clojure - Adieu Java -

From Java To Clojure

Embed Size (px)

Citation preview

JavaからClojureへ- Adieu Java -

自己紹介

lagénorhynque /laʒenɔʁɛk̃/(defprofile lagénorhynque :name "Kent OHASHI" :account @lagenorhynque :company 株式会社オプト :languages [Clojure Haskell Python Scala English français Deutsch русский] :interests [プログラミング 語学 数学])

Lisp × Java

言語としてのJava

言語としてのJavaの問題点

関数型プログラミング(FP)サポートの不足

もっとFPしたい! (OOP要素も静的型付けも必須ではない)

冗長なシンタックス

もっとシンプルに書きたい!

柔軟性/拡張性の不足

もっと自由に書きたい!

独断と偏見によるJVM言語比較

factor Java Groovy Scala Kotlin Clojure

FP support × △ ◯ △ ◯

simplicity × ◯ △ ◯ ◎

�exibility × ◯ ◯ ◯ ◎

Clojure を使えば、

言語としての Java とはお別れできる!!

Adieu, Java !Javaともこれで本当にお別れだね(;_;)/~~~

What is Clojure?

Clojureの名前の由来

Clojure is pronounced exactly like closure, wherethe s/j has the zh sound as in azure, pleasure etc.

The name was chosen to be unique. I wanted toinvolve c (c#), l (lisp) and j (java).

Once I came up with Clojure, given the pun onclosure, the available domains and vast emptiness

of the googlespace, it was an easy decision.

― Rich Hickey, creator of Clojure

cf. meaning and pronunciation of Clojure

Clojure /ˈkloʊʒɚ/※ NOT /ˈkloʊd͡ʒɚ/

element meaning

/ˈkloʊʒɚ/ クロージャ(closure), 関数型プログラミング

C C#(.NET) as a platform, .NET言語

l Lisp方言

j Java as a platform, JVM言語

1. FP言語としてのClojure

2. Lisp方言としてのClojure

3. JVM言語としてのClojure

FP言語としてのClojure

イミュータブルなList, Vector, Map, Set, etc.

user=> '(1 2 3) (1 2 3)

user=> [1 2 3] [1 2 3]

user=> {:a 1 :b 2 :c 3} {:a 1, :b 2, :c 3}

user=> #{1 2 3} #{1 3 2}

高階関数(filter, map, reduce, etc.)

user=> (def xs [1 2 3]) #'user/xs

user=> (filter odd? xs) (1 3)

user=> (map #(* % %) xs) (1 4 9)

user=> (reduce + 0 xs) 6

user=> (reduce + 0 (map #(* % %) (filter odd? xs))) 10

user=> (->> xs #_=> (filter odd?) #_=> (map #(* % %)) #_=> (reduce + 0)) 10

ちなみに、

#( ) は

#(* % %)

↓↓↓(fn [x] (* x x))

に相当するリーダマクロ

ちなみに、

->> は

(->> a (f x) (g y) (h z))

↓↓↓(h z (g y (f x a)))

に展開されるマクロ(threading macroの一種)

遅延シーケンス

user=> (def nats (iterate inc 0)) #'user/nats

user=> (take 10 nats) (0 1 2 3 4 5 6 7 8 9)

user=> (take-while #(< % 10) nats) (0 1 2 3 4 5 6 7 8 9)

Lisp方言としてのClojure

S式( )S-expressions

(f a b c ...)

f: 関数, マクロ, 特殊形式a, b, c, ...: 引数

cf. Java

f(a, b, c, ...)

関数/メソッドの定義も

// Java public void greet(String name) { System.out.println("Bonjour, " + name + " !"); }

S式

;; Clojure (defn greet [name] (println (str "Bonjour, " name " !")))

名前空間/パッケージの宣言もインポートも

// Java package demo_app;

import java.io.IOException; import java.util.ArrayList; import java.util.List;

S式

;; Clojure (ns demo-app.core (:import (java.io IOException) (java.util ArrayList List)))

first(≒ car), rest(≒ cdr), cons, ...

user=> (def xs [1 2 3]) #'user/xs

user=> (first xs) 1

user=> (rest xs) (2 3)

user=> (cons 0 xs) (0 1 2 3)

S式のコードはそのままデータとして扱える(code as data; )homoiconicity

user=> (first '(def xs [1 2 3])) def

user=> (rest '(def xs [1 2 3])) (xs [1 2 3])

user=> (cons 'def '(xs [1 2 3])) (def xs [1 2 3])

user=> (eval (cons 'def '(xs [1 2 3]))) #'user/xs

Lispマクロ強力なコンパイル時メタプログラミング機構

user=> (defmacro unless ; clojure.core/if-not マクロを再実装しただけ #_=> ([test then] #_=> `(unless ~test ~then nil)) #_=> ([test then else] #_=> `(if (not ~test) #_=> ~then #_=> ~else))) #'user/unless

user=> (unless (= 1 2) :ok) :ok

user=> (macroexpand '(unless (= 1 2) :ok)) (if (clojure.core/not (= 1 2)) :ok nil)

ちなみに、

関数定義の defn は

user=> (macroexpand #_=> '(defn greet [name] #_=> (println (str "Bonjour, " name " !"))))(def greet (clojure.core/fn ([name] (println (str "Bonjour, " name " !")))))

特殊形式 def, fn を利用したマクロ

大量の括弧を扱うのがつらい?

⇒ Lisp編集用プラグインがあれば非常に快適

The Animated Guide to Paredit

Parinfer - simpler Lisp editing

JVM言語としてのClojure

Javaのclassファイルにコンパイルjarとして実行可能

$ lein new app demo-app Generating a project called demo-app based on the 'app' template.

$ cd demo-app/

$ lein uberjar Compiling demo-app.core Created /Users/lagenorhynchus/code/demo-app/target/uberjar/demo-app-0.1.0-SNAPSHOT.jar Created /Users/lagenorhynchus/code/demo-app/target/uberjar/demo-app-0.1.0-SNAPSHOT-standalone.jar

$ java -jar target/uberjar/demo-app-0.1.0-SNAPSHOT-standalone.jar Hello, World!

Javaメソッドの呼び出し

staticメソッド

// Java Integer.parseInt("123")

;; Clojure (Integer/parseInt "123")

インスタンスメソッド

// Java "a b c".split("\\s")

;; Clojure (.split "a b c" "\\s")

破壊的な初期化/設定

// Java java.util.Map<String, Integer> m = new java.util.HashMap<>(); m.put("a", 1); m.put("b", 2); m.put("c", 3); return m;

;; Clojure (doto (java.util.HashMap.) (.put "a" 1) (.put "b" 2) (.put "c" 3))

メソッドチェーン

// Java new StringBuilder() .append("a") .append("b") .append("c") .toString()

;; Clojure (.. (StringBuilder.) (append "a") (append "b") (append "c") toString) ;; または (-> (StringBuilder.) (.append "a") (.append "b") (.append "c") .toString)

JavaコレクションAPIとの連携

Javaのコレクション → Clojureの関数

user=> (def xs (doto (java.util.ArrayList.) #_=> (.add 1) #_=> (.add 2) #_=> (.add 3))) #'user/xs

user=> (class xs) java.util.ArrayList

user=> xs [1 2 3]

user=> (map inc xs) (2 3 4)

Clojureのコレクション → Javaのメソッド

user=> (def xs [1 2 3 4 5]) #'user/xs

user=> (class xs) clojure.lang.PersistentVector

user=> (instance? java.util.List xs) true

user=> (.subList xs 1 4) [2 3 4]

cf. Google Sheets API (Java版)の利用例

// Java public Integer duplicateWorksheet(Sheets sheets, String spreadsheetId, Integer worksheetId, String worksheetName) List<Request> reqs = Arrays.asList( new Request().setDuplicateSheet( new DuplicateSheetRequest().setSourceSheetId(worksheetId) .setNewSheetName(worksheetName) .setInsertSheetIndex(1) ) ); return executeUpdate(sheets, spreadsheetId, worksheetId, reqs) .getReplies() .get(0) .getDuplicateSheet() .getProperties() .getSheetId(); }

;; Clojure (defn duplicate-worksheet [sheets spreadsheet-id worksheet-id worksheet-name] (let [reqs [(-> (Request.) (.setDuplicateSheet (-> (DuplicateSheetRequest.) (.setSourceSheetId worksheet-id) (.setNewSheetName worksheet-name) (.setInsertSheetIndex (int 1)))))]] (-> (execute-update sheets spreadsheet-id worksheet-id reqs) .getReplies first .getDuplicateSheet .getProperties .getSheetId)))

ほかにも

core.async

transducers

clojure.spec

ClojureScript

etc.

Clojure ならFPとLispとJavaの力を引き出して

もっとシンプルに、もっと自由に、プログラミングできる!!

Vive les S-expressions !

S式万歳!

Further Reading

: Clojure公式

: Clojureのビルドツール

: Clojureのビルドツール

: ClojureのオンラインREPLのひとつ

: ClojureScriptのオンラインREPLのひとつ

第7章 Clojure

Clojure

Leiningen

Boot

Try Clojure

Replumb REPL

『7つの言語 7つの世界』

『プログラミングClojure 第2版』