我正在阅读拉斯·奥尔森(Russ Olsen)的书《 Getting Clojure》。在第8章“ Def,Symbol和Vars”中,有以下函数定义:
(def second (fn second [x] (first (next x))))
^^^^^^
我的问题是关于带下划线的second
,其次。
起初,我认为这种语法是错误的,因为匿名函数不需要名称。但是as it turnes out,这种语法是正确的。
Usage: (fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)
我尝试比较以下两个函数调用。
user> (fn second [x] (first (rest x)))
#function[user/eval5642/second--5643]
user> (fn [x] (first (rest x)))
#function[user/eval5646/fn-5647]
除了函数的名称外,似乎没有什么区别。
为什么name?
会有一个fn
自变量?
答案 0 :(得分:5)
您可以在创建多个Arity时使用它:
(fn second
([x] (second x 1))
([x y] (+ x y)))
或者如果您需要进行递归调用:
(fn second [x] (when (pos? x)
(println x)
(second (dec x))))
答案 1 :(得分:4)
主要有两种用法:
user=> ((fn foo [x] (when (pos? x) (println x) (foo (dec x)))) 3)
3
2
1
nil
user=> (map (fn bar [x] (inc x)) ["a"])
Error printing return value (ClassCastException) at clojure.lang.Numbers/inc (Numbers.java:137).
java.lang.String cannot be cast to java.lang.Number
user=> (pst)
ClassCastException java.lang.String cannot be cast to java.lang.Number
clojure.lang.Numbers.inc (Numbers.java:137)
user/eval8020/bar--8021 (NO_SOURCE_FILE:1)
clojure.core/map/fn--5866 (core.clj:2753)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
clojure.lang.RT.seq (RT.java:535)
clojure.core/seq--5402 (core.clj:137)
clojure.core/seq--5402 (core.clj:137)
puget.printer.PrettyPrinter (printer.clj:529)
puget.printer/iseq-handler--1663 (printer.clj:314)
puget.printer/iseq-handler--1663 (printer.clj:312)
puget.printer/format-doc* (printer.clj:223)
(请注意user/eval8020/bar--8021
)