2017.10.4「教養としてのClojure」の発表資料です
Θ͔Δʂ+BWBUP$MPKVSFڧཁڭཆͱͯ͠ͷ$MPKVSFEDMK!UPEPLSָ͘͠
View Slide
୭ͩాॴॣ༎!UPEPLSීஈ4DBMBΤϯδχΞϓϥΠϕʔτͰ$MPKVSF$MPKVSF4DSJQUΛͪΐͪ͜ΐ͜৮Δॳ৺ऀ
͓͢͠Δ͜ͱw 8IZ-JTQ 8IZ$MPKVSF w جຊతͳจ๏ʹ͍ͭͯw +BWBͷΞϨΛ$MPKVSFͰॻ͍ͯΈΑ͏
8IZ-JTQw େֶͰ৮͍ͬͯͨͷͰw ࣄͷͨΊw ʮܭࢉػϓϩάϥϜͷߏͱղऍʯΛಡΉͨΊw &NBDTϢʔβʔͩͬͨͷͰw +BWB4DSJQU$ͷൽΛ͔Ϳͬͨ-JTQͩͱฉ͍ͯw ϧϯό͕-JTQͰಈ͍͍ͯΔͱฉ͍ͯw FUD
ϙʔϧɾάϨΞϜ7JBXFCۀऀ:$PNCJOBUPSઃऀ
-JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭϙʔϧɾάϨΞϜ7JBXFCۀऀ:$PNCJOBUPSઃऀ
ී௨ͷౕΒͷ্Λߦ͚ɻ-JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭϙʔϧɾάϨΞϜ7JBXFCۀऀ:$PNCJOBUPSઃऀ
ී௨ͷౕΒͷ্Λߦ͚ɻ-JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭϙʔϧɾάϨΞϜ7JBXFCۀऀ:$PNCJOBUPSઃऀ:BIPPʹച٫
ී௨ͷౕΒͷ্Λߦ͚ɻ-JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭϙʔϧɾάϨΞϜ7JBXFCۀऀ:$PNCJOBUPSઃऀΘͨ͠ී௨ͷϓϩάϥϚ-JTQͰΣϒαʔϏεΛͭ͘Δͱ:BIPPʹԯԁͰങͬͯΒ͑Δʂʂʂ:BIPPʹച٫
ͳͥ$PNNPO-JTQ4DIFNFͰͳ͘ $MPKVSFʁ
8IZ$MPKVSFw ಡΈ͢͞w ׅހͷ͕গͳ͍w ׅހͷछྨ͕ଟ͍w #FUUFS+BWBͰ͋Δ͜ͱw ϦονɾώοΩʔ
ಡΈ͢͞$MPKVSF-JTQͷ౷ΛࣺͯɺಡΈ͢͞ΛͱͬͨʢΒ͍͠ʣͦͷͨΊɺ$PNNPO-JTQ4DIFNFʹൺͯɾׅހ͕গͳ͍ɾׅހͷछྨ͕ଟ͍
ಡΈͨ͢͞ͱ͑ؔͷҾ$PNNPO-JTQ4DIFNF$MPKVSF(defun square (x)(* x x))(define (square x)(* x x))(defn square [x](* x x))
ಡΈͨ͢͞ͱ͑BTTPDJBUJWFͳσʔλߏʢ+BWBͰ͍͏.BQʣ(defparameter greet '(("ja" . "͜Μʹͪ")("en" . "hello")("fr" . "bonjour"))(define greet '(("ja" "͜Μʹͪ")("en" "hello")("fr" "bonjour"))$PNNPO-JTQ4DIFNF(def greet {"ja" "͜Μʹͪ""en" "hello""fr" "bonjour"})$MPKVSF
#FUUFS+BWBͰ͋Δ͜ͱ(.concat "hello" " world") ; -> "hello world";; "hello".concat(" world");(.getName String) ; -> "java.lang.String"; String.getName(.. user getAddress getCity) ; -> "Shibuya"; user.getAddress().getCity();(.-x (new java.awt.Point 2 3)) ;; 2;; -> new java.awt.Point(2, 3).xMath/PI ;; 3.141592653589793;; Math.PI+BWBͷ"1*͕ͦͷ··ݺͼग़ͤΔ☕️ˠ+BWBͰͰ͖Δ͜ͱͰ͖Δʂͱ͍͏҆৺ײ
8IZ$MPKVSFw ಡΈ͢͞w ׅހͷ͕গͳ͍w ׅހͷछྨ͕ଟ͍w #FUUFS+BWBͰ͋Δ͜ͱw ͳʹΑΓָ͍͠ʂ
ͳʹΑΓָ͍͠ʂw ߴ֊ؔԆධՁͳͲͷؔܕϓϩάϥϛϯάελΠϧw ঢ়ଶʹ͍ͭͯͷߟ͑ํɺ*EFOUJUZ 4UBUF 7BMVFͷw γϯϓϧ͞ʹ͍͍ͭͯΖ͍Ζܹత
[email protected]@FBTZ
ͭ·Γ$MPKVSF ͱ͖͍ͬͭ͢ʂ ֶͼָ͕͍͋ͬͯ͠ʂ
+BWBUP$MPKVSFͯ͠ΈΑ͏w )FMMPXPSMEw ࢛ଇԋࢉw มએݴw ؔએݴw ແ໊ؔ
खݩͰࢼ͢ͳΒ5SZ$MPKVSF͕͓͢͢Ίw 5SZ$MPKVSFIUUQXXXUSZDMKDPN
·ͣγϯλοΫεʹ׳ΕΑ͏ʂ
-JTQͷγϯλοΫεׅހͷ࢝·Γ͔ΒऴΘΓ·Ͱ͕୯Ґ(ԿΒ͔ͷॲཧ ॲཧͷରͳͲ…)
͏׳Ε·ͨ͠Ͷ
)FMMPXPSMESystem.out.println("Hello world");+BWB$MPKVSF
)FMMPXPSMESystem.out.println("Hello world");+BWB(println "Hello world")$MPKVSF
࢛ଇԋࢉ12 + 4010 - 12 * 35 / 2+BWB$MPKVSF
࢛ଇԋࢉ12 + 4010 - 12 * 35 / 2+BWB(+ 12 40)(- 10 1)(* 2 3)(/ 5 2)$MPKVSF
࢛ଇԋࢉ12 + 4010 - 12 * 35 / 2+BWB(+ 12 40)(- 10 1)(* 2 3)(/ 5 2) ; -> 5/2 Λѻ͏Ratioܕ$MPKVSF
˞จࣈྻͷ݁߹TUSจࣈྻͷ݁߹Ͱͳ͘TUSΛ͏(+ "hoge" "fuga")ClassCastException java.lang.String cannotbe cast to java.lang.Numberclojure.lang.Numbers.add (Numbers.java:128)(str "hoge" "fuga")hogefuga
มએݴint x = 10;+BWB$MPKVSF
มએݴint x = 10;+BWB(def x 10)$MPKVSF
มએݴMFUʹΑΔϩʔΧϧมఆٛʢϩʔΧϧଋറʣΛݟ͔͚Δ΄͏͕ଟ͍(let [x 10](+ x 3)); xletͷׅހ͚ͩͰࢀরͰ͖Δ$MPKVSF
ؔએݴpublic int f(int x) {return x + 1;}+BWB$MPKVSF
ؔએݴpublic int f(int x) {return x + 1;}+BWB(defn f [x](+ x 1))$MPKVSF
ແ໊ؔx -> x * 2+BWB$MPKVSF
ແ໊ؔx -> x * 2+BWB(fn [x] (* x 2))$MPKVSF
ແ໊ؔx -> x * 2+BWB(fn [x] (* x 2))#(* % 2) ; ↑ͷ؆ܿͳه๏$MPKVSF
ແ໊ؔΛͬͯΈΔArrays.asList(1, 2, 3).stream().map(x -> x * 2).collect(Collectors.toList());// List(2, 4, 6)+BWB$MPKVSF
ແ໊ؔΛͬͯΈΔArrays.asList(1, 2, 3).stream().map(x -> x * 2).collect(Collectors.toList());// List(2, 4, 6)+BWB(map (fn [x] (* x 2)) '(1 2 3))$MPKVSF
ແ໊ؔΛͬͯΈΔArrays.asList(1, 2, 3).stream().map(x -> x * 2).collect(Collectors.toList());// List(2, 4, 6)+BWB(map (fn [x] (* x 2)) '(1 2 3))(map #(* % 2) '(1 2 3))$MPKVSF
ͬͱ+BWBUP$MPKVSFͯ͠ΈΑ͏w γʔέϯεͷจࣈྻ݁߹w จࣈྻ͕ۭPSۭനจࣈ͔Ͳ͏͔ͷఆw *OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉ
γʔέϯεͷจࣈྻ݁߹
γʔέϯεͷจࣈྻ݁߹String[] words = { "a", "b", "c" };StringBuilder sb = new StringBuilder();for(String word : words) {sb.append(word);}System.out.println(sb.toString()); // "abc"// Java8System.out.println(String.join("", words));+BWBͷ߹
γʔέϯεͷจࣈྻ݁߹(def words '("a" "b" "c"))(clojure.string/join "" words); ͘͠(apply str words)DMPKVSFͷ߹
w ՄมҾΛड͚औΔؔʹγʔέϯεΛ͍ͨ͠ͱ͖ʹ͏w +BWB4DSJQUͷBQQMZͱҰॹBQQMZ(str ["a" "b" "c"]) ; -> ["a" "b" "c"](apply str ["a" "b" "c"]) ; -> abc; (str "a" "b" "c") ͱಉ͡
จࣈྻ͕ۭPSۭനจࣈ͔Ͳ͏͔ͷఆ
จࣈྻ͕ۭPSۭനจࣈ͔Ͳ͏͔ͷఆpublic static boolean isBlank(final CharSequence cs) {int strLen;if (cs == null || (strLen = cs.length()) == 0) {return true;}for (int i = 0; i < strLen; i++) {if (!Character.isWhitespace(cs.charAt(i))) {return false;}}return true;}isBlank("hello!"); // falseisBlank(null); // trueisBlank(""); // trueisBlank("\r\n\t") // true+BWBͷ߹
จࣈྻ͕ۭPSۭനจࣈ͔Ͳ͏͔ͷఆ(defn blank? [s](every? #(Character/isWhitespace %) s))(blank? "helllo!") ; false(blank? nil) ; true(blank? "") ; true(blank? "\n\r\t") ; trueDMPKVSFͷ߹
FWFSZw ίϨΫγϣϯͷશͯͷཁૉʹରͯ͠ ड़ޠؔʢCPPMFBOΛฦؔ͢ʣΛద༻w શͯUSVFͳΒUSVF(every? even? '(2 4 6)) ; true(every? even? '(1 2 3)) ; false
*OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉ
*OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉtry(BufferedReader reader =new BufferedReader(new InputStreamReader(new FileInputStream("./test.txt")))) {StringBuilder sb = new StringBuilder();String line;while((line = reader.readLine()) != null) {sb.append(line);}System.out.println(sb.toString());}+BWBͷ߹
*OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉ(require [clojure.java.io :as io])(with-open [bis (io/input-stream "./test.txt")](println (slurp bis)))$MPKVSFͷ߹
DMPKVSFKBWBJPJOQVUTUSFBNw ҾͰड͚औͬͨ'JMF 63* 63- 4PDLFU CZUFྻ 4USJOHʢͰදݱ͞ΕͨύεʣΛ*OQVU4USFBNʹมw มޙͷ*OQVU4USFBNͷσϑΥϧτ࣮ KBWBJP#VGGFSFE*OQVU4USFBN(require '[clojure.java.io :as io])(io/input-stream "http://example.com")
XJUIPQFOw +BWBͰ͍͏USZXJUISFTPVSDFߏจɺ 4DBMBͰ͍͏-PBO1BUUFSOΛ࣮ݱ͢Δͷw XJUIPQFOͰPQFOͨ͠ϦιʔεউखʹDMPTF͞ΕΔ(with-open [in (io/input-stream "./test.txt")](do-something in));; already closed!
TMVSQw 3FBEFS #VGGFSFE3FBEFS *OQVU4USFBN 'JMF 63* 63- 4PDLFU CZUFྻ DIBSྻΛड͚औΓɺ จࣈྻʹͯ͠ฦ͢w ରʹͳΔॻ͖ग़͠ͷͨΊͷؔTQJU(spit "./test.txt" "hello I/O!")(println (slurp "./test.txt"));; -> hello I/O!
*OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉ(require [clojure.java.io :as io])(with-open [bis (io/input-stream "./test.txt")](println (slurp bis)))$MPKVSFͷ߹;; όοϑΝϦϯάͤͣʹϑΝΠϧ͔ΒಡΉ͚ͩͳΒˣͰOK(println (slurp "./test.txt"))
ࠓ+BWBUP$MPKVSFͨ͠ͷw )FMMPXPSMEw ࢛ଇԋࢉw มએݴw ؔએݴw ແ໊ؔw γʔέϯεͷจࣈྻ݁߹w จࣈྻ͕ۭPSۭനจࣈ͔Ͳ͏͔ͷఆw *OQVU4USFBN͔ΒจࣈྻΛͯ͢ಡΉ