如何使用重新匹配大小写或 core.match

How to use re-matches with case or core.match

我正在尝试在 Clojure 中实现模式匹配。我的偏好是使用 core.match 来匹配给定的正则表达式模式。我试过这个:

(defn markdown->html [markdown-line]
  (match [markdown-line]
    [(boolean (re-matches #"#\s+\w+" markdown-line))] (str "<h1>")))

这甚至无法正确编译。我转向了一个有条件的案例:

(defn markdown->html [markdown-line]
  (case markdown-line
    (boolean (re-matches #"#\s+\w+" markdown-line)) (str "<h1>")))

但是,当我用这个调用它时,它并没有给我预期的结果:(markdown->html "# Foo")

但是,这有效!

(defn markdown->html [markdown-line]
  (if
    (boolean (re-matches #"#\s+\w+" markdown-line)) (str "<h1>")))

对于上面的所有测试,我是这样调用函数的:(markdown->html "# Foo")

有谁知道我做错了什么吗?

查看 case 的文档:

The test-constants are not evaluated. They must be compile-time literals, and need not be quoted.

例如:

(case 'y
  y "y"
  c "c"
  (x z) "x or z"
  (a b) "a or b"
  "default")

clojure.core.match/match 相似,所以我想说两者都不是解决您的问题的工具。

如果您正在尝试编写将 Github markdown 转换为 HTML 的函数,请检查 clojure.string/replace,这可以帮助您:

(clojure.string/replace "# Foo bar
# Biz baz" #"#\s+([\w ]*)" (fn [[result group]] (str "<h1>" group "</h1>")))

=> "<h1>Foo bar</h1>\n<h1>Biz baz</h1>"

或者更好,对组使用 $

(clojure.string/replace "# Foo bar
# Biz baz" #"#\s+([\w ]*)" "<h1></h1>")

=> "<h1>Foo bar</h1>\n<h1>Biz baz</h1>"

顺便说一句,你的例子可以这样改进:

(defn markdown->html [markdown-line]
  (when (re-matches #"#\s+\w+" markdown-line) "<h1>"))

(markdown->html "# Foo")
=> "<h1>"

If 缺少 else 分支,所以 when 更好;您不必使用 boolean,因为 falsenil 被认为是逻辑假,任何其他值都是逻辑真,没有理由将一个字符串包装在 [=24 中=].

编辑: headers <h1> 的函数 - <h6>:

(def text "# Foo bar
## Biz baz
### Foo baz
## Biz foo")

(clojure.string/replace text
                        #"(#{1,6})\s+([\w ]*)"
                        (fn [[result group1 group2]]
                          (let [tag (str "h" (count group1) ">")]
                            (str "<" tag group2 "</" tag))))

=> "<h1>Foo bar</h1>\n<h2>Biz baz</h2>\n<h3>Foo baz</h3>\n<h2>Biz foo</h2>"