This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # 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?
@stardiviner Incanter requires a very old version of
java.jdbc -- it hasn't been updated to work with any recent versions.
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
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.
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.
@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 😐
clj-time, you can use
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.
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?
Hum, I wonder in this case, had you changed the name of the lib, then both versions could have co-existed on the classpath
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
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.
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
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.
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
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.
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.
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
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.
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
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.
@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.
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
@stardiviner Use the
parse function in
clj-time.format instead of the
Ah, your format needed
HH instead of
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=>
(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)
Ah, looks like they fixed WSL in build 18277 (it was broken in 18272). So I'm rebooting for an updated build. Goodnight!
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
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=>
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)
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.
When I write functions that do more parsing, what's the good signature?
- they should take a file,
read them into maps, do more parsing of the content, return an updated map?
- they should take the pre-`read` file, i.e., the pre-parsed maps with metadata?