代码之家  ›  专栏  ›  技术社区  ›  hawkeye

在Clojure中传递方法名进行求值的惯用方法?

  •  5
  • hawkeye  · 技术社区  · 14 年前

    我正在传递一个函数的名称,以便在另一个方法中使用。

    (defn mapper [m function]
      (cond
       (= '() m) '()
       true (cons (function (first m))
                (mapper (rest m) function))))
    
    (println (mapper '((blue red)(green red)(white red)) #'first))
    

    3 回复  |  直到 10 年前
        1
  •  9
  •   Brian Carper    14 年前
    • 更喜欢向量而不是列表。你不必在大多数时候引用一个向量,而且它在很多方面都有更好的性能,比如随机访问。在Clojure中使用列表的情况比在其他lisp中要少得多。
    • 喜欢关键字而不是引用符号。关键字突出显示为“常量字符串”或枚举值。Clojure中的关键字可以属于名称空间,因此它们具有符号的所有优点。再说一次,没有必要引用关键字,这很好。在Clojure中很少使用引号符号,除非您正在编写宏。
    • #'first first 是称为“first”的var值,即fn。在这种情况下 (#'first foo) (first foo) 给出同样的答案,但是 #'第一个 每次调用时都会进行额外的解引用。所以不要这样做,除非你希望这种取消引用的情况一再发生。通常不需要使用 #'
    • 内置的 map 他很懒,而你的不是。内置的 地图 利用分块seq获得更好的性能,而你的没有。惯用代码不必是懒惰的或使用分块seq,但请记住,内置代码有一些这样的魔力。所以好好利用。
    • (= '() x) ,空seq的惯用测试是 (seq x) nil 如果 x (= '() nil) 是假的。
    • 如果你真的需要使用空列表(你应该很少需要这样做),你不必引用它。只是使用 ()
    • 内置 地图
    • 没有必要使用 cond if 相反。如果你的一根树枝 退货 when . 很好用 什么时候 如果 在适当的时候,因为它们会立即向读者传达你的意图,而 可以做任何事,迫使读者阅读更多。

    user> (mapper first [[:blue :red] [:green :red] [:white :red]])
    (:blue :green :white)
    
        2
  •  4
  •   Rafał Dowgird    14 年前

    我相信你说得很地道。Clojure自己的 map 使用:

    (defn mapper [coll f]
     (when-let [s (seq coll)]
        (cons (f (first s)) (mapper (rest s) f))))
    

    名称

    coll f

        3
  •  4
  •   user445161 user445161    14 年前

    你的版本在我看来不错。在clojure代码库中,通常会看到集合的名称是'coll'。我也看过“xs”,这是Haskell风格,我想。你也可以参考 Clojure library coding standards

    1. Use:else for'cond'作为转义条件,而不是常见的Lisp样式'T'。

    记住这两个,如果我重写你的代码:

    user> (defn mapper [coll f]
            (cond
              (not (seq coll)) nil
              :else (conj (mapper (next coll) f)
                          (f (first coll)))))
    #'user/mapper
    user> (mapper '(1 2 3) #(* % %))
    (1 4 9)
    user> (mapper [1 2 3] #(* % %))
    (1 4 9)