【问题标题】:Passing a symbol as a function in clojure在clojure中将符号作为函数传递
【发布时间】:2011-06-02 22:54:04
【问题描述】:

我正在学习 clojure,并且我编写了一个小函数,它给定目录路径名,根据文件的 mtime 降序返回文件的排序映射。这里是:

(defn get-sorted-mtimes [dir]      
  (loop [sm (sorted-map-by >)
         lst (for [f (.listFiles (File. dir))]
               (let [k (.lastModified f)
                     v (.getName f)]
                 [k v]))]
    (if (seq lst)
      (recur (assoc sm ((first lst) 0) ((first lst) 1))
        (rest lst))
      sm)))

我的问题是:有没有办法将比较器方法作为符号名称传递给函数,并相应地按 asc 或 desc 顺序排序?我的意思是:

(defn get-sorted-mtimes [dir <sym>]  
  (loop [sm (sorted-map-by <sym>)
       ...

另外,有没有更符合 clojuresque 的方式来完成这项任务?

好吧,为了记录,这是函数的最终形式,它完全符合我的需要:

(defn get-sorted-mtimes [dir comp]      
  (loop [sm (sorted-map-by (comparator comp))
         lst (for [f (.listFiles (File. dir))]
               (let [k (.lastModified f)
                     v (.getName f)]
                 [k v]))]
    (if (seq lst)
      (recur (assoc sm ((first lst) 0) ((first lst) 1))
        (rest lst))
      sm)))

如果不使用(比较器)函数,则会得到 java.lang.ClassCastException 异常。

【问题讨论】:

  • 我不完全确定 是什么,但如果它只是一个函数,它应该完全按照你的建议工作......
  • 我使用 作为要使用的符号的占位符

标签: clojure


【解决方案1】:

&gt; 与 Clojure 中的任何其他函数一样只是一个函数。所以没有什么可以阻止你将它作为参数传递。

事实上,我会说这种方式是很好的 Clojure 风格。 Clojure 本质上是一种函数式编程语言,因此在适当的情况下使用higher order functions 并没有错!

其他一些小建议:

  • 使用comparator 而不是&lt;sym&gt; 作为函数参数的名称。我认为这更具描述性,也更符合 Clojure 的正常命名约定。
  • 您还可以添加另一个函数参数来确定您要比较的内容,以便您可以传递像get-mtime 这样的函数(一个返回文件mtime 的简单函数)。
  • 我建议将文件序列作为函数的输入而不是目录。然后您的功能更通用,可以使用诸如 del 之类的东西。递归目录扫描方式完全相同
  • 我建议使用 (into sm lst) - 比你的大循环/if/recur 构造简单得多!

然后你可以做一些非常好的事情,比如(get-sorted-files (list-files-recursive dir) &gt; get-mtime) - 或者你能想到的任何类似的组合!

【讨论】:

  • 我知道我可以将符号 > 作为任何其他 clojure 函数传递,也就是说,如果符号被硬编码到我的函数体中。我想要做的是将 ">" 或 "string 作为函数参数传递,并相应地对函数进行排序。这将失败并出现以下错误:java.lang.ClassCastException:java.lang.String 无法强制转换为 java.util.Comparator。当我使用 (symbol sym) 进行转换时,出现此错误: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.util.Comparator
  • 我才明白你的意思。通过使用 (comarator ...) 而不是 (symbol ...) 它工作得很好。谢谢!
  • 为什么要将“>”作为字符串传递?我只是将函数作为 > 直接传递,例如如 (get-sorted-mtimes dir >) ...或者我错过了什么??
  • 好的,太好了!顺便说一句,我认为您甚至不需要 (comparator ...) 位。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 2015-01-02
  • 2015-08-18
相关资源
最近更新 更多