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?


Hide
Nicola Mometto added a comment - - edited

1- yes please. that's consistent with how tagged literals work.
2- no please. that would make the proposed syntax useless for e.g. Datomic schemas, for which I think this would be a good fit to reduce noise
3- yes please
4- yes please, consistency over print methods is important

Show
Nicola Mometto added a comment - - edited 1- yes please. that's consistent with how tagged literals work. 2- no please. that would make the proposed syntax useless for e.g. Datomic schemas, for which I think this would be a good fit to reduce noise 3- yes please 4- yes please, consistency over print methods is important
Hide
Nicola Mometto added a comment -

Quoting from a post I wrote on the clojure-dev ML:

  • I really don't like the idea of special-casing `_` here, users are already confused about idioms like `[.. & _]` thinking that `_` is some special token/variable. Making it an actual special token in some occasion wouldn't help.
  • I also don't like how we're making the single `:` auto-qualify keywords when used within the context of a qualifying-map. Auto-qualifying keywords has always been the job of the double `::`, changing this would introduce (IMO) needless cognitive overhead.
  • The current impl treats `#:foo{'bar 1}` and `'#:foo{bar 1}` differently. I can see why is that, but the difference might be highly unintuitive to some.
  • The current proposal makes it feel like quote is auto-qualifying symbols , when that has always been the job of syntax-quote. I know that's not correct, but that's how it's perceived.

Here's an alternative syntax proposal that handles all those issues:

  • No #::, only #:foo or #::foo
  • No auto-resolution of symbols when the namespaced-map is quoted, only when syntax-quoted
  • No special-casing of `_`
  • No auto-resolution of single-colon keywords

Here's how the examples in the ticket description would look:

#:person{::first "Han", ::last "Solo", ::ship #:ship{::name "Millenium Falcon", ::model "YT-1300f light freighter"}}
;=> {:person/first "Han" :person/last "Solo" :person/ship {:ship/name "Millenium Falcon" :ship/model "YT-1300f light freighter"}}

#:foo{::kw 1, :n/kw 2, :bare 3, 0 4}
;=> {:foo/kw 1, :n/kw 2, :bare 3, 0 4}

{::kw 1, :n/kw 2, bare 3, 0 4}
;=> {:user/kw 1, :n/kw 2, :bare 3, 0 4}

Note in the previous example how we don't need `#::` at all – `::` already does that job for us

