fn是一个宏, 用于定义一个简单的函数
defn 宏用来定义一个函数。它的参数包括一个函数名字,一个可选的注释字符串,参数列表,然后一个方法体。而函数的返回值则是方法体里面最后一个表达式的值。所有的函数都会返回一个值, 只是有的返回的值是nil。
- user=> (defn f1 [] "hello");定义无参函数
- #'user/f1
- user=> (f1)
- "hello"
就是对参数从右到左组合执行所有函数,可以转变为:
就是执行:
(f arg1 arg2 .. argn arga argb .. argz)
注意:偏函数的第一个参数是一个函数,后面至少有1个其他参数
partial函数称为“偏函数”或者“部分完整函数”,因为它是不完整的,定义也用def而不是defn。
宏-> 我们也称为 “thread” 宏, 它本质上是调用一系列的函数,前一个函数的返回值作为后一个函数的参数,返回最后一次函数调用的值. 比如下面两行代码的作用是一样的:
- user=>(first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))
- user=>"X"
- user=> (-> "a b c d" .toUpperCase (.replace "A" "X") (.split " ") first)
- user=>"X"
后面的函数迭代使用之前的函数结果作为最后一个参数,返回最后一次函数调用的值
分下下面两个语句:
fn?用于检查给定的参数是否为函数,是返回true,否则返回false,如:
symbol binding. make a=1 and b=2 , then compute a+b, and finally print the result。
在宏中使用,auto-gensym,在宏编译时产生唯一的symbol名字,防止命名冲突。
将参数x, y在各自指定的数据集上进行笛卡尔积混排后,按照指定函数进行运算,返回结果列表,类似java中的多重for循环。
将原始map中指定的key替换为指定的值,如果原始key不存在,则新增。
定义数据类型Employee, 其中有两个字段,名称分别为name和room。
(def emp (Employee. "John Smith" 304))
实例化一个Employee对象。
(:name emp)
获取emp对象中的name字段值。
字符串连接。
和defn的区别在于可以为参数指定默认值,实际调用的时候如果不传参数,会使用默认值进行计算,否则采用传入的参数
(f) -> 11
(f :b 100) -> 101
调用命名空间a下的函数b.
串行连续调用多个函数,第一个函数的返回值作为第二个函数的第一个参数,以此类推。
作用和doseq类似,区别是可以使用额外的条件表达式进行笛卡尔积的筛选,支持的算子有:let :when :while,例如:
(for [x [0 1 2 3 4 5] :let [y (* x 3)] :when (even? y)] y) => (0 6 12)
将y设置为x*3,并且过滤掉奇数。
(for [x (range 3) y (range 3) :when (not= x y)] [x y]) => ([0 1] [0 2] [1 0] [1 2] [2 0] [2 1])
(for [x (range 3) y (range 3) :while (not= x y)] [x y]) => ([1 0] [2 0] [2 1])
将list x和y进行笛卡尔乘积,可以看到筛选算子when和while的区别在于while在list x中的每个元素第一次遇到不符合条件的list y中的元素时,list y后面的元素便全部忽略,从list x中的下一个元素开始重新对list y进行笛卡尔乘积。
‘(a b c) 链表
[a b c] 数组
#{a b c} set
{:a 1, :b 2, :c 3} map
斜杠用于表示静态方法调用
创建一个Integer对象,后面的参数是构造函数中所需参数。(注意Integer后面的点)
向右的单箭头称为thread-first,按照从左到右的顺序依次将第一个form的计算结果作为第一个参数传入紧接下来右边的form. 将各个处理节点作为数据处理管道串联起来。
例如:
(defmacro mymacro [number & body]
`(let [number# ~number]
(cond
(> number# 0) "positive"
(= number# 0) "zero"
:else ~@body)))
`称为syntax quote,表示宏主体里面的内容都会按照字面被展开,除了带波浪线的元素外,波浪线标注的元素number在展开时以其对应的值来代替,~@表示body是一个序列。number#是用来产生一个独特的符号名而不会和其他符号名冲突。
(def simple_map {:a 1, :b 2, :c 3})
(:a simple_map)
(defn ^String substr [^String s ^Integer begin ^Integer end] (.substring s begin end))
使用^提示clojure编译器,方法的参数和返回值的类型。
定义一个匿名函数,%表示函数的第一个参数(第2, 3个函数用%2, %3表示),该匿名函数获取参数中键值为key对应的value。
comp将多个函数按照right-to-left的顺序应用于指定数据集上,上述REPL运行结果为"6"。
连接集合 (1 2 3 4 5 6 7 8 9 10)
("x" "x" "x" "x" "x")
迭代计算 (5 6 7 8 9 10 11 12 13 14 15 ... n
如果不用take配合,最终会导致OOM。
合并多个map,对于重复重现的Key,后面出现的会覆盖前面同样的Key。
返回一个唯一集合 #{
1
2
3
4
5
}
group-by根据算子f对集合coll进行排序,返回一个map,其中key为f计算的结果,key对应的value为coll中的对应元素,map按照key进行排序,
(group-by count ["a" "as" "asd" "aa" "asdf" "qwer"]) -> {1 ["a"], 2 ["as" "aa"], 3 ["asd"], 4 ["asdf" "qwer"]}
返回map对应value的序列 ("foo" "bar")