将符号作为clojure中的函数传递

时间:2011-06-02 12:34:31

标签: clojure

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

(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异常。

1 个答案:

答案 0 :(得分:4)

>就像Clojure中的任何其他功能一样。所以没有什么可以阻止你把它作为一个论点。

事实上,我认为这样做是很好的Clojure风格。 Clojure本质上是一种函数式编程语言,所以在适当的地方使用higher order functions并没有错!

其他一些小建议:

  • 使用comparator代替<sym>作为函数参数的名称。我认为这更具描述性,并且与Clojure的常规命名约定更加一致。
  • 您还可以添加另一个函数参数来确定您要比较的内容,以便您可以传递像get-mtime这样的函数(一个返回文件mtime的简单函数)。
  • 我建议将一系列文件作为函数的输入而不是目录。然后你的功能更通用,可以用例如像
  • 以完全相同的方式进行递归目录扫描
  • 我建议使用(into sm lst) - 比你的大循环/ if / recur构造简单得多!

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