Clojure:#(hash)vs re-pattern

时间:2017-11-05 20:01:27

标签: clojure

我正在学习Clojure,我发现创建正则表达式有两种方法:

  1. (re-pattern "12(ab)*34")
  2. #"12(ab)*34"
  3. 我做了一个快速的基准测试,看起来(1)比使用boot repl时快了(2)(在循环中需要~7秒而不是~10秒)。

    请问为什么会这样?我期待#""语法做一些聪明的编译时优化,但它比看油漆干慢。

1 个答案:

答案 0 :(得分:1)

我不确定你在测量什么 - 你提到的只是构造正则表达式对象,这可能不是你感兴趣的。

但是,测量重新查找以匹配字符串与正则表达式会在两种情况下产生非常相似的结果

(let [re #"12(ab)*34"
      s "aanbciasdfsidufuo12ab34xcnm,xcvnm,xncv,m"]
  (c/quick-bench 
   (re-find re s)))

Evaluation count : 907494 in 6 samples of 151249 calls.
             Execution time mean : 659.120946 ns
...


(let [re (re-pattern "12(ab)*34")
      s "aanbciasdfsidufuo12ab34xcnm,xcvnm,xncv,m"]
  (c/quick-bench 
   (re-find re s)))
Evaluation count : 1018872 in 6 samples of 169812 calls.
             Execution time mean : 588.138157 ns
...

文字正则表达式语法与re-pattern之间没有任何根本区别。最终都使用java.util.Pattern.compile方法编译最终的正则表达式。

re-pattern源代码:

...
  [s] (if (instance? java.util.regex.Pattern s)
        s
        (. java.util.regex.Pattern (compile s))))

文字语法由LispReader$RegexReader nested class处理:

public static class RegexReader extends AFn{
    static StringReader stringrdr = new StringReader();

    public Object invoke(Object reader, Object doublequote, Object opts, Object pendingForms) {
        StringBuilder sb = new StringBuilder();
        ...
        return Pattern.compile(sb.toString());
    }
}