This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-22
Channels
- # announcements (2)
- # architecture (33)
- # babashka (4)
- # beginners (445)
- # bristol-clojurians (10)
- # calva (23)
- # cider (43)
- # clj-kondo (36)
- # cljs-dev (13)
- # cljsrn (20)
- # clojure (136)
- # clojure-argentina (8)
- # clojure-dev (1)
- # clojure-europe (18)
- # clojure-germany (1)
- # clojure-italy (5)
- # clojure-nl (45)
- # clojure-spec (66)
- # clojure-uk (29)
- # clojurescript (69)
- # conjure (157)
- # cursive (2)
- # datomic (216)
- # emacs (10)
- # exercism (4)
- # figwheel-main (8)
- # fulcro (30)
- # graphql (21)
- # hoplon (5)
- # kaocha (7)
- # leiningen (3)
- # luminus (4)
- # music (1)
- # off-topic (24)
- # pathom (10)
- # re-frame (19)
- # reagent (11)
- # reitit (16)
- # remote-jobs (1)
- # ring-swagger (5)
- # rum (7)
- # shadow-cljs (125)
- # spacemacs (8)
- # sql (9)
- # tools-deps (12)
should spec have their own ns an import app ns? or should the app import the spec ns? I am having this issue that circular dependencies seem unavoidable
@ashnur The answer is "it depends". You should be able to find a partial ordering of dependencies that would allow you to split things into different namespaces -- probably three, so you have an "app" ns, a "spec" ns, and a "predicate" or "utility" ns that contains things the specs depend on, and the app can also depend on. But it may not be worth doing that analysis so having the specs in the same ns as your app code may just be easier.
If you're writing code that you want to be able to run on older versions of Clojure(Script) that don't include spec, you have to break them out into optional namespaces so that users can opt in if they want the specs -- but that's really only for library writers.
At work, I try to have the data specs in a separate namespace (and do the work to untangle any problematic dependencies) but the function specs will generally go in the same namespace as the functions they are for.
The simple answer to that question is no. The complex answer is there are ways to spread a namespace across multiple files but I don't think it will solve the problem you have here.
I must be doing something silly again because I am unable to refer to my s/defs from the spec file/ns
Can you share some code to illustrate the problem? Is this in a project up on GitHub?
in spec file I wanted to do something like (s/def :my.specs/one-spec identity) then in app file ns require [my.specs :as myspecs]
it's closed source but I can make a new repo with completely new code, it might just take a couple of weeks before i have the time
OK. And what can't you do in the app file ns?
(sorry for the delay in responding -- was dealing with an issue someone just opened on clj-new that I needed to repro!)
In you app file ns, after that require, you should be able to reference that spec either as :my.specs/one-spec
(i.e., its fully-qualified name) or ::myspecs/one-spec
using the auto-resolve syntax which will expand ::myspecs
to :my.specs
using the alias of the namespace... the latter requires that the actual spec name really matches the spec ns in the qualifier. (and you could just (s/def ::one-spec identity)
in the spec ns to have the spec automatically match the ns of the namespace it is defined in).
I feel bad if you apologize for such stuff, I realize people have lives beyond what is visible here : )
I am also in utter confusion about how keywords work, not just in spec but other places. I know it's a symbol that retuns itself, but apparently it also can hold specs
s/def
updates a registry behind the scenes which is essentially a map from keywords to spec objects. The keywords don't "hold" specs -- the association is done separately.
I have no idea what (def (s/def ...))
would do... but it's definitely not the right thing to do.
That's what I assumed -- not the right thing to do.
The "name-of-spec" is the keyword. That's how you refer to it in code that calls s/valid?
or something.
Link? So I can see what the context is.
Ah, probably because of function specs: s/fdef
uses the fully-qualified function name (symbol) so that's probably why s/def
will accept a symbol.
You can't refer in a single spec.
Once you've loaded the ns in which specs are defined, they are globally available.
They're not like Vars or functions.
So you could require the specs ns in whatever you app entry point is and you would have access to those specs (as keywords) everywhere in your program.
Just require the namespace like any other. Then the specs are in the registry and available globally.
Yeah, if you're not using the ::
auto-resolve syntax, you don't even need :as
(:require ... [my.specs] ...)
when I think I understand something, it turns out that thing is specific to that particular area, and something else using the same syntax behaves completely differently
Here's where the docs talk about the registry https://clojure.org/guides/spec#_registry -- don't know if that'll help?
the problem, which you have to realize is a problem, that I've had this page open for days and I have read it through from top to bottom and bottom to up several times
Don't worry, sometimes it taking a lot of reading the Clojure docs before it actually makes sense and you get to see a big picture!
this time I will succeed because finaly I can do stuff like this, waking up at 1:30 am, then suffering for an hour before you come to help 🙂
I hear great things about shadow-cljs -- when (if) I ever go back to trying to do ClojureScript, that's the path I'll take.
Hello everyone,
I am defining some specs in a .cljc
file, some only exist in a #?(:clj (do ...))
, others in a #?(:cljs (do ...))
I get an error on a keyword at parsing time:
2. Unhandled clojure.lang.ExceptionInfo
failed compiling
file:/.../foo.cljc
{:file
#object[.File 0x5b1b23e7 "/.../foo.cljc"],
:clojure.error/phase :compilation}
compiler.cljc: 1717 cljs.compiler$compile_file$fn__3955/invoke
1. Caused by clojure.lang.ExceptionInfo
/.../foo.cljc
[line 52, col 41] Invalid keyword: ::const/env.
{:type :reader-exception,
:ex-kind :reader-error,
:file
"/.../foo.cljc",
:line 52,
:col 41}
Here the ::const
namespace is declared only for .clj parts of code (:require ... #?(:clj [... :as const]))
When I split this .cljc into two files .clj and .cljs, there is no error.
Would it be related to spec or is it a more general error? It is the first time that it happens.
I really don't have any clue.
Thanksit's more general - ::const relies on having a clojure runtime namespace context to resolve it - I'm not sure what the exact problem is without more context but generally you'll want to avoid these in reader conditionals
you should be able to just use :foo/const or whatever instead
Thanks @alexmiller it works. It's not as convenient as the shortcut version but it's still better than two .clj and cljs files. If you want more info, don't hesitate to ask for. I'll send in a private message.