Guidelines/Recommendations for namespaces and qualified keywords

240 views
Skip to first unread message

Josh Tilles

unread,
Oct 15, 2016, 11:17:15 PM10/15/16
to Clojure
I’ve got a couple questions for Alex Miller and/or the other Cognitect folks.
  1. Are single-segment namespaces still “bad” when it comes to registering specs under qualified keywords?
    In the past, single-segment namespaces have been discouraged in the Clojure community—both because of Java interop concerns and because of the possibility of name-collision when combining projects. However, many of the spec examples I’ve seen have demonstrated registering specs under keywords qualified by a single-segment namespace. For example, the guide’s section on multi-spec defines :search/url and :error/message. Is that because namespace-qualifiers of specs shouldn’t be under the same constraints as namespaces used to organize code? I’m guessing not; it seems more likely that the single-segment namespaces have been used only to keep the code snippets straightforward and focused on spec, and that “real” code would alias (e.g.) my-company.my-project.search as search before defining a ::search/url spec.

  2. When designing, how do you decide whether to use a simple keyword or a qualified one?
    There’s an interesting mix of the two in the official docs and in the code for spec itself. For example: the spec rationale and guide both use simple keywords when labeling path components, and spec reports invocation errors for instrumented functions with maps that exclusively use qualified keys at the “root” but simple keywords appear as values and as keys in nested maps.
Thank you for your help. I really appreciate it.

Best,
Josh

James Gatannah

unread,
Oct 17, 2016, 10:46:06 PM10/17/16
to Clojure


On Saturday, October 15, 2016 at 10:17:15 PM UTC-5, Josh Tilles wrote:
I’ve got a couple questions for Alex Miller and/or the other Cognitect folks.

That isn't me. I'm just chiming in from the peanut gallery. Must of my "experience" so far stems from converting
my toy projects from prismatic schema to spec.
  1. Are single-segment namespaces still “bad” when it comes to registering specs under qualified keywords?
    In the past, single-segment namespaces have been discouraged in the Clojure community—both because of Java interop concerns and because of the possibility of name-collision when combining projects. However, many of the spec examples I’ve seen have demonstrated registering specs under keywords qualified by a single-segment namespace. For example, the guide’s section on multi-spec defines :search/url and :error/message. Is that because namespace-qualifiers of specs shouldn’t be under the same constraints as namespaces used to organize code?
This part of the question interests me a lot.

I've found myself defining a lot of specs in, say, the com.foo.project.schemas namespace.

This used to be extremely convenient, due to ns aliases.

I think the docs say that I should be able to set up the same kind of basic aliasing so that I can
just refer to those specs as (for example) :c.f.p.s/whatever. But I haven't been able to actually 
get that to work yet.

I've found myself with a lot of definitions that look like (apologies for the formatting/whitespace):

(s/def ::socket-description (s/keys :opt [::client-keys
                                          ::server-key]
                                    :req [::ctx
                                          :com.jimrthy.cljeromq.common/direction
                                          ::port
                                          ::sock-type
                                          :com.jimrthy.cljeromq.common/socket
                                          :com.jimrthy.cljeromq.core/url]))

That isn't *too* bad. But this sort of thing gets annoying when I'm nesting these things into other namespaces. Especially from the REPL, which is lisp's strongest selling point (to me).

I'm willing to bet that I've just missed a talk somewhere about how this is supposed to work. Or maybe I just need to keep working on getting my head wrapped around these changes.

I don't want to hijack your thread. This was more of a "Me too! This is why...I think" sort of thing.. 



  1. I’m guessing not; it seems more likely that the single-segment namespaces have been used only to keep the code snippets straightforward and focused on spec, and that “real” code would alias (e.g.) my-company.my-project.search as search before defining a ::search/url spec.

Thank you for your help. I really appreciate it.

Again, me too! Thanks,
James 

Best,
Josh

Mauricio Aldazosa

unread,
Oct 17, 2016, 11:10:56 PM10/17/16
to clo...@googlegroups.com
On Mon, Oct 17, 2016 at 9:46 PM, James Gatannah <james.g...@gmail.com> wrote:


On Saturday, October 15, 2016 at 10:17:15 PM UTC-5, Josh Tilles wrote:
I’ve got a couple questions for Alex Miller and/or the other Cognitect folks.

