core.match

Shadowing bindings does not work as expected

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Critical Critical
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

This is a bug with core.match, or (far less likely) with the macro expansion in Clojure.

This code:

```
(let [foo [:bar :baz]]
(match foo
[:bar boo] boo
:else :got-else))
```

returns `:baz`. While this code:

```
(let [foo [:bar :baz]]
(match foo
[:bar foo] foo
:else :got-else))
```

returns `:got-else`.

They should be equal, since the `foo` in the match should shadow the `foo` in
the let. In fact, when running `macroexpand-1` on these forms, they only differ in
the gensym numbers and the letter `f` vs `b` in `foo` and `bar`.

I have created a repo that reproduces the bug:

https://github.com/magnars/bug-examples/tree/core-match-shadow-bindings

Activity

Hide
Greg Chapman added a comment - - edited

This is actually working as designed. core.match treats locally defined symbols (symbols which occur in the macro's &env) as literal expressions where the literal value is the evaluated symbol (to see this in match.clj, look for uses of the *locals* variable). Thus the match in your failing case is effectively:

(match foo
  [:bar [:bar :baz]] foo
  :else :got-else}
Show
Greg Chapman added a comment - - edited This is actually working as designed. core.match treats locally defined symbols (symbols which occur in the macro's &env) as literal expressions where the literal value is the evaluated symbol (to see this in match.clj, look for uses of the *locals* variable). Thus the match in your failing case is effectively:
(match foo
  [:bar [:bar :baz]] foo
  :else :got-else}

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: