匿名函数消耗另一个匿名函数 - clojure koan

use*_*639 3 clojure

我正在研究clojure koans,函数中的一个问题需要进一步解释我"得到它"并且有一个aha时刻.我能够编写满足问题的函数.但我不完全理解为什么所有这些都有效.

Clojure> (= 25 ((fn [a b] (b a)) 5 (fn [n] (* n n))))
true
Run Code Online (Sandbox Code Playgroud)

问题1. 我不明白为什么会抛出错误:

Clojure> (= 25 ((fn [b a] (b a)) 5 (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
Run Code Online (Sandbox Code Playgroud)

因此,上述唯一的变化是切换b和a的顺序.在我的大脑中,我读到了"一个带有a和b"或"b和a"的函数,但它们如何被使用取决于随后的语句.为什么订单在这一点上很重要?

问题2.

Clojure> (= 25 ((fn [a] (5 a)) (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
Run Code Online (Sandbox Code Playgroud)

为什么当我将b的值替换为它所代表的int时,我会收到错误?

Qution 3.

((fn [a b] (b a)) 5 (fn [n] (* n n))))
Run Code Online (Sandbox Code Playgroud)

为什么这不会抛出错误(ba)b在这个例子中是5,这是一个符号.括号中的第一项预计是函数或特殊形式,除非它是一个列表?

Mat*_*ick 6

  1. 在第一个函数中查看你的表达式:

    (b a)
    
    Run Code Online (Sandbox Code Playgroud)

    既然b是第一个,b必须是一个功能.在你的第二个例子中,你试图传递5 b,但是5不是函数.使用描述性名称,您可以看到您尝试使用5作为函数:

    ((fn [argument function] (argument function)) ;; problem!!
     5 
     (fn [n] (* n n)))
    
    Run Code Online (Sandbox Code Playgroud)

    记住lisps的评估规则:给出这个s-expression:

    (f x y z)
    
    Run Code Online (Sandbox Code Playgroud)

    计算f,x,y和z,并将f作为函数应用于x,y和z.

  2. 看到答案1 - '5'不是一个功能.使用描述性名称,并轻松发现问题:

    ((fn [function] (5 function)) ;; problem!!
     (fn [n] (* n n)))
    
    Run Code Online (Sandbox Code Playgroud)

    改成:

       ((fn [a] (a 5))  ;; 'a' and '5' flipped
        (fn [n] (* n n)))
    
    Run Code Online (Sandbox Code Playgroud)

    让它运行.

  3. 这不是问题: a是5,b是一个功能(b a).使用描述性名称更有意义:

    ((fn [argument function] (function argument)) 
     5
     (fn [n] (* n n)))
    
    Run Code Online (Sandbox Code Playgroud)