Clojureåå¼·æ¥è¨ï¼ãã®ï¼ ï¼ï¼ï¼ æ§è½ã®æé©å
ããã«ã¡ã¯ã
å¾ã
ã«æ¸ãããã¨ãåºãã£ã¦ãã¦ã¯ãã¾ãããã¾ã ï¼åã®ï¼ã
ã¨ããããå°éã«ç¶ãã¾ãã
åç« ã§è¿°ã¹ãJavaã®å¼ã³åºãã§è¿°ã¹ãæ¹æ³ã使ã£ã¦Javaãå¼ã¶ã®ãClojureã§ã¯æ®éã
ããã§åºæ¬çã«ã¯ååã«é«éã®ã¯ãã ããããã«é«éåãè¡ããã¨ãã§ããã
ããã¯å¤é¨IFã«ã¯å½±é¿ãä¸ããã«åºæ¥ããããå¾ãããã¥ã¼ãã³ã°ã»ã»ã»ã¨ãããã¨ãå¯è½ã
1.æ§è½ã®ããã«ããªããã£ãã使ã
ããã¾ã§ã¯ãã©ã¡ã¼ã¿ã«åæ
å ±ãã¤ãã¦ããªãã£ãã
ï¼ã¡ã¿ãã¼ã¿ã§åãã³ããã¤ããããã¨ãããã¨ã«ã¤ãã¦ã¯æ¸ãã¦ã¾ãããã
ããã¯ã³ã¼ãããã£ããããããããã®åãã¼ã¿åããããã«ãããªããæ§è½ä¸ã®ãªã¼ãããããçºçããã
ãâããã®ããæ¹ãããã¯ã¿ã¤ãã³ã°ã¨ãã模æ§ã
ä¾ã¨ãã¦ãï¼ããï½ã¾ã§è¶³ãåãããé¢æ°ãèããã
(defn sum-to [n] (loop [i 1 sum 0] (if (<= i n) (recur (inc i) (+ i sum)) sum))) #'user/sum-to user=> (sum-to 100) 5050
ãã®é¢æ°ã®å®è¡æéãè¨æ¸¬ãããè¨æ¸¬ã«ã¯ä¸è¨ã®dotimesãã¯ãã¨timeé¢æ°ã使ç¨ã§ããã
(dotimes bindings & body)
; bindings => name n
dotimesã¯nameã0ãn-1ã¾ã§ãã¤ã³ãããªããç¹°ãè¿ãå®è¡ããã
ä»åã®å ´åã¯nameèªä½ã¯ç¨ããªããã_ã«ãã¤ã³ãããã¦å®è¡ããã
user=> (dotimes [_ 10](time (sum-to 100000))) "Elapsed time: 1.228224 msecs" "Elapsed time: 1.26989 msecs" "Elapsed time: 1.176595 msecs" "Elapsed time: 1.180218 msecs" "Elapsed time: 1.123155 msecs" "Elapsed time: 1.196522 msecs" "Elapsed time: 1.542979 msecs" "Elapsed time: 0.825156 msecs" "Elapsed time: 0.706501 msecs" "Elapsed time: 0.820627 msecs" nil
â»è¿½è¨
æ´ã«ãcriteriumã使ã£ã¦è¨æ¸¬ãè¡ãã
ããã¨çµæã¯ä¸è¨ã®éãã
user=> (crit/bench (sum-to 100000)) WARNING: Final GC required 1.6129901392836168 % of runtime Evaluation count : 49500 in 60 samples of 825 calls. Execution time mean : 1.260639 ms Execution time std-deviation : 47.370884 μs Execution time lower quantile : 1.210134 ms ( 2.5%) Execution time upper quantile : 1.382792 ms (97.5%) Overhead used : 4.145950 ns Found 6 outliers in 60 samples (10.0000 %) low-severe 5 (8.3333 %) low-mild 1 (1.6667 %) Variance from outliers : 23.8473 % Variance is moderately inflated by outliers
ãããæ´ã«é«éåããã«ã¯Clojureã®é¢æ°ã«å¯¾ãã¦è¿½è¨ããintåã§ãããã¨ãéç¥ããã
â»2013/04/20 ä¸è¨ã®ã³ã¼ãã«ãã°ããã£ãããæ´æ°æ¸ã¿
(defn sum-to-int [n] (let [n (int n)] (loop [i (int 1) sum (int 0)] (if (<= i (int i) n (int n)) (recur (inc i) (+ i sum)) sum))))
ããããã¨å®è¡æéã¯ä¸è¨ã®ããã«ãªãã
user=> (dotimes [_ 10](time (sum-to-int 100000))) "Elapsed time: 20.259719 msecs" "Elapsed time: 16.261216 msecs" "Elapsed time: 10.265046 msecs" "Elapsed time: 10.58161 msecs" "Elapsed time: 10.351546 msecs" "Elapsed time: 10.111971 msecs" "Elapsed time: 10.428989 msecs" "Elapsed time: 11.088387 msecs" "Elapsed time: 10.124652 msecs" "Elapsed time: 10.366943 msecs"
user=> (crit/bench (sum-to-int 100000)) Evaluation count : 4680 in 60 samples of 78 calls. Execution time mean : 13.179291 ms Execution time std-deviation : 450.355311 μs Execution time lower quantile : 12.837863 ms ( 2.5%) Execution time upper quantile : 14.645732 ms (97.5%) Overhead used : 4.145950 ns Found 7 outliers in 60 samples (11.6667 %) low-severe 2 (3.3333 %) low-mild 5 (8.3333 %) Variance from outliers : 20.6197 % Variance is moderately inflated by outliers
ã»ã»ã»ã»ã¦ããããéã«é
ããªã£ããã¨ãããä½æ
ãããªã£ãã
ã»ã»ã»ãã®ãããçµå±åæè¨ã«ããå®è¡æéåä¸ã«ã¤ãã¦ã¯ãã£ã±ãã¨ããç¶æ³ã
åçã«åã確å®ãããå ´åã§ããä¸åº¦ç¢ºå®ãããã°ä»¥å¾éããªããªã©ã®æªç½®ããããã§ããããã»ã»ã»ï¼
åæè¨ã®ä»ã«ãClojureã®ä¸è¬çãªæ¼ç®åã¯çµæããªã¼ãã¼ããã¼ããªããã©ãããã§ãã¯ãã¦ããã
ãããç¡è¦ãããã¨ããã«é度ã¯ä¸ããã
ã»ã»ã»ã¨ã¯ãããåæè¨ã«æ¯ã¹ãã¨æ©æµã¯éåå°ãããªããã
user=> (defn sum-to-uncheck [n] (let [n (int n)] (loop [i (int 1) sum (int 0)] (if (<= i (int i) n (int n)) (recur (inc i) (unchecked-add i sum)) sum)))) #'user/sum-to-uncheck user=> (dotimes [_ 10](time (sum-to-uncheck 100000))) "Elapsed time: 18.555974 msecs" "Elapsed time: 17.44641 msecs" "Elapsed time: 10.129634 msecs" "Elapsed time: 10.635956 msecs" "Elapsed time: 10.423101 msecs" "Elapsed time: 10.402721 msecs" "Elapsed time: 10.794918 msecs" "Elapsed time: 10.510054 msecs" "Elapsed time: 11.55078 msecs" "Elapsed time: 10.513225 msecs"
ã¨ã¯ãããintã§ã®åãã³ããã¤ããç¶æ
ã¯ãã¡ããã¡ããã¦ãããå¯èªæ§ãç ç²ã«ãªãã
åºæ¬ã¯åãã³ããªãã®ãã¼ã¸ã§ã³ã§è¡ããããã«ããã¯ã¨ãªã£ãå ´åã«å¯¾å¦ããã»ã»ã»ãããã§ãããããã
å°ãsum-toã®ä¾ã¯Clojureã¨ãã¦ã¯ã°ãæ£ç´ãªæ¸ãæ¹ã§ãå®éã¯reduceã使ç¨ãã¦æ¸ãã
ã·ã¼ã±ã³ã¹ã®ç·åãæ±ãããã¨ã¯ã¾ãæåã®ï¼ã¤ã®è¦ç´ ãå ç®ããããã次ã®è¦ç´ ã«å ç®ãã»ã»ã»
ã¨ç¹°ãè¿ããã¨ã ããã
reduceã使ç¨ããã¨åæ§ã®å¦çã¯ä¸è¨ã®ããã«ãªãã
ã»ã»ã»ãªã®ã ããå®ã¯é
ãï¼æ±
user=> (defn better-sum [n] (reduce + (range 1 (inc n)))) #'user/better-sum user=> (dotimes [_ 10](time (better-sum 100000))) "Elapsed time: 7.456752 msecs" "Elapsed time: 7.226687 msecs" "Elapsed time: 3.628515 msecs" "Elapsed time: 3.518917 msecs" "Elapsed time: 3.718639 msecs" "Elapsed time: 4.544701 msecs" "Elapsed time: 3.505783 msecs" "Elapsed time: 3.466834 msecs" "Elapsed time: 3.611758 msecs" "Elapsed time: 3.701429 msecs"
å®éã®ã¨ãããããã§è¡ãã¹ãã¯ãæ£ããã¢ã«ã´ãªãºã ãé¸æãããã¨ãããã¨ã
ä»åã®å ´å1ãnã®åè¨ã¯n * (n + 1) / 2 ã§æ±ããããã
ãã®å ´ååãã³ãã使ããªãã¦ãç¹°ãè¿ããè¡ãã©ããªãã¼ã¸ã§ã³ããæ©ãã
user=> (defn best-sum [n] (/ (* n (inc n)) 2)) #'user/best-sum user=> (dotimes [_ 10](time (best-sum 100000))) "Elapsed time: 0.072461 msecs" "Elapsed time: 0.00951 msecs" "Elapsed time: 0.014945 msecs" "Elapsed time: 0.009057 msecs" "Elapsed time: 0.009058 msecs" "Elapsed time: 0.009058 msecs" "Elapsed time: 0.008605 msecs" "Elapsed time: 0.014039 msecs" "Elapsed time: 0.008604 msecs" "Elapsed time: 0.009057 msecs"
æ§è½ã¨ããã®ã¯åä»ã ããé度ãããããã¨ãã¦ã³ã¼ããããããã«ãã¡ããã¡ããããã®ãä¸çªNGã
ã¾ãé©åãªã¢ã«ã´ãªãºã ãé¸ãã§æ£ããåãã³ã¼ããæ¸ãã
ã»ã»ã»ããã«ã¤ãã¦ã¯ãClojureã ããããä»ã®è¨èªã ãããå¤ãããªã模æ§ã
2.åãã³ãã®ä»ä¸
Clojureã§ã¯é¢æ°ã®ä»®å¼æ°ãletã®ãã¤ã³ããå¤æ°åãå¼ã«åãã³ããã¤ãããã¨ãã§ããã
åãã³ãã¯ä¸è¨ã®å½¹ç®ãæã¤ã
- æ§è½ä¸ã¯ãªãã£ã«ã«ãªãã¹ã®æé©å
Clojureã¨Javaä¸çã®ããåãã¯ãªãã¬ã¯ã·ã§ã³ãç¨ããåå¤æãç¨ãã¦ãããã
ãããä¸é¨çç¥ããããã¨ãå¯è½ã
- è¦æ±ããã¦ããåã®ããã¥ã¡ã³ã
docã®è¿ãå¤ï¼
- è¦æ±ãããåãã©ã³ã¿ã¤ã ã«å¼·å¶ãã
çµæãï¼ã¤ç®ã®æ§è½ã®ä»¶ãããããå®å ¨æ§ãå¢ãã
ã¹ãã·ã£ã«å¤æ°*warn-on-reflection*ã«trueãã»ããããã¨ãClojureãJavaã¨ã®éã§ã©ããããæ
å ±ãæ¨æ¸¬ãã¦ããããç¥ããã¨ãã§ããã
ãã®ä¸ã§ãé¢æ°ãå®ç¾©ããã¨ä¸è¨ã®ãããªwarningãåºãã
user=> (set! *warn-on-reflection* true) true user=> (defn describe-class [clazz] {:name (. clazz getName) :final (java.lang.reflect.Modifier/isFinal (. clazz getModifiers)) }) Reflection warning, NO_SOURCE_PATH:3:37 - reference to field getName can't be resolved. Reflection warning, NO_SOURCE_PATH:3:98 - reference to field getModifiers can'tbe resolved.
ããã¯Clojureãå¤æ°clazzã®åãé¢æ°å®ç¾©æç¹ã§ã¯åãããªãããã«çºçãã¦ããã¨ã©ã¼ã§ãã模æ§ã
ãªã¼ãã¡ã¿ãã¼ã¿ãç¨ãã¦åãã³ããæå®ãã¦ããã¨è¦åã¯çºçãããªããªãã
user=> (defn describe-class [#^Class clazz] {:name (. clazz getName) :final (java.lang.reflect.Modifier/isFinal (. clazz getModifiers)) }) #'user/describe-class
è¦åã表示ãããªãç¶æ
ã§ã¯Clojureã®ã³ã¼ãã¯Javaã®ã³ã¼ãã¨åçã«ã³ã³ãã¤ã«ãããåçã®ã¹ãã¼ããæã¤ã
ãã®ä¸ã§ãå½ç¶ãªããClass以å¤ã®ãã®ã渡ãã¨ClassCastExceptionãæããããã
user=> (describe-class "Test") ClassCastException java.lang.String cannot be cast to java.lang.Class user/describe-class (NO_SOURCE_FILE:4) user=> (describe-class :class) ClassCastException clojure.lang.Keyword cannot be cast to java.lang.Class user/describe-class (NO_SOURCE_FILE:4) user=> (describe-class 10) ClassCastException java.lang.Long cannot be cast to java.lang.Class user/describe-class (NO_SOURCE_FILE:4)
ãã¨ã¯æ§è½çã«ã¯ã©ãã»ã©å·®åãåºããã確èªããã
â åãã³ããªã
user=> (defn describe-class [clazz] {:name (. clazz getName) :final (java.lang.reflect.Modifier/isFinal (. clazz getModifiers)) }) Reflection warning, NO_SOURCE_PATH:20:37 - reference to field getName can't be resolved. Reflection warning, NO_SOURCE_PATH:20:98 - reference to field getModifiers can't be resolved. #'user/describe-class user=> (time (dotimes [_ 10000] (describe-class (. "Test" getClass)))) "Elapsed time: 73.380385 msecs" "Elapsed time: 74.76939 msecs" "Elapsed time: 178.357795 msecs" "Elapsed time: 128.481343 msecs" "Elapsed time: 64.758774 msecs" "Elapsed time: 86.242378 msecs" "Elapsed time: 73.174775 msecs" "Elapsed time: 85.438503 msecs"
â åãã³ããã
user=> (defn describe-class [#^Class clazz] {:name (. clazz getName) :final (java.lang.reflect.Modifier/isFinal (. clazz getModifiers)) }) #'user/describe-class user=> (time (dotimes [_ 10000] (describe-class (. "Test" getClass)))) "Elapsed time: 3.446923 msecs" "Elapsed time: 3.702352 msecs" "Elapsed time: 2.0235 msecs" "Elapsed time: 4.013033 msecs" "Elapsed time: 3.946005 msecs" "Elapsed time: 3.884413 msecs" "Elapsed time: 3.621738 msecs" "Elapsed time: 3.367668 msecs"
ããªã大ããªéããåºããã¨ããããã
ä»åã®å ´åã¡ã½ããã®è¦æ¨¡ãå°ããããã«ãªãã¬ã¯ã·ã§ã³ã«ããè² è·ã®å²åã大ããã®ãããããªãããï¼ï¼åç¨ã®å¦çæéã®å·®åãçºçãã¦ããã
ã»ã»ã»ã¨ãããããå¼ã³åºãåæ°ãé常ã«å¤ããªãã¨æ¨æ¸¬ãããå ´åã¯å©ç¨è
å´ã§æ¸ãã«ãããªããªãç¨åº¦ã«
åãã³ããä»ä¸ããã®ãç¡é£ã»ã»ã»ã«æããä»æ¥ãã®é ã
ã¨ã¯ããããããéçåä»ãè¨èªã«æ
£ãéãããããªã®ãããããªããã
å°ãå
ã»ã©ã¯åãã³ãã«ãã£ã¦ã¯ã©ã¹ãã£ã¹ããé¿ãããã¨ãã§ãããã
åãã³ããä»ä¸ãããªãã¸ã§ã¯ãã«å¯¾ãã¦Javaã®ã¡ã½ããå¼ã³åºããä¸åè¡ããªããã°Clojureã¯ãã£ã¹ããæ¿å
¥ããªãã
user=> (defn wants-a-string [#^String target] (println target)) #'user/wants-a-string user=> (wants-a-string :keyword) :keyword nil user=> (wants-a-string 11111) 11111 nil user=> (wants-a-string "Test") Test nil
ã¡ãªã¿ã«åãã³ããä»ä¸ããã«å®è¡ãã¦ãè¦åãçºçããªãã
user=> (defn wants-a-string [target] (println target)) #'user/wants-a-string
Clojureå´ã¯wants-a-stringãå¼æ°ãæååã¨ãã¦æ±ã£ã¦ããªããã¨ã解æã§ããï¼printlnã¯ã©ããªãªãã¸ã§ã¯ãã§ãåºåãããã¨ããï¼ã
ãã®ãããClojureã¯targetãæååã«ãã£ã¹ããããã¨ãããçµæåé¡ãçºçããªãã
å°ãJavaã®ã¡ã½ãããå¼ã³åºãã¨ä¾ãObjectåã®ã¡ã½ãããç¨ããå ´åã§ãè¦åã¯çºçããã
user=> (defn wants-a-string [target] (.toString target)) Reflection warning, NO_SOURCE_PATH:42:31 - reference to field toString can't beresolved. #'user/wants-a-string
ãã ããã®å ´ååãã³ããã¤ããã°ä½ãå¼æ°ã¨ãã¦æ¸¡ãããObjectåã¨ããæ¡ä»¶ã¯æºãããããã¨ã¨ãªãããã
è¦åã¯çºçããªãããå½ç¶ãªããClassCastExceptionãçºçããªãã
ã¨ãããã¨ã¯Objectåãå¼æ°ã¨ãã¦åãåããã¨ãæ³å®ããå ´åã¯ã¨ããããåãã³ããã¤ãã¦ããã»ã»ã»
ã¨ããã®ããããããããªãããããªç¶æ³ãããã®ãã©ããã¯ã¾ãå¥ã®è©±ã«ãªããã
user=> (defn wants-a-string [#^Object target] (.toString target)) #'user/wants-a-string user=> (wants-a-string "Test") "Test"
å é¨ã§Clojureãã©ããã£ã¦ã¯ã©ã¹å¤æã試ã¿ã¦ããããè¥å¹²å£éè¦ããç« ãªã®ã§ä¸ã é¢ç½ã話ã§ããã