(require '[clojure.string :as s])
#::s{::kw 1, :n/kw 2, bare 3, 0 4}
;=> {:clojure.string/kw 1, :n/kw 2, :bare 3, 0 4}

`{a 1, n/b 2, ~'c 3}
;=> {user/a 1, n/b 2, c 3}

Again, no need for `#::` here, we can just rely on the existing auto-qualifying behaviour of `.

`#:foo{a 1, n/b 2}
;=> {foo/a 1, n/b 2}

I think this would be more consistent with the existing behaviour – it's basically just making `#:foo` or `#::foo` mean: in the top-level keys of the following map expression, resolve keywords/symbols as if ns was bound to `foo`, rather than introducing new resolution rules and special tokens.

I realize that this proposal wouldn't work with EDNReader as-is, given its lack of support for `::` and "`". I don't have a solution to that other than "let's just bite the bullet and implement them there too", but maybe that's not acceptable.

Show
Nicola Mometto added a comment - Quoting from a post I wrote on the clojure-dev ML:
  • I really don't like the idea of special-casing `_` here, users are already confused about idioms like `[.. & _]` thinking that `_` is some special token/variable. Making it an actual special token in some occasion wouldn't help.
  • I also don't like how we're making the single `:` auto-qualify keywords when used within the context of a qualifying-map. Auto-qualifying keywords has always been the job of the double `::`, changing this would introduce (IMO) needless cognitive overhead.
  • The current impl treats `#:foo{'bar 1}` and `'#:foo{bar 1}` differently. I can see why is that, but the difference might be highly unintuitive to some.
  • The current proposal makes it feel like quote is auto-qualifying symbols , when that has always been the job of syntax-quote. I know that's not correct, but that's how it's perceived.
Here's an alternative syntax proposal that handles all those issues:
  • No #::, only #:foo or #::foo
  • No auto-resolution of symbols when the namespaced-map is quoted, only when syntax-quoted
  • No special-casing of `_`
  • No auto-resolution of single-colon keywords
Here's how the examples in the ticket description would look:
#:person{::first "Han", ::last "Solo", ::ship #:ship{::name "Millenium Falcon", ::model "YT-1300f light freighter"}}
;=> {:person/first "Han" :person/last "Solo" :person/ship {:ship/name "Millenium Falcon" :ship/model "YT-1300f light freighter"}}

#:foo{::kw 1, :n/kw 2, :bare 3, 0 4}
;=> {:foo/kw 1, :n/kw 2, :bare 3, 0 4}

{::kw 1, :n/kw 2, bare 3, 0 4}
;=> {:user/kw 1, :n/kw 2, :bare 3, 0 4}
Note in the previous example how we don't need `#::` at all – `::` already does that job for us
(require '[clojure.string :as s])
#::s{::kw 1, :n/kw 2, bare 3, 0 4}
;=> {:clojure.string/kw 1, :n/kw 2, :bare 3, 0 4}

`{a 1, n/b 2, ~'c 3}
;=> {user/a 1, n/b 2, c 3}
Again, no need for `#::` here, we can just rely on the existing auto-qualifying behaviour of `.
`#:foo{a 1, n/b 2}
;=> {foo/a 1, n/b 2}
I think this would be more consistent with the existing behaviour – it's basically just making `#:foo` or `#::foo` mean: in the top-level keys of the following map expression, resolve keywords/symbols as if ns was bound to `foo`, rather than introducing new resolution rules and special tokens. I realize that this proposal wouldn't work with EDNReader as-is, given its lack of support for `::` and "`". I don't have a solution to that other than "let's just bite the bullet and implement them there too", but maybe that's not acceptable.
Hide
Alex Miller added a comment -

Nicola, thanks for the proposal, we talked through it. We share your dislike for :_/kw syntax and you should consider that a placeholder for this behavior for the moment - it may be removed or replaced before we get to a published release.

For the rest of it:

  • requiring syntax quote is a non-starter
  • supporting a mixture of default ns and the current ns is important and this is not possible with your proposal. Like #:foo{:bar 1 ::baz 2}.
  • there is a lot of value to changing the scope of a map without modifying the contents, which is an advantage of the syntax in the ticket
Show
Alex Miller added a comment - Nicola, thanks for the proposal, we talked through it. We share your dislike for :_/kw syntax and you should consider that a placeholder for this behavior for the moment - it may be removed or replaced before we get to a published release. For the rest of it:
  • requiring syntax quote is a non-starter
  • supporting a mixture of default ns and the current ns is important and this is not possible with your proposal. Like #:foo{:bar 1 ::baz 2}.
  • there is a lot of value to changing the scope of a map without modifying the contents, which is an advantage of the syntax in the ticket
Hide
Christophe Grand added a comment -

Why restrict this feature to a single namespace? (this doesn't preclude a shorthand for the single mapping) I'd like to locally define aliases (and default ns).

Show
Christophe Grand added a comment - Why restrict this feature to a single namespace? (this doesn't preclude a shorthand for the single mapping) I'd like to locally define aliases (and default ns).
Hide
Alex Miller added a comment - - edited

We already have namespace level aliases. You can use :: in the map to leverage those aliases (independently from the default ns):

(ns app 
  (:require [my.domain :as d]
            [your.domain :as y]))

#::{:svc 1, ::d/name 2, ::y/name 3}

;;=> {:app/svc 1, :my.domain/name 2, :your.domain/y 3}
Show
Alex Miller added a comment - - edited We already have namespace level aliases. You can use :: in the map to leverage those aliases (independently from the default ns):
(ns app 
  (:require [my.domain :as d]
            [your.domain :as y]))

#::{:svc 1, ::d/name 2, ::y/name 3}

;;=> {:app/svc 1, :my.domain/name 2, :your.domain/y 3}
Hide
Christophe Grand added a comment -

Alex, if existing namespace level aliases are enough when there's more than one namespace used in the key set I fail to understand the real value of this proposal.

Okay I'm lying a little: there are no aliases in edn, so this would bring aliases to edn (and allows printers to factor/alias namespaces out). And for Clojure code you can't define an alias to a non-existing namespace – and I believe that this implementation wouldn't check namespace existence when resolving the default ns #:person{:name}.

Still my points hold for edn (and that's where the value of this proposal seems to be): why not allows local aliases too?

#:person #:employee/e {:name "John Smith", :e/eid "012345"}
;=> {:person/name "John Smith", :employee/eid "012345"}

I have another couple of questions:

  • should it apply to other datatypes?
  • should it be transitive?
Show
Christophe Grand added a comment - Alex, if existing namespace level aliases are enough when there's more than one namespace used in the key set I fail to understand the real value of this proposal. Okay I'm lying a little: there are no aliases in edn, so this would bring aliases to edn (and allows printers to factor/alias namespaces out). And for Clojure code you can't define an alias to a non-existing namespace – and I believe that this implementation wouldn't check namespace existence when resolving the default ns #:person{:name}. Still my points hold for edn (and that's where the value of this proposal seems to be): why not allows local aliases too?
#:person #:employee/e {:name "John Smith", :e/eid "012345"}
;=> {:person/name "John Smith", :employee/eid "012345"}
I have another couple of questions:
  • should it apply to other datatypes?
  • should it be transitive?
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?


Hide
Alex Miller added a comment -

New patch rev supports spaces between the namespace part #:foo and the map in both LispReader and EdnReader.

Show
Alex Miller added a comment - New patch rev supports spaces between the namespace part #:foo and the map in both LispReader and EdnReader.
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 ]
Hide
Tim Gilbert added a comment -

Any news on the flag to prevent this behavior (mentioned in the screener notes)?

I ask because (pr-str) in Clojure 1.9.0-alpha12 currently produces EDN that can't be consumed by (cljs.reader/read-string) in ClojureScript 1.9.229 (the ClojureScript consumption side is tracked in CLJS-1706).

It would be nice to have a way to disable this behavior until ClojureScript reaches parity, and a lot of fairly widely-used open-source libraries use plain (pr-str) to generate EDN output - for example, ring-middleware-format.

Show
Tim Gilbert added a comment - Any news on the flag to prevent this behavior (mentioned in the screener notes)? I ask because (pr-str) in Clojure 1.9.0-alpha12 currently produces EDN that can't be consumed by (cljs.reader/read-string) in ClojureScript 1.9.229 (the ClojureScript consumption side is tracked in CLJS-1706). It would be nice to have a way to disable this behavior until ClojureScript reaches parity, and a lot of fairly widely-used open-source libraries use plain (pr-str) to generate EDN output - for example, ring-middleware-format.
Hide
Alex Miller added a comment -

Yes, that was implemented in a separate ticket (CLJ-1993) in Clojure 1.9.0-alpha11. There is now a print-namespace-maps dynvar. It defaults to false, but is set to true in the standard REPL.

So at the REPL you can (set! print-namespace-maps false) to turn it off.

If you're doing stuff in your program outside a REPL, it will be off by default so you probably don't need to do anything as of alpha11.

Show
Alex Miller added a comment - Yes, that was implemented in a separate ticket (CLJ-1993) in Clojure 1.9.0-alpha11. There is now a print-namespace-maps dynvar. It defaults to false, but is set to true in the standard REPL. So at the REPL you can (set! print-namespace-maps false) to turn it off. If you're doing stuff in your program outside a REPL, it will be off by default so you probably don't need to do anything as of alpha11.
Hide
Alex Miller added a comment -

that's *print-namespace-maps* above, sorry for the formatting

Show
Alex Miller added a comment - that's *print-namespace-maps* above, sorry for the formatting
Hide
Vitalie Spinu added a comment -

Any plans to extend this to vectors? Would be useful in a number of contexts:

(s/keys :req #:foo[:a :b])
(select-keys m #:foo[:a :b])
(get-in m #:foo[:a :b])
Show
Vitalie Spinu added a comment - Any plans to extend this to vectors? Would be useful in a number of contexts:
(s/keys :req #:foo[:a :b])
(select-keys m #:foo[:a :b])
(get-in m #:foo[:a :b])
Hide
Alex Miller added a comment -

We've considered extending it to vectors and that might be a future addition. One thing with that is it drives the question of whether the namespace syntax should be applicable to all collections and the syntax clashes with the set literal syntax is pretty ugly: #:foo#{:a :b}.

Show
Alex Miller added a comment - We've considered extending it to vectors and that might be a future addition. One thing with that is it drives the question of whether the namespace syntax should be applicable to all collections and the syntax clashes with the set literal syntax is pretty ugly: #:foo#{:a :b}.
Hide
Vitalie Spinu added a comment -

How do I bind *print-namespace-maps* in REPL?

with-bindings hardcodes it to true. Looks like an ugly exception, as all the other bindings pick the root value there.

Show
Vitalie Spinu added a comment - How do I bind *print-namespace-maps* in REPL? with-bindings hardcodes it to true. Looks like an ugly exception, as all the other bindings pick the root value there.
Hide
Alex Miller added a comment -

If you're in a clojure.main repl, as you note it's already bound, so you can just use `set!`:

user=> (set! *print-namespace-maps* false)
false
user=> {:a/b 1}
{:a/b 1}

This won't work in nrepl-based repls that don't set it though, so you can also use `binding`:

user=> (binding [*print-namespace-maps* false] (println {:a/b 1}))
{:a/b 1}
Show
Alex Miller added a comment - If you're in a clojure.main repl, as you note it's already bound, so you can just use `set!`:
user=> (set! *print-namespace-maps* false)
false
user=> {:a/b 1}
{:a/b 1}
This won't work in nrepl-based repls that don't set it though, so you can also use `binding`:
user=> (binding [*print-namespace-maps* false] (println {:a/b 1}))
{:a/b 1}
Hide
Vitalie Spinu added a comment -

Thanks for the clarification. It's NREPL issue then. I can happily set! other globals there but not this one.

Show
Vitalie Spinu added a comment - Thanks for the clarification. It's NREPL issue then. I can happily set! other globals there but not this one.

People

Vote (1)
Watch (10)

Dates

  • Created:
    Updated:
    Resolved: