Confusing clojure syntax in storm analysis

Source: Internet
Author: User
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))))

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.