This article from the NetEase cloud community
Lino
"Clojure is elegant and pragmatic; It helps me focus more on solving business problems. "
Unlike static languages such as Java, Clojure is a dynamic language, and dynamic typing means that these types are deduced dynamically by Clojure when the code is run, without any restrictions on compilation.
User=> (Defn F1 [a B] (+ "1" 2)) # ' USER/F1
User=> (F1 1 2) ClassCastException Java.lang.String cannot is cast to Java.lang.Number Clojure.lang.Numbers.add (number s.java:128)
Comparing the two ends of the code above, even if the function F1 contains an expression of the wrong type (+ "1" 2) can also be defined. However, once run (we randomly gave two unused parameters), function + tries to cast "1" and 2 to the number class in Java, when the type error in the code is thrown in classcastexception because the string "1" cannot be projected into the number class.
Note: Casting is not the same as conversion (convert), and casting is typically projecting a member of a subclass onto its superclass, whereas "1" + 2 = 3 in JavaScript is implicitly converted. The native function of Clojure does not use an implicit conversion.
So we don't usually need a given data type when writing code, but that doesn't mean the type is unimportant.
To better understand the type of clojure, a function is first used: type
User=> (Doc type)-------------------------clojure.core/type ([x]) Returns the:type metadata of X, or its Class if none Nil
We can use this function to get the type item in the metadata in the definition, and if it does not, return its class name.
Basic data types
Let's start by looking at some of the default types that are derived from common values:
Numerical
User=> (Type 1) java.lang.Long
Clojure integers Use the long base type in Java by default,
User=> (type MATH/PI) java.lang.Double
Decimals use the double type in Java.
If we want to use some other basic types of integers or floating-point numbers in Java, we can use the
User=> (Type (int 1)) java.lang.integeruser=> (type (float 3.14)) java.lang.Float
This type of cast (coerce) function is generated.
Interested students can try (type 1111111111111111111111111111111111111111) and (Type (/1 2)) what type.
String
User=> (Type \a) java.lang.characteruser=> (type "Hello") java.lang.String
Characters and strings are also from Java.
Keywords
As you can see, numbers, strings use Java types, and Clojure has some unique built-in base types, such as keywords,
User=> (Type:hello) Clojure.lang.Keyword
Similar to: A,:book,:code such keywords. The keyword equality test is very fast, so the common use scenario for keywords is the key in the map type (which is described in more detail later).
In the following benchmark, we compare the call time for the value of the key corresponding to the two maps, and the key using the keyword is 50% faster than the other map using the string key.
insight.main=> (Def t {:hello 1}): hella# ' insight.main/tinsight.main=> ( quick-bench (Get t :hello)) warning: final gc required 76.32000953339649 % of runtimeevaluation count : 55186818 in 6 samples of 9197803 calls. execution time mean : 10.005364 ns execution time std-deviation : 1.900011 ns execution time lower quantile : 8.087005 ns ( 2.5%) execution time upper quantile : 12.200609 ns (97.5%) Overhead used : 2.154486 nsnilinsight.main=> (def t1 {"Hello" 1}) # ' insight.main/t1insight.main=> (quick-bench (get t1 "Hello")) warning: final GC required 71.39921475186507 % of runtimeEvaluation count : 39262944 in 6 samples of 6543824 calls. Execution time mean : 15.356626 ns Execution time std-deviation : 0.589740 ns execution time lower quantile : 14.530609 ns ( 2.5%) execution time upper quantile : 16.016271 ns (97.5%) Overhead used : 2.154486 nsfound 1 outliers in 6 samples (16.6667 %) low-severe 1 (16.6667 %) variance from outliers : 13.8889 % Variance is moderately inflated by outliersnilinsight.main=>
Collection (Collections)
To understand Clojure code, only the preceding types are not enough, but also need some basic data structure, such as Vector,list,map,set and so on, because Clojure code is data.
List
List is a kind of data structure common in functional language, we can have two basic methods to make up
User=> (Type ' (1 2 3)) clojure.lang.persistentlistuser=> (Type (List 1 2 3)) Clojure.lang.PersistentList
In fact, the list's display is not required ' (quote) or list
User=> (Map Inc ' (1 2 3)) (2 3 4)
So why not write this when you build the list? In fact, the reason is very simple,
List is an important part of the Clojure code!
Looking back at the syntax of the Lisp language such as Clojure, the code in list form such as (Type 1), (+ 1 2) is actually shaped like
(Operator Operand1 operand2 ... operandn)
In this code, the first item of operator is treated as an executable function, and the next N-item operands is the operator parameter. Simply put, the expression is written as a list, and by default it is evaluated as an expression of the function application (evaluate), and ', that is, the quote function, can prevent evaluation.
Evaluation:
User=> (List 1 (+ 1 2) 3) (1 3 3)
No evaluation:
User=> ' (1 (+ 1 2) 3) (1 (+ 1 2) 3)
Clojure languages have the same image (Homoiconicity), which means that the code is generally organized in the form of data, which makes the manipulation code as easy as manipulating the data and facilitates metaprogramming (macros can be written in Clojure).
Returning to the list type, list in Clojure is called Persistentlist, which is a "persistent list", which is a type of immutable data. Clojure's persistent data structure facilitates the creation of "modify" operations (data immutable, "modification", which is essentially new data created) based on existing structures and can be shared as much as possible (structure sharing).
The structure sharing of a persistent list can be explained in the following example (from a wiki):
(Def XS ' (0 1 2)) (Def Ys ' (3 4 5))
Merge these two lists into a junction (CONCAT)
(Def ZS (concat xs Ys))
You can see that Xs and Ys have survived, only XS has been copied in memory, and Ys is shared because the blue part of the figure is not exactly the same as XS
Vector
Vector is a data structure in clojure that is generally understood to be similar to ArrayList in Java.
user=> (Type [0 1 2]) Clojure.lang.PersistentVector
Vectors are also persistent data types.
In fact, vectors are arrays stored in a tree structure with a maximum of 32 sub-nodes per layer, so its random access is O (log32n) (i.e. O (Logn)). Interested friends can see understanding Clojure's Persistent Vectors, Pt. 1 for a very detailed introduction to how to add, subtract elements.
Similarly, we can also use
user=> (vector 1 2 3) [1 2 3]
To form a vector, or to use
User=> (VEC ' (1 2 3)) [1 2 3]
Converts a list or other structure into a vector.
We can also think of vector as a similar to array, add, update, query all as long as O (1) structure.
Vector is also a common use for organizing code, as in function definitions
(Defn plus [a b] (+ a B))
The function parameter between the function name and the function body is given in the form of a vector. and the rest.
(Defn F1 [a b] (let [sum (+ a B) diff (-a b)] (* sum diff)))
We need to give a vector that has even pairs of members and satisfies some special conditions.
Set
In Clojure, set is also a built-in data structure, with special writing forms
User=> (Type #{1 2 3}) Clojure.lang.PersistentHashSet
The members of set are unique, and we can use it as a function to determine whether a value is a member of a set.
User=> (def S1 #{1 3 5 7}) # ' user/s1user=> (S1 3) 3user=> (S1 4) Nil
When this member is present in the collection, it returns itself, or nil (equivalent to null) is returned.
Map
Map is a very high frequency data structure in Clojure, and for simple maps, we can write even several members directly in {'}, neither key nor value use the same type.
User=> (Type {: Name "Doge" "Age" 2}) Clojure.lang.PersistentArrayMap
The default map type is Arraymap, which is similar in structure to vectors, where entries are arranged in the order in which they are created, and if you want to create HASHMAP, we can use
User=> (hash-map:name "x": Age "Ten") {: Age ",": Name "x"}user=> (Type (hash-map:name "x": Age ")") Clojure.lang. Persistenthashmap
Maps can also be executed as functions,
User=> (def M1 {: Name "X": "Age"}) # ' user/m1user=> (m1:name) "X" User=> (m1:title) niluser=> (m1:title "Defa Ult value ")" Default value "
Will look for the first parameter in the map as the value of key, if not, return nil by default, if there is a second argument, it will be returned instead of nil.
Clojure provides a number of convenient functions for map operation, and we can use get to get the value corresponding to a key.
User=> (Def M1 {: Age 10:name {: FirstName "John": Surname "Smith"}}) # ' user/m1user=> (Get M1:name) {: FirstName "John" ,: Surname "Smith"}
And when we need to query deeper value, we can use get-in to match the vector of the keys given in order.
User=> (get-in M1 [: Name:surname]) "Smith"
When we want to insert or overwrite the value of a key, we can use the Assoc
User=> (Assoc m1:height) {: Age,: Name {: FirstName "John",: Surname "Smith"},: Height 150}
If you need to update a value, you can use the update
User=> (Update m1:age (fn [x] (+ x 1)) {: Age one,: name {: FirstName "John",: Surname "Smith"}}
The difference between update and Assoc is that update can use the original value as a parameter to generate a new value, but he is also equivalent to using a get and then using Assoc, and using the following equation to express
(update M k f) = (Assoc m k (f (get M k)))
When used, the use of the most fitting code logic is more conducive to the readability and maintainability of the code. The subsequent notation, if it is equal to the left M and K, appears two times, potentially increasing the risk of modification. But the latter wording sometimes seems more flexible.
Similar to get, Clojure also provides assoc-in and update-in, with the use of a common macro----to make map operations very simple and intuitive to write.
user=> {: name {: FullName "Xiao Wang"}: From {: Country ' China ': City ' Beijing '}} #_ = = (assoc:age) #_ = = (Assoc-in [: from:city] "shanghai") #_ = (update-in [: Name:fullname] (fn [Full-name] (clojure.string/sp Lit Full-name # ")) (#_) {: name {: FullName [" Xiao "" Wang "]},: from {: Country ' China ',: City ' Shanghai '},: Age 3 0}
Summarize
With these basic data types in mind, Clojure's code will be very easy to get started, and it's welcome to try Clojure,clojure's simplicity and intuition to impress your friends, so you can focus on solving real problems. The installation of the method can refer to the previous I wrote this article,
Answer
User=> (Type 111111111111111111111111111111111111111111111111111) clojure.lang.bigintuser=> (Type (/1 2)) Clojure.lang.Ratio
NetEase Cloud New User package: Www.163yun.com/gift
This article from the NetEase cloud community, by the author Lino authorized release.
Related articles:
"Recommended" a Code specification for ECMAScript2015 (Part One)