clojure代码示例中的这个函数定义是做什么的?

时间:2012-07-27 19:48:21

标签: clojure functional-programming higher-order-functions

我跟随'Clojure in Action'并且我对此感到困惑:

(defn with-log [function-to-call log-statement ]
      (fn [& args]
          (println log-statement)
          (apply  function-to-call args)))

这是令我困惑的代码段。这是我到目前为止所能解读的内容:

(defn with-log [function-to-call log-statement] ..)定义一个名为“with-log”的函数,该函数接受参数'function-to-call'和'log-statement'和function -to-call是一个作为参数传递给该函数的函数。 下一节让我感到困惑:(fn [& args] ....是一个在这里定义的匿名函数吗?'with-log'函数是否返回一个新的函数定义?

(fn [& args]
          (println log-statement)
          (apply  function-to-call args))

所以通过调用(with-log somefunc“my label”) - 它是否只是重新启动一个新的匿名函数?还是调用匿名函数?

3 个答案:

答案 0 :(得分:6)

with-log会生成一个函数,在调用时,它将完全执行function-to-call所做的操作,但副作用是log-statement将在*out*之前打印到function-to-call使用给匿名函数的参数来评估with-log

这是Decorator Pattern的示例 - 通过将现有函数的行为包装在另一个函数(即(fn ...)使用with-log表单创建的匿名函数)中来扩展现有函数的行为。

为了使装饰器函数function-to-call与任何可以想象的(fn [& args] ...)一起使用,指定了匿名函数的参数列表,以便可以使用function-to-call使用多个参数调用它。当匿名函数调用apply时,它使用函数with-log“展开”参数列表。

使用((with-log some-fn "Calling some-fn") arg1 arg2) 的方式可能是:

(defn my-fn [a b]
  (+ a b))
(def my-fn-with-logging (with-log my-fn "Calling my-fn"))

(my-fn 1 2) ; evaluates to 3
(my-fn-with-logging 1 2) ; prints "Calling my-fn" and evaluates to 3 

{{1}}

答案 1 :(得分:1)

它返回匿名函数,并且没有被调用。

例如,这将调用具有给定参数的匿名函数:

((with-log some-fn "log statement") arg1 arg2)

这是有效的,因为返回的函数是列表中的第一项,这意味着它就像任何其他函数一样被调用。

答案 2 :(得分:0)

是的,你是对的。 (fn ..)是一个创建匿名函数的表单。给定函数f和一些值s的这段代码将返回一个函数,该函数在被调用时将打印s然后调用f

user=> (defn with-log [function-to-call log-statement ]
      (fn [& args]
          (println log-statement)
          (apply  function-to-call args)))
#'user/with-log
user=> (with-log + "String")
#<user$with_log$fn__1 user$with_log$fn__1@147264b1>
user=> ((with-log + "String") 1 2 3)
String
6
user=>

请注意以#<user$...开头的行。这是刚刚创建的匿名函数的内部标识符,即对with-log的简单调用返回一个函数。然后我们应用相同的函数(它的行为是相同的;事实上它将是不同的对象,因为每次调用with-log都会为许多参数创建相同函数的新“实例”。打印"String"字符串,然后REPL向我们显示(+ 1 2 3)的结果。

Here您可以了解更多信息。