一个论点,很多功能

cla*_*laj 9 clojure

我有一个来自我正在使用tail-seq读取的文件的传入惰性流行(对于contrib - 现在!)我想要一个接一个地处理这些行,其中有几个"侦听器函数"根据re-seq采取行动-hits(或其他东西)在行中.

我尝试了以下方法:

(defn info-listener [logstr]
  (if (re-seq #"INFO" logstr) (println "Got an INFO-statement")))

(defn debug-listener [logstr]
  (if (re-seq #"DEBUG" logstr) (println "Got a DEBUG-statement")))

(doseq [line (tail-seq "/var/log/any/java.log")] 
   (do (info-listener logstr)
       (debug-listener logstr)))
Run Code Online (Sandbox Code Playgroud)

它按预期工作.但是,代码中有很多代码重复和其他错误,更新代码很无聊.

一个重要的步骤似乎是将许多函数应用于一个参数,即

(listen-line line '(info-listener debug-listener))
Run Code Online (Sandbox Code Playgroud)

并使用它而不是枯燥和容易出错的声明.

我尝试了以下看似聪明的方法:

(defn listen-line [logstr listener-collection]
  (map #(% logstr) listener-collection))
Run Code Online (Sandbox Code Playgroud)

但这只会呈现

(nil) (nil)
Run Code Online (Sandbox Code Playgroud)

懒惰或一流的功能肯定会咬我,但我在哪里提出申请?

我也对这个问题采取截然不同的方法,但这似乎是一个非常理智的方式.宏/多方法现在似乎有点矫枉过正.

Ale*_*ard 10

使用核心函数可以使用相同的参数从一组函数中创建单个函数juxt:

=>(def juxted-fn (juxt identity str (partial / 100)))
=>(juxted-fn 50)
[50 "50" 2]
Run Code Online (Sandbox Code Playgroud)

结合juxt起来partial非常有用:

(defn listener [re message logstr] 
  (if (re-seq re logstr) (println message)))
Run Code Online (Sandbox Code Playgroud)
(def juxted-listener 
  (apply juxt (map (fn [[re message]] (partial listner re message)) 
     [[#"INFO","Got INFO"],
      [#"DEBUG", "Got DEBUG"]]))
(doseq [logstr ["INFO statement", "OTHER statement", "DEBUG statement"]] 
  (juxted-listener logstr))


Mic*_*zyk 9

你需要改变

(listen-line line '(info-listener debug-listener))
Run Code Online (Sandbox Code Playgroud)

(listen-line line [info-listener debug-listener])
Run Code Online (Sandbox Code Playgroud)

在第一个版本中,由于引用,listen-line最终使用符号info-listenerdebug-listener它们自己作为函数.符号实现clojure.lang.IFn(Clojure函数调用背后的接口)就像关键字一样,即它们看起来像一个类似map的参数(实际上是a clojure.lang.ILookup),nil如果应用于不是map的东西则返回.

另请注意,您需要包装listen-linein 的主体dorun以确保它实际执行(因为map返回一个惰性序列).更好的是,切换到doseq:

(defn listen-line [logstr listener-collection]
  (doseq [listener listener-collection]
    (listener logstr)))
Run Code Online (Sandbox Code Playgroud)

  • 更好的是,切换到`juxt`:`((应用juxt listener-collection)logstr)` (3认同)