Clojure

Namespaced maps

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Critical Critical
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: Release 1.9
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Ok

Description

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

{: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:

;; 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
  1. clj-1910.patch
    07/Apr/16 11:36 AM
    11 kB
    Alex Miller
  2. clj-1910-2.patch
    28/Apr/16 1:33 PM
    14 kB
    Alex Miller

Activity

Alex Miller made changes -
Field Original Value New Value
Assignee Alex Miller [ alexmiller ]
Fix Version/s Release 1.9 [ 10750 ]
Attachment clj-1910.patch [ 15582 ]
Approval Vetted [ 10003 ]
Alex Miller made changes -
Description A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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 normal map definition.
* Namespaced maps are reader macros starting with "#:" or "#::".
** "#: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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Patch changes print-method for maps but not pprint. Should it?
A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Patch changes print-method for maps but not pprint. Should it?
3. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
Alex Miller made changes -
Description A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Patch changes print-method for maps but not pprint. Should it?
3. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


Alex Miller made changes -
Description A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


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

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


Alex Miller made changes -
Priority Major [ 3 ] Critical [ 2 ]
Alex Miller made changes -
Description A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


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

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


Alex Miller made changes -
Attachment clj-1910-2.patch [ 15635 ]
Description A common usage of namespaced keywords and symbols is in providing attribute disambiguation in map contexts:

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

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:

{code}
;; 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"}}
{code}

*Open questions:*

1. Current patch does not allow whitespace between ns and map definition. Should we allow whitespace there for formatting?
2. Should autoresolution support fully-qualified loaded namespaces? (like auto-resolved keywords)
3. Should there be a printer flag to suppress printing namespaced maps?
4. Patch changes print-method for maps but not pprint. Should it?


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

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

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:

{code}
;; 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"}}
{code}

*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
Stuart Halloway made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Rich Hickey made changes -
Approval Screened [ 10004 ] Ok [ 10007 ]
Alex Miller made changes -
Status Open [ 1 ] Resolved [ 5 ]
Resolution Completed [ 1 ]
Alex Miller made changes -
Status Resolved [ 5 ] Closed [ 6 ]

People

Vote (1)
Watch (10)

Dates

  • Created:
    Updated:
    Resolved: