Skip to main content
 Web开发网 » 操作系统 » linux系统

clojure匿名函数

2021年10月14日6060百度已收录

匿名函数用 fn 创建匿名函数。

● 这是一个很简短且不言自明的函数,如果给它取名字的话,不会令可读性增强,反而使得代码更难以阅读。

● 这是一个仅在别的函数内部使用的函数,需要的是局部名称,而非顶级绑定。

● 这个函数是在别的函数中被创建的,其目的是为了隐藏某些数据。

用作过滤器的函数总是简短且不言自明的。

src/examples/exploring.clj

(defn indexable-word? [word]

(> (count word) 2))

(require '[clojure.string :as str])

(filter indexable-word? (str/split "A fine day it is" #"\W+"))

-> ("fine" "day")

匿名函数能让你仅用一行代码就做到相同的事情。

最简单的匿名函数形式fn。

(fn [params*] body)

通过这种形式,能在调用filter时直接插入indexable-word?的实现。

(filter (fn [w] (> (count w) 2)) (str/split "A fine day" #"\W+"))

-> ("fine" "day")

还有一种采用隐式参数名称,也更加简短的匿名函数语法。其参数被命名为%1、%2,以此类推。对于第一个参数,你也可以使用%表示。

#(body)

可以使用这种更简短的匿名形式来重新调用filter。

(filter #(> (count %) 2) (str/split "A fine day it is" #"\W+"))

-> ("fine" "day")

使用匿名函数的第二个动机是,确定想要一个具名函数,但该函数仅在其他函数的作用域内使用。

src/examples/exploring.clj

(defn indexable-words [text]

(let [indexable-word? (fn [w] (> (count w) 2))]

(filter indexable-word? (str/split text #"\W+"))))

let将那个匿名函数与名称indexable-word?绑定在了一起,但这次它被限定在了indexable-words的词法作用域内。

(indexable-words "a fine day it is")

-> ("fine" "day")

采用这种let和匿名函数的组合,相当于对代码的读者说:“函数indexable-word?有足够的理由拥有一个名称,但仅限于在indexable-words中。”

使用匿名函数的第三个原因是,需要在运行期动态创建一个函数。

src/examples/exploring.clj

(defn make-greeter [greeting-prefix]

(fn [username] (str greeting-prefix ", " username)))

为一个通过 fn 得到的函数命名是没有意义的,因为每次调用make-greeter都会创建一个不同的函数。

可以使用 def 对 make-greeter创建的函数进行命名。

(def hello-greeting (make-greeter "Hello"))

-> #'user/hello-greeting

(def aloha-greeting (make-greeter "Aloha"))

-> #'user/aloha-greeting

可以像调用其它函数那样调用这些函数了。

(hello-greeting "world")

-> "Hello, world"

(aloha-greeting "world")

-> "Aloha, world"

没有必要为每个问候函数都命名。可以简单地创建一个问候函数,并将它放置到列表形式的第一个(函数)槽(slot)中。

((make-greeter "Howdy") "pardner")

-> "Howdy, pardner"

不同的问候函数会记住创建它们时的那个greeting-prefix值。用更为正式的说法,这些问候函数对greeting-prefix的值构成了闭包(closures)。

何时使用匿名函数匿名函数只是一种选择,而非必须。只有令代码更具可读性时,才应该使用这样的匿名形式。

评论列表暂无评论
发表评论
微信