I am trying to implement pattern-matching in Clojure. My preference is to use core.match
to match on a given regex pattern. I tried this:
(defn markdown->html [markdown-line]
(match [markdown-line]
[(boolean (re-matches #"#\s+\w+" markdown-line))] (str "<h1>")))
This does not even compile properly. I pivoted to a case conditional:
(defn markdown->html [markdown-line]
(case markdown-line
(boolean (re-matches #"#\s+\w+" markdown-line)) (str "<h1>")))
However, that did not give me the expected results when I invoke it with this: (markdown->html "# Foo")
However, this works!
(defn markdown->html [markdown-line]
(if
(boolean (re-matches #"#\s+\w+" markdown-line)) (str "<h1>")))
For all the tests above, I am invoking the function like so: (markdown->html "# Foo")
Does anyone know what I am doing wrong?
See the docs for case
:
The test-constants are not evaluated. They must be compile-time literals, and need not be quoted.
For example:
(case 'y
y "y"
c "c"
(x z) "x or z"
(a b) "a or b"
"default")
And clojure.core.match/match
is similar, so I'd say both are wrong tool for your problem.
If you're trying to write function for converting Github markdown to HTML, check clojure.string/replace
, which can help you:
(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>"
Or even better, using $
for group:
(clojure.string/replace "# Foo bar
# Biz baz" #"#\s+([\w ]*)" "<h1>$1</h1>")
=> "<h1>Foo bar</h1>\n<h1>Biz baz</h1>"
By the way, your example can be improved like this:
(defn markdown->html [markdown-line]
(when (re-matches #"#\s+\w+" markdown-line) "<h1>"))
(markdown->html "# Foo")
=> "<h1>"
If
is missing else branch, so when
is better; you don't have to use boolean
, because false
or nil
are considered as logical false and any other value is logical true and there is no reason to wrap one string in str
.
EDIT: Function for 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>"