使用IFn扩展Clojure正则表达式以支持映射

时间:2018-11-26 12:19:54

标签: regex interface clojure clojurescript extends

我希望能够在正则表达式上调用curve_fit,就像这样:

map

如何扩展正则表达式以支持IFn接口?还是有其他方法可以做到?

4 个答案:

答案 0 :(得分:2)

ClojureScript:

(extend-type js/RegExp
  IFn
  (-invoke
    ([match s] (re-find match s))
    ([match replacement s]
      (clojure.string/replace s match replacement))))

现在,您可以将正则表达式作为函数来调用,甚至可以将它们传递给map

(#"abc+" "abcccc")
=> "abcccc"

(map #"abc+" ["abcccc" "abcccccccc"])
=> ("abcccc" "abcccccccc")

很不幸,IFn不是Clojure中的协议,因此您不能扩展它。真不幸。

答案 1 :(得分:2)

由于IFn不是核心Clojure中的协议,所以我认为这是不可能的。

我能得到的最接近的结果是创建一个实现IFn的包装器类型:

(defrecord R [^java.util.regex.Pattern regex]
  clojure.lang.IFn
  (invoke [this s]
    (re-find regex s))
  (invoke [this replacement s]
    (clojure.string/replace s regex replacement)))

(map (->R #"abc+") ["abcccc" "abcccccccc"])

=> ("abcccc" "abcccccccc")

答案 2 :(得分:1)

尝试执行此操作的麻烦在于,使用正则表达式无法直接清楚地知道要执行的操作-特别是当大多数生产代码看起来像(map #"ab+" entries)

正则表达式仅与模式 matching 有关,它们并不直接暗示您要从它们中进行什么转换,因此,您真的应该避免尝试将其转换为错误模式。

如果是一次,请使用

(map #(clojure.string/replace % #"ab+c*" "ab") ["ab" "ac" "abbcc"])

=> ("ab" "ac" "ab")

(尚不清楚您的示例应如何工作?结果中包含的元素更少-您正在过滤转换吗?如何获得“ abbb”元素?)< / p>

如果您经常使用它,我建议您仅在可与map一起使用的通用命名空间中创建一个辅助函数,而不要尝试扩展IFn接口。。由于创建函数

答案 3 :(得分:0)

正如CmdrDats所说,在匿名函数中使用re-find绝对是可行的方法:

(filter #(re-find #"ab+c*" %) ["abbb" "ac" "abbcc"]) 

    => ("abbb" "abbcc")

有时我会使用一个辅助函数来强调我只想要正确/错误的输出(而不是匹配项或一系列匹配项),并且由于我总是忘记re-xxx函数之间的区别:

(ns demo.core
  (:require [schema.core :as s]))

(s/defn contains-match?  :- s/Bool
  "Returns true if the regex matches any portion of the intput string."
  [search-str :- s/Str
   re :- s/Any]
  #?(:clj (assert (instance? java.util.regex.Pattern re)))
  (boolean (re-find re search-str)))