Document directory
- Defnk
- ->, (-> X form & more)
- ->>,(-> X form & more)
- Comp, (Comp F1 F2 F3 & FS)
- If-Let, when-Let
- Into, (into to from)
- Merge, (merge & maps)
- Merge-with, (merge-with F & maps)
- Mapcat, (mapcat F & colls)
- Doall, dorun
- Doseq
- Gen-class
- Memfn, (memfn name & ARGs)
Http://qiujj.com/static/clojure-handbook.html
Defnk
Different from defn, you can use K and V in the parameter, and you can use K in the function body to obtain the value.
In fact, its implementation is to add a hashmap to store these K, V
user> (use 'clojure.contrib.def)niluser> (defnk f [:b 43] (inc b))#'user/fuser> (f)44user> (f :b 100)101user=> (defnk with-positional [foo :b 43] (+ foo (inc b)))#'user/with-positionaluser=> (with-positional 5 :b 1)7
->, (-> X form & more)
Http://clojuredocs.org/clojure_core/clojure.core/-%3E
Linear nesting to make it more readable. Inserts X as the second item in the first form
The following example shows that the first parameter (X) is used as the initial input, the second parameter (FN) is called, and the return value is used to call subsequent functions.
Similar to..., but... can only be used for Java calls.
;; Arguably a bit cumbersome to read:user=> (first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))"X";; Perhaps easier to read:user=> (-> "a b c d" .toUpperCase (.replace "A" "X") (.split " ") first)"X"
->>,(-> X form & more)
Http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E
Inserts X as the last item in the first form
The difference between "->" and "->" is that X is inserted at a different position,
-> Is inserted in the second item, that is, immediately following the function name,
And-> is inserted in the last item
;; An example of using the "thread-last" macro to get;; the sum of the first 10 even squares.user=> (->> (range) (map #(* % %)) (filter even?) (take 10) (reduce +))1140;; This expands to:user=> (reduce + (take 10 (filter even? (map #(* % %) (range)))))1140
Comp, (Comp F1 F2 F3 & FS)
Return a function with a set of functions as the parameter, for example, my-FN.
The effect of using my-FN is,
The number of parameters of my-FN is equal to the number of parameters required by FS, because the actual method is to call fs with the parameter of my-FN, and then call F3 with the return value of FS... Continue
Therefore, all functions except FS must contain only one parameter. Therefore, partial is often used to reduce the number of parameters.
user=> (def my-fn (comp (partial * 10) - *))user=> (my-fn 5 3) ; 10*(-(5*3))-150
If-Let, when-Let
Add if to let to judge. In the following example, if Nums is not false or nil, accumulate; otherwise, "No even numbers found" is printed in the list ."
It is applicable to different processing of different let results.
user=> (defn sum-even-numbers [nums] (if-let [nums (seq (filter even? nums))] (reduce + nums) "No even numbers found."))user=> (sum-even-numbers [1 3 5 7 9])"No even numbers found."user=> (sum-even-numbers [1 3 5 7 9 10 12])22
When-Let: Same theory. When the LET value is not false or nil, the corresponding logic is executed; otherwise, Nil is returned.
(defn drop-one [coll] (when-let [s (seq coll)] (rest s)))user=> (drop-one [1 2 3])(2 3)user=> (drop-one [])nil
Collection operations
Into, (into to from)
Join from to. We can see that the order of list, vector, set, and addition is different at the bottom, and there are some doubts at the beginning.
In fact, into only reads items from the from and appends them to the to. The final order is different because the data structure processes append differently.
; Adds a list to beginning of another. Note that elements of list are added in reverse since each is processed sequentially.(into '(1 2 3) '(4 5 6))=> (6 5 4 1 2 3)
(into [5 6 7 8] '(1 2 3 4))=> [5 6 7 8 1 2 3 4] (into #{5 6 7 8} [1 2 3 4])=> #{1 2 3 4 5 6 7 8}
Merge, (merge & maps)
Put multiple map merge together. If the same key exists, latter takes precedence.
user=> (merge {:a 1 :b 2 :c 3} {:b 9 :d 4}){:d 4, :a 1, :b 9, :c 3}
Merge-with, (merge-with F & maps)
Normal merge only replaces Val, while merge-with can use F for merge. For example, the following example uses
;; merge two maps using the addition functionuser=> (merge-with + {:a 1 :b 2} {:a 9 :b 98 :c 0}) {:c 0, :a 10, :b 100}
Mapcat, (mapcat F & colls)
Unlike normal map, the Concat operation is performed on the result of map execution.
Equal to (Concat (map f & colls ))
user=> (mapcat reverse [[3 2 1 0] [6 5 4] [9 8 7]])(0 1 2 3 4 5 6 7 8 9)
Doall, dorun
Both doall and dorun are used for force lazy-seq. The difference is that
Doall will hold the head and return the whole seq. Therefore, seq is stored in memory during the process. Pay attention to outofmemory.
Dorun does not hold Head, traverses run, and finally returns Nil
(doall (map println [1 2 3]))123(nil nil nil)(dorun (map println [1 2 3]))123nil
Doseq
In fact, doseq supports dorun's for (list comprehension), which is basically consistent with the for syntax.
For returns lazy-seq, while doseq = dorun (...)
(doseq [x (range 7) y (range x) :while (odd? x)] (print [x y]))(for [x (range 7) y (range x) :while (odd? x)] [x y])
user=> (doseq [x [1 2 3] y [1 2 3]] (prn (* x y)))123246369nil
Java call
First look at the most common corresponding table
Gen-class
Http://clojure.org/compilation
To solve the compile ahead-of-time (AOT) problem, clojure, as a dynamic language, will compile and run on JVM during runtime, but in some cases, compile and generate class
For example, there is no source code for deliver, Or you want your clojure code to be called by Java...
Clojure compiles all code you load on-the-fly into JVM bytecode, but sometimes it is advantageous to compile ahead-of-time (AOT). Some reasons to use AOT compilation are:
- To deliver your application without source
- To speed up application startup
- To generate named classes for use by Java
- To create an application that does not need runtime bytecode generation and custom classloaders
The solution to this problem is to use gen-class, which is often used in combination with NS. This will automatically generate a class for the namespace (save: name)
(ns clojure.examples.hello (:gen-class))
In the example in storm, defaultscheduler implements the ischeduler interface, and the interface implementation function has a '-' prefix, such as '-schedule'
(ns backtype.storm.scheduler.DefaultScheduler (:gen-class :implements [backtype.storm.scheduler.IScheduler]))(defn -prepare [this conf] )(defn -schedule [this ^Topologies topologies ^Cluster cluster] (default-schedule topologies cluster))
Memfn, (memfn name & ARGs)
Java, method call, file. isdirectory ()
But for clojure, the function is first class, so the call method is isdirectory (file)
The problem is that when I use Java class functions in clojure, I also want to use the first class method, so memfn is needed for conversion.
user=> (def *files* (file-seq (java.io.File. "/tmp/")))user=> (count (filter (memfn isDirectory) *files*))68user=> (count (filter #(.isDirectory %) *files*))68
It can be seen that * files *. isdirectory () is called, but through memfn, it seems to be using isdirectory (* files *)
Let's take a look at the implementation of this macro, that is, converting memfn (name, argS) to target. Name (ARGs)
(defmacro memfn "Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn." {:added "1.0"} [name & args] `(fn [target# ~@args] (. target# (~name ~@args))))