【问题标题】:What does this function definition in clojure code example do?clojure 代码示例中的这个函数定义有什么作用?
【发布时间】:2012-07-27 19:48:21
【问题描述】:

我正在关注“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”以及函数-to-call 是作为参数传递给该函数的函数。 下一部分让我感到困惑:(fn [& args] .... 这里定义了一个匿名函数吗?'with-log' 函数是否返回一个新的函数定义?

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

所以通过调用 (with-log somefunc "my label") - 它只是返回一个新的匿名函数吗?还是调用匿名函数?

【问题讨论】:

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


    【解决方案1】:

    with-log 将产生一个函数,当调用该函数时,它将完全执行 function-to-call 所做的事情,除了在使用参数评估 function-to-call 之前将 log-statement 打印到 *out* 的副作用给匿名函数。

    这是Decorator Pattern 的一个示例 - 通过将现有函数包装在另一个函数中来扩展现有函数的行为,即with-log 使用(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 
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

        是的,你是对的。 (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=>
        

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

        Here你可以了解更多。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-03
          • 1970-01-01
          • 1970-01-01
          • 2020-04-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多