Interesting.  This is a change in 1.6.0:

; => test.clj
(let [sym 'foo/bar/baz/bot]
  (prn {:name (name sym)
        :namespace (namespace sym)
        :version *clojure-version*}))

;; Running for all the (release) versions I had locally:
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 2,
:incremental 0, :qualifier ""}}
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 2,
:incremental 1, :qualifier ""}}
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 3,
:incremental 0, :qualifier nil}}
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 4,
:incremental 0, :qualifier nil}}
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 5,
:incremental 0, :qualifier nil}}
{:name "bot", :namespace "foo/bar/baz", :version {:major 1, :minor 5,
:incremental 1, :qualifier nil}}
{:name "bar/baz/bot", :namespace "foo", :version {:major 1, :minor 6,
:incremental 0, :qualifier nil}}

Several potentially-related changes in the 1.6.0 changelog (
https://github.com/clojure/clojure/blob/master/changes.md):

- Map destructuring extended to support namespaced keys (
http://dev.clojure.org/jira/browse/CLJ-1318)
- Allow EdnReader to read foo// (http://dev.clojure.org/jira/browse/CLJ-1238
)
- Allow ** as a valid symbol name without triggering "not declared dynamic"
warnings (http://dev.clojure.org/jira/browse/CLJ-1233)

But in general this doesn't seem well-advertised.



On Sat, May 24, 2014 at 6:01 PM, Gregg Reynolds <d...@mobileink.com> wrote:

> On Sat, May 24, 2014 at 3:14 PM, Benjamin R. Haskell <cloj...@benizi.com>
> wrote:
> > On Sat, May 24, 2014 at 3:09 PM, Gregg Reynolds <d...@mobileink.com>
> wrote:
> >>
> >> Hi,
> >>
> >> In working on an ANTLR grammar for Clojure I came across this regex in
> >> clojure.lang.LispReader which is used in matchSymbol:
> >>
> >> symbolPat == [:]?([\\D&&[^/]].*/)?(/|[\\D&&[^/]][^/]*)
> >>
> >> Look at the first part of the second group:
> >>
> >> /|[\\D&&[^/]]
> >>
> >> Am I missing something or is that equal to \\D?
> >
> >
> > That would be equal to \\D, but you're missing that /|[\\D&&[^/]][^/]* is
> > the alternation of / and [\\D&&[^/]][^/]* rather than ( the alternation
> of /
> > and [\\D&&[^/]] ) concatenated with [^/]*
>
> Aha.  So concatenation of [] binds more tightly than '|'?  Or maybe it
> follows from greedy matching on the second alternative.  In any case I
> made the opposite assumption.
>
> >
> > '/' is special-cased as a symbol.  It can only be used (with an optional
> > namespace) if it's the only character in the name.
>
> Something doesn't look right.
>
> user=> :a/b/c/d
> :a/b/c/d
> user=> (namespace :a/b/c/d)
> "a"
> user=> (name :a/b/c/d)
> "b/c/d"
> user=> (symbol "x/y/z" "foo")
> x/y/z/foo
> user=> (type 'x/y/z/foo)
> clojure.lang.Symbol
> user=> (namespace (symbol "x/y/z" "foo"))
> "x/y/z"
> user=> (namespace 'x/y/z/foo)
> "x"
> user=> (name 'x/y/z/foo)
> "y/z/foo"
> user=> (name (symbol "x/y/z" "foo"))
> "foo"
> ...etc...
>
> The sym regex gets it right - '/' chars are part of the ns string:
>
> user> (def longrgx (re-pattern
> "[:]?([\\D&&[^/]].*/)?(/|[\\D&&[^/]][^/]*)"))
> user> (re-find longrgx "x/y/z/foo")
> ["x/y/z/foo" "x/y/z/" "foo"]
>
> But it doesn't match a final '/' preceded by a namespace string:
> user> (re-find longrgx "x/y/z/")
> ["x/y/z" "x/y/" "z"]
>
> unless its doubled:
> user> (re-find longrgx "x/y/z//")
> ["x/y/z//" "x/y/z/" "/"]
>
> So if the name portion of a symbol cannot contain '/' then why
> user=> (name 'x/y/z/foo)
> "y/z/foo"
> user=> (name (symbol "x" "y/z/foo"))
> "y/z/foo"
>
> Ok, clojure.core/name calls clojure.lang.Named/getName, implemented by
> clojure.lang.Symbol.
>
> Conclusion: it looks like there is an inconsistency between the Symbol
> regex and matchSymbol processing, on the one hand, and Symbol.intern,
> which is called by matchSymbol and analyzes the passed string to set
> its name and namespace fields:
>
> /* in clojure.lang.Symbol
> static public Symbol intern(String nsname){
>     int i = nsname.indexOf('/');
>     if(i == -1 || nsname.equals("/"))
>         return new Symbol(null, nsname.intern());
>     else
>         return new Symbol(nsname.substring(0, i).intern(),
> nsname.substring(i + 1).intern());
> }
>
> I guess this isn't a big problem, since programming continues apace,
> but it is confusing and sure looks like a bug from here.  By now I
> would guess lots of code depends on (name foo) returning a string with
> embedded '/'.  Or maybe not.
>
> Thanks,
>
> Gregg
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to