This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-05-31
Channels
- # aws (2)
- # beginners (101)
- # cider (8)
- # clara (8)
- # cljs-dev (3)
- # cljsrn (17)
- # clojars (2)
- # clojure (67)
- # clojure-austin (2)
- # clojure-finland (1)
- # clojure-france (5)
- # clojure-italy (3)
- # clojure-nl (3)
- # clojure-russia (2)
- # clojure-serbia (1)
- # clojure-spec (72)
- # clojure-uk (112)
- # clojurescript (92)
- # core-async (74)
- # core-typed (2)
- # cursive (8)
- # datomic (2)
- # duct (5)
- # emacs (35)
- # events (11)
- # fulcro (32)
- # instaparse (9)
- # jobs (1)
- # luminus (1)
- # lumo (3)
- # off-topic (118)
- # om (2)
- # onyx (10)
- # pedestal (5)
- # re-frame (21)
- # reagent (48)
- # reitit (40)
- # ring (12)
- # shadow-cljs (113)
- # spacemacs (21)
- # tools-deps (47)
@raymcdermott I've tried a limited version of your code and this seems to work (when tested with nc
on command line):
(defn configured-prepl
[]
(clj-server/io-prepl :valf identity))
(defn shared-prepl
[opts]
(let [socket-opts {:port 5555
:server-daemon false ; Keep the app running
:accept `configured-prepl}]
(let [server (clj-server/start-server (merge socket-opts opts))]
(println "listening on port" (.getLocalPort ^ServerSocket server)))))
Run server:
(clj-server/remote-prepl "localhost" 5555)
Later on command line:
nc localhost 5555
(+ 1 1)
{:tag :ret, :val 2, :ns "user", :ms 0, :form "(+ 1 1)"}
(defn foo 1)
{:tag :ret, :val {:cause "Call to clojure.core/defn did not conform to spec:\nIn: [1] val: 1 fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector?\nIn: [1] val: 1 fails spec: :clojure.core.specs.alpha/args+body at: [:args :bs :arity-n :bodies] predicate: (cat :args :clojure.core.specs.alpha/arg-list :body (alt :prepost+body (cat :prepost map? :body (+ any?)) :body (* any?)))\n", :via [{:type clojure.lang.Compiler$CompilerException, ...
For client written in Clojure I guess you should try remote-prepl
as Alex suggested, but your problem seems to be related to the fact that read
is not able to recognize #object
in the response returned by remote repl.
The error looks is caused by sth. like this:
(pr-str (Object.))
#object[java.lang.Object 0x66a64b49 "java.lang.Object@66a64b49"]
(read-string (pr-str (Object.)))
RuntimeException No reader function for tag object clojure.lang.LispReader$CtorReader.readTagged (LispReader.java:1430)
The #object
in response comes from spec failure (partial output, see the last line)
{:tag :ret, :val {:cause "Call to clojure.core/defn did not conform to spec:\nIn: [1] val: 1
fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector?\nIn: [1]
val: 1 fails spec: :clojure.core.specs.alpha/args+body at: [:args :bs :arity-n :bodies]
predicate: (cat :args :clojure.core.specs.alpha/arg-list :body (alt :prepost+body
(cat :prepost map? :body (+ any?)) :body (* any?)))\n", :via [{:type clojure.lang.Compiler$CompilerException,
:message "clojure.lang.ExceptionInfo: Call to clojure.core/defn did not conform to spec:\nIn: [1]
val: 1 fails spec: :clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate: vector?\nIn: [1]
val: 1 fails spec: :clojure.core.specs.alpha/args+body at: [:args :bs :arity-n :bodies] predicate: (cat :args :clojure.core.specs.alpha/arg-list
:body (alt :prepost+body (cat :prepost map? :body (+ any?)) :body (* any?)))\n #:clojure.spec.alpha{:problems
({:path [:args :bs :arity-1 :args], :pred clojure.core/vector?, :val 1, :via [:clojure.core.specs.alpha/defn-args :clojure.core.specs.alpha/args+body
:clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [1]}
{:path [:args :bs :arity-n :bodies], :pred (clojure.spec.alpha/cat :args :clojure.core.specs.alpha/arg-list
:body (clojure.spec.alpha/alt :prepost+body (clojure.spec.alpha/cat :prepost clojure.core/map?
:body (clojure.spec.alpha/+ clojure.core/any?)) :body (clojure.spec.alpha/* clojure.core/any?))), :val 1,
:via [:clojure.core.specs.alpha/defn-args :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body], :in [1]}),
:spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x233319e7 \"clojure.spec.alpha$regex_spec_impl$reify__2436@233319e7\"]
,,,
I'm not sure if this can be resolved somehow...That last bit I tested in separate repl:
(require '[clojure.core.server :as ccs])
user=> (ccs/remote-prepl "localhost" 5555 *in* #(prn %))
(+ 1 1)
{:tag :ret, :val 2, :ns "user", :ms 0, :form "(+ 1 1)"}
(defn foo 1)
Exception in thread "clojure.core.server/remote-prepl" clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: No reader function for tag object
at clojure.lang.LispReader.read(LispReader.java:304)
...
in theory with valf set to identity we should get a :data
property and we can then read that directly
tbh I’m struggling on what to give it as a Reader and an out-fn …. so I’m in :thinking_face: mode at the moment
@raymcdermott Couldn't find anything better than leveraging *default-data-reader-fn*
somehow:
user=> (require '[clojure.core.server :as ccs])
nil
user=> (alter-var-root #'*default-data-reader-fn* (fn [_] (fn [tag value] value)))
#object[user$eval3$fn__138$fn__139 0xfd8294b "user$eval3$fn__138$fn__139@fd8294b"]
user=> (ccs/remote-prepl "localhost" 5555 *in* (fn [result] (if (-> result :val :cause) (prn (-> result :val :data)) (prn result))))
(+ 1 1)
{:tag :ret, :val 2, :ns "user", :ms 1, :form "(+ 1 1)"}
(defn foo 1)
{:clojure.spec.alpha/problems ({:path [:args :bs :arity-1 :args], :pred clojure.core/vector?, :val 1, :via [:clojure.core.specs.alpha/defn-args :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/arg-list :clojure.core.specs.alpha/arg-list], :in [1]} {:path [:args :bs :arity-n :bodies], :pred (clojure.spec.alpha/cat :args :clojure.core.specs.alpha/arg-list :body (clojure.spec.alpha/alt :prepost+body (clojure.spec.alpha/cat :prepost clojure.core/map? :body (clojure.spec.alpha/+ clojure.core/any?)) :body (clojure.spec.alpha/* clojure.core/any?))), :val 1, :via [:clojure.core.specs.alpha/defn-args :clojure.core.specs.alpha/args+body :clojure.core.specs.alpha/args+body], :in [1]}), :clojure.spec.alpha/spec [clojure.spec.alpha$regex_spec_impl$reify__2436 590551527 "clojure.spec.alpha$regex_spec_impl$reify__2436@233319e7"], :clojure.spec.alpha/value (foo 1), :clojure.spec.alpha/args (foo 1)}
I really must look at all of those ear-muff things one day if I’m going to live down here 🙂
This is interesting and probably ultimately needs a change in spec reporting. Rather than send the spec instance, it should be sending the spec name or form where you are seeing the object. For now, I think you’ll need to intercept either on the server or client side and either remove or transform it yourself
spec for the reporting
Maybe prepl although it gives you the hook to address it
I think hooking the default data reader to fall back to using tagged-literal is a pretty good dodge that covers many potential issues like this
How would I alias a namespace that isn't required? Circular dependency is a problem if I require it
I want to keep a separate namespace/file for my spec but use another namespace
Like my-namespace
with functions and my-namespace.spec
with the spec
But using :t/id
instead of having to write :my-namespace/id
So do you mean like.
Inside of my-namespace
you have some spec like
(s/def :t/id)
instead of (s/def ::id)
or (s/def :my-namespace/id)
As far as i understood you have to require the namespace the spec is in, to use it in a different namespace. But i could be wrong
So you might want to just move your spec somewhere else to get around the circular dependencies?
I ended up just giving certain specs fake namespaces to and not using ::id
. Instead something like :user/id
in my-namespace.spec
I have a (s/def ::id nat-int?)
. Resulting in :my-namespace.spec/id
I would like the spec to remain in my-namespace.spec
but be registered to :my-namespace/id
That will work, but it feels wrong when I have a lot of defs
You will still need to require my-namespace.spec
in a different ns if you want to use the spec contained
I think my counter argument to "but it feels wrong when I have a lot of defs" would be its a bit redundant to have .spec in the spec name
Only reason for the .spec
is that I want to have a separate namespace for the specs vs the functions
A bit worried about keyword collisions when doing it that way, but everything you say makes sense
I would have prefered to do something like (alias 't 'my-namespace
)
Yeah, but I might be using a third party library that also implement :user/name
or something
But that is a problem for future me 🙂 Thanks a lot for the help
sure but then you can prefix to to Andreas.user/name or Projectname.user/name etc :thumbsup:
In the docs it mentions vectors, but wouldn't a set of keys make more sense, like: (s/keys :req-un #{::a ::b})
?
conceptually, yes
I ask because I've seen a weird issue where UUIDs are not being coerced by spec-tools if I use a set 😅
You can reproduce it with
(s/def ::a (st/spec uuid?))
(s/def ::b (s/keys :req-un #{::a}))
(st/decode ::b {:a "4c6e852b-e8a3-4686-8916-4e345be53731"} st/json-transformer)
;; => {:a "4c6e852b-e8a3-4686-8916-4e345be53731"}
where st
is spec-tools.core
If you replace the set with a vector it works fine and coerces the UUID string into an actual UUID. I was thinking "maybe this is an issue with spec-tools", but if you're supposed to use a vector anyway this is technically okay, just a confusing gotcha.
yes, the s/keys
is parsed here: https://github.com/metosin/spec-tools/blob/master/src/spec_tools/parse.cljc#L112-L117. Hasn't been tested with sets. PR welcome ;)
So @U050V1N74 and I have spotted it 😄
Any idea why the call to flatten is required here though? https://github.com/metosin/spec-tools/blob/93ca24167131a2e312fed1da79beb25632090fda/src/spec_tools/impl.cljc#L53
(probably this one actually https://github.com/metosin/spec-tools/blob/93ca24167131a2e312fed1da79beb25632090fda/src/spec_tools/impl.cljc#L64)
I think it's for supporting the nested`or`s? See the tests https://github.com/metosin/spec-tools/blob/master/test/cljc/spec_tools/parse_test.cljc
Seems like https://dev.clojure.org/jira/browse/CLJ-2123 is related to my question about aliases