【问题标题】:What is the "name?" argument in Clojure's fn?是什么名字?” Clojure 的 fn 中的论点?
【发布时间】:2019-10-28 10:28:41
【问题描述】:

我正在阅读 Russ Olsen 的《Getting Clojure》一书。在第 8 章“Def、Symbols 和 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]

除了函数名,好像没有什么区别。

为什么fn 会有一个name? 参数?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    你可以在创建多个arities时使用它:

    (fn second
          ([x] (second x 1))
          ([x y] (+ x y)))
    

    或者如果您需要进行递归调用:

    (fn second [x] (when (pos? x)
                      (println x)
                      (second (dec x))))
    

    【讨论】:

      【解决方案2】:

      主要有两种用法:

      • 递归函数(你现在知道名字了)
      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-01
        • 1970-01-01
        • 2017-09-07
        • 1970-01-01
        • 2011-10-06
        • 1970-01-01
        • 2012-05-30
        • 1970-01-01
        相关资源
        最近更新 更多