Skip to content
This repository has been archived by the owner on Jun 24, 2020. It is now read-only.

Macro expansion in Clojure step defs #3

Open
mpkorstanje opened this issue Oct 14, 2017 · 0 comments
Open

Macro expansion in Clojure step defs #3

mpkorstanje opened this issue Oct 14, 2017 · 0 comments

Comments

@mpkorstanje
Copy link
Contributor

From: cucumber/cucumber-jvm#631

I am trying to use a macro in a step definition, and instead of having access to the value passed in to my step definition I get a symbol.

This is perhaps nothing more than me being relatively new to Clojure but it's certainly unexpected.

Given the the following scenario:

Scenario: Using macros inside step defintions
  Given my words are replaced:
  """
  My word is %{word}
  """

When I run my cukes with a step defintion like:

;; Step definition
(defmacro fmt [^String string]
  (let [-re #"%\{(.*?)\}"
        fstr (clojure.string/replace string -re "%s")
        fargs (map #(read-string (second %)) (re-seq -re string))]
    `(format ~fstr ~@fargs)))

(Given #"my words are replaced:" [string]
  (let [word "interpolated"]
    (assert (= (fmt string) "My word is interpolated")))

Then I get an error of:

Caused by: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.CharSequence
    at clojure.core$re_matcher.invoke(core.clj:4386)
    at clojure.core$re_seq.invoke(core.clj:4411)
    at cucumber.runtime.clj$fmt.invoke(api_steps.clj:18)
    at clojure.lang.Var.invoke(Var.java:423)
    at clojure.lang.AFn.applyToHelper(AFn.java:167)
    at clojure.lang.Var.applyTo(Var.java:532)
    at clojure.lang.Compiler.macroexpand1(Compiler.java:6468)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6546)

I've gisted the full backtrace if that's of use, and I'm running cukes via lein-cucumber.

[lein-cucumber "1.0.2"]
  [info.cukes/cucumber-clojure "1.1.1"]
    [info.cukes/cucumber-core "1.1.1"]

If this is just me struggling at 11pm I apologise.

As a workaround I'm using a function instead of a macro, and passing the interpolations in:

(defn- fmt [^String string interpolations]
  (let [pattern #"%\{(.*?)\}"
        f (fn [[_ k]] (get interpolations k :missing))]
    (clojure.string/replace string pattern f)))

Without the macro all is well.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant