This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-05
Channels
- # announcements (7)
- # beginners (107)
- # boot (5)
- # calva (2)
- # cider (18)
- # clj-kondo (48)
- # cljs-dev (16)
- # cljsrn (2)
- # clojure (208)
- # clojure-berlin (1)
- # clojure-dev (25)
- # clojure-europe (14)
- # clojure-italy (10)
- # clojure-nl (10)
- # clojure-sg (1)
- # clojure-spec (52)
- # clojure-uk (13)
- # clojurescript (53)
- # cursive (7)
- # data-science (7)
- # datomic (4)
- # duct (1)
- # events (10)
- # fulcro (1)
- # graphql (5)
- # jobs (2)
- # kaocha (13)
- # leiningen (6)
- # off-topic (17)
- # pathom (4)
- # quil (6)
- # re-frame (52)
- # reagent (12)
- # reitit (3)
- # shadow-cljs (97)
- # spacemacs (10)
- # sql (39)
- # tools-deps (18)
- # uncomplicate (1)
- # xtdb (1)
What is the proper way to run Jetty in the background in the REPL? I tried run-jetty handler {:port 3000})
but I think that runs in the foreground.
I think there's another option you can pass
in that map
Nah, I think it’s join?
@st3fan: yeah, :join? false
: https://github.com/ring-clojure/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj#L173
is there a built in facility to reload or refresh an entire ns, or all active ns in a given repl session?
require
has :reload
and :reload-all
(reloads dependent ns'es too) options
(require 'foo.bar :reload-all)
I feel like I really don't understand datafy and nav. I thought it would make sense to use it to implement a lazy beanification. So say I call datafy on a Java object, it returns me the bean for it (clojure's bean fn). And then I thought I could nav into a key of the map, which would in turn call bean on the value and return that. But I can't figure it out
@didibus have you read my blog posts about this, just out of curiosity?
I'm happy to chat about this because I've been using it extensively with JDBC stuff...
Maybe I'm also confused about the expected use from a user. Like I'm imaging I would be able to do: (-> a-java-object datafy (nav :field))
or something of the sort
By default, datafy
doesn't "do" much -- you need to extend the protocol for your specific case.
OK...?
(doesn't that override the built-in definition?)
Say I have:
public class Person {
public Car car;
}
public class Car {
public String make;
}
But now my thoughts were I could nav into :car. And in turn get the datafied car back
If you nav
into that you'll get a raw Java object. Then you call datafy
again.
The process is Thing -> datafy
-> data -> nav
-> newThing -> datafy
-> newData...
No, and it must not.
So here I would need to extend clojure Map so that nav returns the value at key? And then call datafy on that ?
Thing and newThing above are "native objects". It's a regular square of operations.
A Clojure hash map can be nav
'd natively.
I guess I don't understand nav. Like, if nav works over data, why do I need it? I can just use get or anything else to navigate the data
Because nav
on datafy
'd objects will produce new objects
If you're in the Clojure world only, datafy
is a no-op (identity), and only nav
does anything.
Not sure I follow...
Example with JDBC. datafy
turns a result set into a "result set that can be nav
'd"
And nav
on that produces something that can be datafy
'd.
So doesn't my example make sense then? datafy needs to return a Java object that can be nav'd
I don't understand your question.
It's Thing -> datafy
-> data -> nav
-> newThing -> datafy
-> newData.
I don't know how to explain it better than that.
It's a square: native objects on the left, Clojure data on the right. datafy
takes you from the left to the right. Normal Clojure navigation keeps you on the right. nav
takes you from the right to the left.
I think I'm starting to get it. Its probably just my example isn't as good a use case for it.
datafy
= go right; nav
= go diagonally left & down.
So in my example, I would do:
(extend-protocol p/Navigable
clojure.lang.APersistentMap
(nav [coll k v]
(get coll k)))
Where ideally I don't extend APeristentMap, but instead use the new meta-protocol extend so only the Map my datafy return has this nav implementation.I've no idea what you're asking here. APersistentMap
is already pure data.
I don't know how to explain this, sorry.
It makes complete sense to me.
You have to understand the square with non-data on the left and data on the right.
datafy
goes from non-data to data.
Normal Clojure code (like get
) navigates around on the right hand side (all data).
nav
works a bit like get
but takes you back to the left hand side (non-data).
If you're talking about Clojure data, none of this matters.
data -> datafy
-> data is identity
so data -> nav
is the same as data
-> get
-- and produces pure data.
This only matters/makes sense when you're starting with non-Clojure-data.
@vale It could be anything you want to (lazily) navigate and have a different representation. Have you looked at REBL at all?
REBL shows how to turn Vars and namespaces into (Clojure) data that you can then (lazily) nav
to interesting new data.
In particular, REBL lets you navigate through Vars into what they use and what uses them (dynamically).
Also, with namespaces, you have navigate into the items within them etc.
no i haven't played with rebl yet. i couldn't yet figure out what i'd need it for in the first place
In clojure.java.jdbc
(experimental) and next.jdbc
, you can datafy
a result set and get a "navigable" vector of hash maps, that will lazily take you to a new table.
@vale Maybe have a look at my YouTube videos about Atom/Chlorine/REBL?
REBL is a core part of my workflow, every day now. I love it.
in general, yes you use datafy/nav with java objects (as clojure data is already data and navigable)
Non-sequitur 🙂
Metadata really has nothing to do with this discussion, IMO.
(extend-protocol p/Datafiable
Object
(datafy [o]
(with-meta (into {} (bean o))
{`d/nav (fn [coll k v]
(get coll k))})))
That breaks a lot of stuff, "obviously"
I don't know what to say -- you're clearly fundamentally misunderstanding how this whole thing should work 😐
This does though:
(extend-protocol p/Datafiable
Object
(datafy [o]
(bean o)))
(extend-protocol p/Navigable
clojure.lang.APersistentMap
(nav [coll k v]
(get coll k)))
But it's wrong
You're breaking the non-data/data divide there.
But that's useless.
The important aspect here is: non-data -> datafy
-> data -> nav
-> non-data.
So that works purely because your datafy
isn't deep so it leaves native Java objects embedded in the data.
Your example is fine, but you're not understanding why.
It does take a while.
I happened to "grok" it quickly, but I've seen a lot of confusion about it since it was shown off at Clojure/conj late last year.
I think it's very early days for datafy
/`nav` so there's almost no one using it. I think more people need to use REBL to figure this out. That's where this stuff shines.
I think REBL is a game-changing breakthrough.. but unless you agree, you probably won't "get" datafy
/`nav`...
@didibus the following are also from seancorfield and quite helpful: https://github.com/seancorfield/next-jdbc/blob/master/doc/datafy-nav-and-schema.md (specifically the Identifying Foreign Keys section -- i went through this part with a friend using next.jdbc to follow his description in detail [1]) and this video of his demos this foreign key "link" (and more): https://www.youtube.com/watch?v=ZhzMoEz4j1k#t=6m40 [1] https://github.com/sogaiu/datafy-nav-with-next-jdbc -- includes links to other resources 🙂
Thanks @UG1C3AD5Z (and @U04V70XH6!) a very helpful summary of REBL resources!
Read the docs for spec
, I see the :confirm-keys
for map-of
? But there is no example for it, what's the different between add it and not add? I have done:
;; not add. default `false`
(s/def ::scores (s/map-of int? int?))
(s/conform ::scores {"Sally" 1000, "Joe" 500})
;; => :clojure.spec.alpha/invalid
;; add it.
(s/def ::scores (s/map-of int? int? :conform-keys true))
(s/conform ::scores {"Sally" 1000, "Joe" 500})
;; => :clojure.spec.alpha/invalid
In both of these examples, the keys are invalid. The difference is whether the keys are replaced with the conformed values or not in the result. If the key spec is a predicate, you won’t see any difference here - you’d need a key spec that conformed differently like s/or or a regex op
Is there something I can do about these warnings:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000801184840 (file:/Users/roklenarcic/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(org.xml.sax.InputSource,org.xml.sax.HandlerBase)
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x0000000801184840
solved the warning by adding
:jvm-opts ["--add-exports" "java.xml/com.sun.org.apache.xerces.internal.jaxp=ALL-UNNAMED"]
Would be good to know the source of the reflection - use —illegal-access=debug to learn more
The source is depstar library
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000801184840 (file:/Users/roklenarcic/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(org.xml.sax.InputSource,org.xml.sax.helpers.DefaultHandler)
at clojure.lang.Reflector.canAccess(Reflector.java:49)
at clojure.lang.Reflector.toAccessibleSuperMethod(Reflector.java:84)
at clojure.lang.Reflector.lambda$invokeInstanceMethod$0(Reflector.java:99)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:101)
at clojure.xml$startparse_sax.invokeStatic(xml.clj:76)
at clojure.xml$startparse_sax.invoke(xml.clj:75)
at clojure.xml$parse.invokeStatic(xml.clj:92)
at clojure.xml$parse.invoke(xml.clj:78)
at clojure.xml$parse.invokeStatic(xml.clj:86)
at clojure.xml$parse.invoke(xml.clj:78)
at hf.depstar.uberjar$maybe_copy_pom.invokeStatic(uberjar.clj:244)
at hf.depstar.uberjar$maybe_copy_pom.invoke(uberjar.clj:238)
at hf.depstar.uberjar$run$fn__244.invoke(uberjar.clj:317)
at hf.depstar.uberjar$run.invokeStatic(uberjar.clj:309)
at hf.depstar.uberjar$run.invoke(uberjar.clj:296)
at hf.depstar.uberjar$uber_main.invokeStatic(uberjar.clj:335)
at hf.depstar.uberjar$uber_main.invoke(uberjar.clj:328)
at hf.depstar.jar$_main.invokeStatic(jar.clj:6)
at hf.depstar.jar$_main.doInvoke(jar.clj:4)
Prob a good ticket for them then. There are some popular forks of depstar btw, not sure which you’re using
@U04V70XH6 seancorfield/depstar
Looks like this is use of clojure.xml, which is not recommended these days, should be using org.clojure/data.xml
that looks quite unfinished, also it seems to pull a bunch of development dependencies into the project (piggiback, clojurescript, tools nrepl, test.chec, figwheel-sidecar, binaryage/devtools)
it's a mess
Those are test deps so not pulled in. It’s more stable than the version implies.
The pom.xml is the source of truth in that project, not project.clj btw
depstar
very deliberately uses no external dependencies (so that it can rely on the contents of the classpath when it just excludes itself). That's why I used clojure.xml
. Switching to org.clojure/data.xml
would complicate stuff quite a bit.
Feel free to open an issue on GitHub for me to look at. If I can read the pom.xml
file without external dependencies and avoid clojure.xml
, that would be the ideal solution for me...
Maybe you could make the jar a java module that declares dependency on java.xml module... although the reflector is in clojure itself so I'm not sure if this would work
I haven't really read up on modules
It needs to work on JDK8...
seancorfield/depstar "0.3.3"
is available -- no longer uses clojure.xml
so you won't get "Illegal Reflective Access" warnings on JDK11 any more!
Every time I see similar issues, my brain’s first reaction would be: Are we using the ‘wrong’ jdk?
Hey folks, we are thinking about breaking down our glorious monolith into more apps and we were wondering what are the available options. We are open to have monorepos in order to share common code too. Or build a solution with multiple jars, etc. Any thoughts?
Found https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies
Is there any idiomatic or example work of extending Transit
so that you can send java.time
types, like LocalDate
, to Clojurescript?
@U0AQ3HP9U Here is an example read/write handler for Transit: https://github.com/dimovich/linked-transit that itself was based on this code https://github.com/tonsky/datascript-transit
Thanks @U051951T6 🙂 To be more precise; I’m working on an application that already uses Java7 types in the backend, such as java.util.Date
under #inst
s, and (I guess) cljs-time types and js native types in the frontend. I’m trying to figure out how to go about migrating to java.time
in the backend; the way I see it, I would also need a completely new set of types in the frontend unless I also change all of my existing types in one big-bang move; and if I have both Java7 types and java.time
types living side by side in my CLJ backend for a while, how else, other than discerning by the type in the CLJS frontend, is Transit
going to know when I’m referring to a type that should be converted to either a Java7 or java.time
type when sent to the CLJ backend?
So, seeing as java.time
is a new set of types, and transit/CLJS/CLJ traditionally and idiomatically rely on #inst
which is a Java7 construct, I figured someone else might already have gone through these motions and implemented a set of CLJS types along with transit handlers to match java.time
, or at least come up with a strategy for gradually moving an application with existing Java7 types and corresponding CLJS types to java.time
.
(a strategy that I could piggyback on 😄 )
❓Notice that lein compile :all
or lein jar
does not pick up a wrong-arity mistake in the code, e.g. (double? s "rubbish")
. Meaning if those lines of code are not covered by tests, they are shipped and becomes part of you outcome jar and let the runtime catch any exception like that. Are there any tips in handling this situation apart from relying on eastwood
?
Adopting a solid RDD (REPL-Driven Development) workflow where you eval and test each small piece of code as you write it -- even if you don't create actual test files -- goes a long way to eliminating this sort of mistake.
And then there are things like Joker which can check in real time as you're editing code (I use this with Atom all the time and catches nearly all arity errors, as well as unused local bindings and all sorts of other potential code problems).
https://www.dropbox.com/s/gdwrf30glar547o/Screenshot%202019-09-05%2018.21.25.png?dl=0
Those are my tips for handling the situation you asked about 🙂
RDD is a good workflow, regardless, because you get immediate feedback on all your code, and you get into the habit of making small changes and verifying each one. See Stu Halloway's talks (RDD to Chicago Clojure from June 2017, and Running With Scissors to Strange Loop 2018, as I recall) and also Eric Normand's excellent RDD online course (worth the monthly fee).
Experienced devs with a bad workflow will have more buggy code than most devs with a really good workflow.
yes, most devs do repl-dd. In reality, when you are under pressure, urgent to fix a bug, in a rush, things can happen
Using Language X's workflow with Clojure isn't enough. no matter how experienced you are.
I would argue that most (Clojure) devs do not do RDD. I see all sorts of evidence of that on this Slack...
Agree, but I would like an automated tooling to catch and stop these kind of obvious mistakes, at least eastwood could help with this kind of stuff, I think
Most Clojure devs still type stuff into the REPL and tend to write whole functions and tests and then run them. None of that is RDD.
(and don't get me started on how bad I consider the "watcher"-based workflows! 🙂 )
is it possible to slurp a file sitting in a jar in classpath, e.g.: I want to slurp externs.js for cljsjs package. Can someone show me how?
No, I mean real example. With a file sitting in a jar in ~/.m2. Can you show me an example with a real cljsjs package? How does the path to it looks like?
If you are talking about JVM classpath, they follow JVM convention, e.g. "com/example/package/file1.json"
So that’s my problem. I need to read an extern file for cljsjs package from Clojure code. I thought, since Clojure knows how to import things from ~/.m2, maybe there is a way to read those files
jar files are zip files, you can either use JarFile things to read them, or use io.zip.blah to read them
when I say (require ’some-lib) it knows where to get it. How can I slurp the source of `some-lib?
The precondition for (require)
to work is that the some-lib
jar is already on runtime classpath. (though classloader magic can make it dynamic of course).
source of a lib, it probably depends, if the source is packaged into the jar, you can slurp it via io file.
so… it is in the classpath, right? How do I slurp a file that’s in the classpath? It goes back to your first answer. But how do I do it for real? Can you show me using any library that you have listed in project.clj
this might help you https://github.com/stuarthalloway/reflector
the libraries in your proejct.clj does not exist as jar file on classpath, in stead, they exist like they have been extracted or unzipped
You might know this already, and not sure if this helps, but a jar is essentially a zip archive of the files it contains
https://stackoverflow.com/questions/8453543/extracting-jar-file-with-command-line/23887468
Adopting a solid RDD (REPL-Driven Development) workflow where you eval and test each small piece of code as you write it -- even if you don't create actual test files -- goes a long way to eliminating this sort of mistake.
seancorfield/depstar "0.3.3"
is available -- no longer uses clojure.xml
so you won't get "Illegal Reflective Access" warnings on JDK11 any more!