This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-08
Channels
- # 100-days-of-code (1)
- # admin-announcements (1)
- # aleph (1)
- # announcements (9)
- # beginners (125)
- # cider (1)
- # cljs-dev (80)
- # cljsrn (2)
- # clojure (82)
- # clojure-czech (1)
- # clojure-dev (5)
- # clojure-finland (1)
- # clojure-italy (16)
- # clojure-nl (6)
- # clojure-spec (24)
- # clojure-uk (39)
- # clojurescript (35)
- # community-development (49)
- # core-async (3)
- # cursive (31)
- # data-science (17)
- # datomic (21)
- # emacs (5)
- # fulcro (92)
- # graphql (1)
- # jobs (2)
- # lambdaisland (1)
- # leiningen (19)
- # luminus (9)
- # off-topic (21)
- # parinfer (6)
- # pedestal (1)
- # portkey (2)
- # re-frame (12)
- # reagent (8)
- # reitit (4)
- # shadow-cljs (117)
- # spacemacs (5)
- # specter (4)
- # sql (2)
- # testing (2)
- # tools-deps (3)
- # vim (1)
I am getting started with Cursive. I have opened a leiningen project, and I want to start a REPL from the project's root dir, but when the REPL starts it appears to eval the <project-name>/core.clj file. If I have errors or incomplete code in that file the eval will error and the REPL won't start. Is there a way I can prevent the REPL from eval'ing the file on startup?
@ben.grabow I'm not familiar with Cursive but @cfleming is very helpful over in the #cursive channel (he's not in this channel).
Does anybody has similar issue https://github.com/incanter/incanter/issues/397 ?
@stardiviner Incanter requires a very old version of java.jdbc
-- it hasn't been updated to work with any recent versions.
I suspect you'll need to choose something way back in the 0.2.3-ish range?
Is there a way to stick Incanter to use specific java.jdbc version? I think Incanter should do this by default.
Isn't this should be dependency handling when released? Hmmm, first time meet this problem.
Well, Incanter depends on clojureql
and here's the java.jdbc
dependency: https://github.com/LauJensen/clojureql/blob/master/project.clj
0.2.3
If you remove org.clojure/java.jdbc
from your project.clj
, it will use the one that Incanter expects.
But you can't have two different versions -- and you'll be forced to use that very old version's API in your own code too for that project.
I see. Thanks @seancorfield
I added a comment to that GitHub issue.
It's interesting that clojureql
went five years with no changes (from 2013 until early 2018). It was updated to make it work with Clojure 1.9 but the other dependencies weren't updated.
Maybe the maintainer doesn't update a lot. This is really bad of locking support on new release of esstensioanl basic libraries like jdbc.
I want to convert a date string into a date object to be used by clj-time.core/date-time
. Here is my try: (.format (new SimpleDateFormat "yyyy-mm-dd hh:mm:ss") "2018-02-01 12:11:05")
But it reports error: `java.lang.IllegalArgumentException
Cannot format given Object as a Date`. Seems my syntax is wrong.
I don't know Java. don't know whether it is correct for invoke method like that.
@stardiviner To be fair, most libraries don't change their API as much as java.jdbc
has had to change over the years. When I took it over, it was a fairly old-fashioned API, relying on global dynamic variables which doesn't compose well (if you needed to interact with more than one DB) and options weren't consistently passed through everything -- and it used named arguments (with keywords) instead of option maps.
But I signaled deprecation long in advance of removing anything and I kept the old API around in a separate namespace for a while as well. I hoped everyone would update their libraries to the modern API over a period of a few years 😐
@stardiviner Regarding clj-time
, you can use clj-time.format
and parse
the string into a date/time object.
BTW, if you're starting a new project from scratch on Java 8 or later, I would recommend not using clj-time
and instead using Java Time (built-in), via the clojure.java-time
wrapper if you really want to avoid Java interop.
(and the clj-time
readme makes that clear)
This is terrible. I wish those libraries can update on new API. Is there a way to find out all clojure libraries rely on jdbc, then send email or IM notifications to authors/maintainers?
Thanks for suggestion.
Hum, I wonder in this case, had you changed the name of the lib, then both versions could have co-existed on the classpath
Well, clojure.java.jdbc
predates that talk by many years 🙂
I took it over (as contrib.sql) back in 2011.
When it was part of the monolithic contrib library and everything got split up and renamed.
Haha, I know, not criticizing, just realizing some of the value of that talk. Though for some reason, the JVM core devs are very against that idea.
I asked the Clojure/core folks for feedback on the API and what it would take to get it to 1.0.0 -- and they wanted the dynamic variables removed and didn't like the namespace organization so I made a lot of changes...
Here's an overview of what relies on which versions of it https://crossclj.info/ns/org.clojure/java.jdbc/latest/project.clj.html
Incanter was pretty much abandonware for quite a while...
Maybe that's a bit harsh 🙂
It has been maintained, but it's kinda stayed on an old stack of libraries so the underpinnings haven't changed much for years.
I've always been annoyed by not allowing two versions on the classpath. I still am not sure why Java doesn't want to allow it. With the new modules in Java 9+ they went as far as having a check to see if you were appending versions to the end to trick the module system in allowing it.
Two versions of a library? I thought it was allowed on the classpath, but you only got the first one?
Well, ya, I think that's true. But I meant more, that the JVM would be smart enough to know which class came from what versions and both could co-exist
Loading two different versions of a library that might end up passing references to data objects to each other (either directly, or indirectly via how they are used in the application) is pretty much a guaranteed recipe for disaster, I would think.
Well, they probably didnt want modules to become OSGi~like?
OSGi... shudder
There was an opportunity with Jigsaw. Since they add modules which is basically an official way to mention dependencies. If they had added versions to it. Then the JVM could have loaded both, solving the problem of Jar hell for good.
There are some issues with it also though. Most of the time, you want to force everything to use the latest mintor version, like the latest backward compatible version
So that the overall size stays small, and also to get most fixes and security patches.
What I personally would have wanted, is that it doesn't allow two versions, unless you explicitly whitelist them.
also, do you tho, if someone fails to adhere to semantic versioning and breaks compatibility in a point release, your system kills itself
Well, I think the idea is that. You decide to depend on the latest version. And you use it in your code. One of your dependencies unfortunately depends on an older version. So now you are forced to choose which one to actually use. If you force the new, it might break the lib expecting the old (in case the new was not backward compatible). If you force the old, you're stuck on old features. So, what I wanted was to give me the choice. I can go new, old or say just load both, let me use the new and the dependency can continue to use the old.
yeah but I was specifically wondering on having librariers, lets say a version 1.0.x
, which - accidentally - received an incompatible change in a bugfix release, like 1.0.7
if all your components suddely start to use the highest within a major, so 1.0.x
, your system dies. I think upgrading versions should always be a choice that needs a developer
I'm talking say you defined a dependency on X v1.2.4 And you also have a dependency on Y 2.3.1 But Y 2.3.1 uses X v0.5.3 You can not start a JVM instance in this case. It will either fail, or force the use of either 1.2.4 or 0.5.3 for both your code and Y's.
This is different then specifying a dependency on say X v1.2.N where every time you build it automatically pull in the latest minor version. That is risky, for what you described.
yeah right
The reason you can't start a JVM with both, is that the class names and package names conflict. And when your code says import com.x.Class the JVM doesn't know if it needs to load the class found in 0.5.3 or the one in 1.2.4
but with clever namespacing that would be solvable
Well, that's basically one of Rich's point: Never ever break backwards compatibility, and if you do, that's not a new version, that's a whole new package with a whole new name, namespace, git repo, etc.
He argues version upgrades should always be backward compatible. So you don't need SemVer, because that implies that it isn't always safe to upgrade.
well I think there is a middle ground there
At least that's what I understand from the talk. And then he goes on thinking about if this was true, then how could we detect backwards incompatible changes, and could we depend on functions instead of packages, and even have a Sha on them, so if the code path you depend on hasn't been touched, you know that it will still work, etc.
I need to watch that talk before I can judge
Haha, ya, its one of his more open ended. He doesn't really propose a concrete solution, just challenges the audience to think outside the box about the problem.
I have made enough mistakes programming to know that I want a way to break compat for private libraries
without forking the entire lib and start maintaining two
Oh, I don't think you would maintain two. You'd deprecate one, and the new one with a different name is now where all changes happen.
well with some form of versioned imports, versioned modules you know
I really want com.blab.blab.blab
but preferrably v2.0
yeah, but if half your apps are still depending on v1.2
you sometimes have to fix bugs in both your 1 and 2 branch
so you inevidable get 1.2.1 and 2.0.1
this grows linerally with your breaking changes
Ya, I mean the idea I think is more related to the problem I described. If the namespace is the same, you force people to upgrade. Where as if you change the namespace, new and old can co-exist.
yeah, I’d suggest solving it on the JVM level, Rich by forking your own libs right ^^
JVM level would be best, but the core JVM team have opposed the community about this quite strongly. Everyone wants it, but they don't want too.
I still recommend watching the talk. It's one of those that had grown on me more and more. At first I was like, what's wrong with SemVer! and slowly I'm thinking, this isn't dumb, maybe we do need something else.
I checked out clojure.java-time
. read the readme.md, Found this example: (local-date "MM/yyyy/dd" "09/2015/28")
. I use it like this: (local-date-time "yyyy-mm-dd hh:mm:ss" "2018-02-01 12:11:05")
. Don't know why it failed.
If Rich had given his talk years ago, I would have just introduced a new namespace to java.jdbc
not ever broken backward compatibility. Hindsight is 20/20.
@stardiviner because mm
and MM
mean different things.
yyyy-MM-dd hh:mm:ss
is probably what you want.
@seancorfield can you link that talk?
@lennart.buit This is the transcript https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/Spec_ulation.md
and the actual talk https://www.youtube.com/watch?v=oyLBGkS5ICk
Thank you!
@seancorfield I use (local-date-time "yyyy-MM-dd hh:mm:ss" "2018-02-01 12:11:05")
still failed. Seems related with this issue https://github.com/dm3/clojure.java-time/issues/11
So I have to switch to to clj-time
. I have converted date-time string to numbers with:
clojure
(clj-time.core/date-time
;; TODO: convert a LazySeq into all literal numbers.
(
(map #(Integer/parseInt %)
(str/split "2018-02-01 12:11:05" #"-|:| "))))
But in upper code snippet, I need to flatten a sequcne (2018 2 1 12 11 5)
into 018 2 1 12 11 5
. Don't know how.
Maybe there is simpler way to convert this date-time string. But don't know how.
I'm just reading through the change log for java.jdbc
, which is an interesting trip down memory lane:
0.2.3 -- 2012, June.
0.3.0 Alpha 1 -- 2013, April. Deprecates the old API (but keeps it in the namespace, and just adds the new functions).
0.3.0 Beta 1 -- 2013, November. Breaking change, moves deprecated API functions to new namespace (so user code can just change the require
and continue using the old API).
0.5.6 -- 2016, April. Announced that deprecated namespace would go away in 0.6.0.
0.6.0 Alpha 1 -- 2016, April. Removal of deprecated namespace.
0.6.0 (Gold) -- 2016, May. Only the new API remains.
I would have considered a four year migration plan to be slow enough. But Rich is right that purely additive change is better.
Is there any way I can run a REPL or basic IDE on Android? I have one but it's laughably old (clojure 1.2 ~ 1.4 ?)
Weird, I have one on 1.7 just called Clojure REPL. But it seems to no longer be on Google Play Store
The app on the Google Play Store may not support the latest versions of Android. The app I have runs clojure 1.7 and still seems to work with android version 9
clojurescript would be fine too if not
@stardiviner Use the parse
function in clj-time.format
instead of the split
/`map` stuff!
@stardiviner (local-date-time "2018-02-01T12:11:05")
would work.
(going back to clojure.java-time
)
It's kind of a pain that it expects the T
for ISO-8601 but it does work.
Ah, your format needed HH
instead of hh
:
boot.user=> (jt/local-date-time "yyyy-MM-dd HH:mm:ss" "2018-02-01 12:11:05")
#object[java.time.LocalDateTime 0x40c66b55 "2018-02-01T12:11:05"]
boot.user=>
Date/time formatting and parsing is horribly confusing -- blame Java.
(sorry, took me a while to get a REPL fired up on my Windows laptop -- given that WSL is broken in the latest Insider build and all of my Clojure dev stuff is done on Ubuntu via WSL normally)
(and it's bedtime here!)
Ah, looks like they fixed WSL in build 18277 (it was broken in 18272). So I'm rebooting for an updated build. Goodnight!
Anyone using rebel-readline
here?
I am unable to use doc
. It says unable to resolve symbol
Even spelling it out completely doesn't help.
(clojure.core/doc +)
says No such var: clojure.core/doc
Requiring core doesn't do it either. Same thing with source
as well.
user=> (require '[clojure.core :as core])
nil
user=> (core/doc +)
Syntax error compiling at (1:1).
No such var: core/doc
user=> (core/source +)
Syntax error compiling at (1:1).
No such var: core/source
user=>
doc is not in core
those functions are in clojure.repl
Oops! I thought clojure.core
is the only thing that's loaded and referred into the repl
most Clojure repls auto-refer a few extra functions like those (and clojure.pprint/pprint)
which is admittedly confusing
Maybe this is #architecture or #code-reviews but, it seems beginnery: I have a local cache of some xml files that I'll be processing in numerous ways. I wrote a read
function to create a map with some metadata gleaned from the file path, and the slurped, clojure.data.xml/parse-str
'd data. Next I want to do more processing of that content.