We're updating the issue view to help you get more done. 

Namespaced maps

Description

A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

1 2 {:person/first "Han" :person/last "Solo" :person/ship {:ship/name "Millenium Falcon" :ship/model "YT-1300f light freighter"}}

The namespaces provide value (disambiguation) but have the downside of being repetitive and verbose.

Namespaced maps are a reader (and printer) feature to specify a namespace context for a map.

  • Namespaced maps combine a default namespace with a map and yield a map.

  • Namespaced maps are reader macros starting with #: or #::, followed by a normal map definition.

    • #:sym indicates that sym is the default namespace for the map to follow.

    • #:: indicates that the default namespace auto-resolves to the current namespace.

    • #::sym indicates that sym should be auto-resolved using the current namespace's aliases OR any fully-qualified loaded namespace.

      • These rules match the rules for auto-resolved keywords.

  • A namespaced map is read with the following differences from normal maps:

    • A keyword or symbol key without a namespace is read with the default namespace as its namespace.

    • Keys that are not symbols or keywords are not affected.

    • Keys that specify an explicit namespace are not affected EXCEPT the special namespace _, which is read with NO namespace. This allows the specification of bare keys in a namespaced map.

    • Values are not affected.

    • Nested map keys are not affected.

  • The edn reader supports #: but not #:: with the same rules as above.

  • Maps will be printed in namespaced map form only when:

    • All map keys are keywords or symbols

    • All map keys are namespaced

    • All map keys have the same namespace

Examples:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ;; same as above - notice you can nest #: maps and this is a case where the printer roundtrips user=> #:person{:first "Han" :last "Solo" :ship #:ship{:name "Millenium Falcon" :model "YT-1300f light freighter"}} #:person{:first "Han" :last "Solo" :ship #:ship{:name "Millenium Falcon" :model "YT-1300f light freighter"}} ;; effects on keywords with ns, without ns, with _ ns, and non-kw user=> #:foo{:kw 1, :n/kw 2, :_/bare 3, 0 4} {:foo/kw 1, :n/kw 2, :bare 3, 0 4} ;; auto-resolved namespaces (will use user as the ns) user=> #::{:kw 1, :n/kw 2, :_/bare 3, 0 4} :user/kw 1, :n/kw 2, :bare 3, 0 4} ;; auto-resolve alias s to clojure.string user=> (require '[clojure.string :as s]) nil user=> #::s{:kw 1, :n/kw 2, :_/bare 3, 0 4} {:clojure.string/kw 1, :n/kw 2, :bare 3, 0 4} ;; to show symbol changes, we'll quote the whole thing to avoid evaluation user=> '#::{a 1, n/b 2, _/c 3} {user/a 1, n/b 2, c 3} ;; edn reader also supports (only) the #: syntax user=> (clojure.edn/read-string "#:person{:first \"Han\" :last \"Solo\" :ship #:ship{:name \"Millenium Falcon\" :model \"YT-1300f light freighter\"}}") #:person{:first "Han", :last "Solo", :ship #:ship{:name "Millenium Falcon", :model "YT-1300f light freighter"}}

Patch: clj-1910-2.patch

Screener notes:

  • Autoresolution supports fully-qualified loaded namespaces (like auto-resolved keywords)

  • TODO: pprint support for namespaced maps

  • TODO: printer flag to suppress printing namespaced maps

Environment

None

Status

Assignee

Alex Miller

Reporter

Alex Miller

Labels

Approval

Ok

Patch

Code and Test

Fix versions

Priority

Critical