That isn't me. I'm just chiming in from the peanut gallery. Must of my "experience" so far stems from converting
my toy projects from prismatic schema to spec.
  1. Are single-segment namespaces still “bad” when it comes to registering specs under qualified keywords?
    In the past, single-segment namespaces have been discouraged in the Clojure community—both because of Java interop concerns and because of the possibility of name-collision when combining projects. However, many of the spec examples I’ve seen have demonstrated registering specs under keywords qualified by a single-segment namespace. For example, the guide’s section on multi-spec defines :search/url and :error/message. Is that because namespace-qualifiers of specs shouldn’t be under the same constraints as namespaces used to organize code?
This part of the question interests me a lot.

I've found myself defining a lot of specs in, say, the com.foo.project.schemas namespace.

This used to be extremely convenient, due to ns aliases.

I think the docs say that I should be able to set up the same kind of basic aliasing so that I can
just refer to those specs as (for example) :c.f.p.s/whatever. But I haven't been able to actually 
get that to work yet.

You can use the alias to do that, if you have a ns declaration like this:

(ns test.core
  (:require [com.foo.project.schemas :as sch]))

Then you can use the alias to get to the specs in that namespace

::sch/bar => :com.foo.project.schemas/bar

Cheers,
Mauricio

Alex Miller

unread,
Oct 18, 2016, 10:07:49 AM10/18/16
to Clojure


On Saturday, October 15, 2016 at 10:17:15 PM UTC-5, Josh Tilles wrote:
I’ve got a couple questions for Alex Miller and/or the other Cognitect folks.
  1. Are single-segment namespaces still “bad” when it comes to registering specs under qualified keywords?
I will give a qualified *sometimes*. :) There are several possible contexts and I would not give the same answer for all of them. 

If you are creating a library, particularly a library that will interoperate with other libraries, I would strongly recommend using namespaced keywords with sufficient namespaces that you will not clash with others. In some cases, a library may be well-entrenched or well-known enough to make a single namespace sufficient. For example, consider ring request/response maps and middleware, which is a prime example for interoperable libraries. If you were creating a Ring session middleware, you might want to use namespace keys in the request like :ring.session/token (or whatever, don't compare this to any actual existing lib). Here, "ring" is probably sufficiently established to be unambiguous and "ring.session" scopes you to something narrower. I think that's highly preferable to just :ring/token. 

If you're creating a brand new library designed for interoperation with other libs, I would strongly consider using more than a single segment namespace that combines some notion of organization and project. 

If you're creating an internal application, I think you're free to do whatever you want. So a single segment path in the context of a single application might be totally fine - :domain/email. As long as you're not colliding with some library and you coordinate in your private scope, do what communicates the best for you. If you have multiple internal projects that need to coordinate, you might need more namespace segments to disambiguate.
  1. In the past, single-segment namespaces have been discouraged in the Clojure community—both because of Java interop concerns and because of the possibility of name-collision when combining projects. However, many of the spec examples I’ve seen have demonstrated registering specs under keywords qualified by a single-segment namespace. For example, the guide’s section on multi-spec defines :search/url and :error/message. Is that because namespace-qualifiers of specs shouldn’t be under the same constraints as namespaces used to organize code?
These short names are mostly chosen to make the examples brief and readable, although they might be sufficient when used in an application as mentioned above. However, I think it is important to note that your namespace qualifiers do NOT need to correspond to your code. You can use create-ns and alias to create shorter names in the context of a particular namespace just to save typing, while still using namespaces independent from your code. We are considering changing alias to automatically create a ns if it does not exist (see http://dev.clojure.org/jira/browse/CLJ-2030).
  1. I’m guessing not; it seems more likely that the single-segment namespaces have been used only to keep the code snippets straightforward and focused on spec, and that “real” code would alias (e.g.) my-company.my-project.search as search before defining a ::search/url spec.
Yes. 

  1. When designing, how do you decide whether to use a simple keyword or a qualified one?
    There’s an interesting mix of the two in the official docs and in the code for spec itself. For example: the spec rationale and guide both use simple keywords when labeling path components, and spec reports invocation errors for instrumented functions with maps that exclusively use qualified keys at the “root” but simple keywords appear as values and as keys in nested maps.
Path components are simple as they exist in the context of a particular spec which has a fully-qualified name. I suspect in general the other choices mostly follow that pattern - fully-qualified when they are used without context or when they might be intermingled with other keys and unqualified when used as keys in the scope of some other context. That said, things may not be 100% consistent in every possible case.

Hope that helps!
Alex
Reply all
Reply to author
Forward
0 new messages