Fork me on GitHub

It seems Clojure install guide doesn't reall walk you through to how to install Java


And it appears however you install Java, the clj cli expects you to set JAVA_HOME


Does that seem correct? If someone has Clojure installed and working, thus I can safely assume that JAVA_HOME is set as well ?


You are asking if it is possible to set up an environment that runs Clojure without setting the JAVA_HOME env variable? I would guess it is possible, at least. I do not know whether it is common to do so.


I don't really install java, just download the jdk and set my bashrc to add the path to the bins


Hum, not exactly. I'm asking if setting up Clojure requires you to setup the JAVA_HOME environment variable.


clojure uses java, and java has to be on the path. I think java_home is a fallback used by many programs if java isn't available?


through installation I mean


I am attempting to try out a fresh install of Clojure on an Ubuntu Linux system to confirm, but I am pretty sure I can follow the Clojure getting started steps, installing a JDK in a way that does not assign a value to the JAVA_HOME env variable, and the clj and clojure commands will still work. Will report back what I find.


This is the code for the clojure command to find java:

# Find java executable
set +e
JAVA_CMD=$(type -p java)
set -e
if [[ ! -n "$JAVA_CMD" ]]; then
  if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
    >&2 echo "Couldn't find 'java'. Please set JAVA_HOME."
    exit 1


So it seems it first tries $(type -p java) which I do not know what that does. And if that didn't work, it tries to look for JAVA_HOME, I think that's correct, my bash isn't great


yeah, if you didn't install java via some installer, where it sets the path so it appears callable, then it falls back to the java_home. I ran into this long ago with intellij tools


Ok, type is a linux command, I'm guessing available on mac as well


On an Ubuntu 18.04 system where I had never installed Clojure before, but did have OpenJDK 11 installed via an Ubuntu/Debian package, and there was no JAVA_HOME variable assigned a value in the environment, I can follow the Linux install instructions on Clojure's get started page, and both clojure and clj commands run without complaint.


The output of type -p java on that system is /usr/bin/java , which is where the java executable is installed by the Ubuntu/Debian package


The bash command page describes what the type built-in command does.


buried within that many-pages-long man page 🙂


Ok cool. I could probably use that logic too. Though it seems there is also a way using java itself: java -XshowSettings:properties -version which prints a bunch of info, one of them being where java is installed


This assumes java executable is already in path, if that matters.


Ya, my install instructions will mention that. I need it in the path for other reasons already.


It is more common to expect JAVA_HOME to be defined and then figure out the path to java ($JAVA_HOME/bin/java).


But I am thinking about Windows more. For Linux and MacOS, java will be available in path already. In Windows, I often had to add java to path manually.


Ya, I think I remember that for Windows. I might add a fallback to JAVA_HOME in the future, but I think it wouldn't be too bad to ask to add java to the path. Especially in Emacs, you can add stuff to your path within your emacs config as well, so that might be a better way to go.


Seems more reliable, I might go with that


If you are assuming bash exists, then type command exists, too.


I think that will work on windows as well


Wndows without WSL tends to be enough different from macOS/Linux that it often needs it own way of doing things.


ya, I don't know how much I should bother for windows. Do people even use Emacs on windows 😛


I'm at least one 😊


Haha, well, I'd like to support it. And I'll try, not sure how to test it though


I use Emacs via WSL.


Ok, through WSL I think that should work the same as linux so shouldn't be an issue


Yes, it's the same as Linux.


I have before, but not recently. It exists.


If you do not polish/test/support Windows, you will not be alone 🙂

Eccentric J04:04:09

Is there a simple way to have clj install the deps and do nothing else?


clj -Spath IIRC

Eccentric J05:04:30

Awesome, thanks!


How can I debug "Error building classpath. Could not find artifact ... in central"? I'd like to know what the resolved dependency is that doesn't have its own dependency in central.


Found it manually, but it would still be nice to know if there's any other way.


Anyone knows what is this error when using aws-cli?

(def s3 (aws/client {:api :s3}))
(aws/validate-requests s3 true)

(aws/invoke s3 {:op :ListBuckets})

{:cognitect.anomalies/category :cognitect.anomalies/fault,
 :cognitect.anomalies/message nil,
  :cause nil
  [{:type java.nio.channels.ClosedChannelException
    :message nil
    :at [.FillInterest onClose "" 150]}]
  [[.FillInterest onClose "" 150]
   [.AbstractEndPoint onClose "" 354]
   [.ChannelEndPoint onClose "" 216]
   [.AbstractEndPoint doOnClose "" 225]
   [.AbstractEndPoint close "" 192]
   [.AbstractEndPoint close "" 175]
   [.ssl.SslConnection$DecryptedEndPoint doClose "" 1132]
   [.AbstractEndPoint doOnClose "" 220]
   [.AbstractEndPoint close "" 192]
   [.ssl.SslConnection$DecryptedEndPoint onFillable "" 425]
   [.ssl.SslConnection onFillable "" 305]
   [.ssl.SslConnection$2 succeeded "" 159]
   [.FillInterest fillable "" 103]
   [.ChannelEndPoint$2 run "" 118]
   [org.eclipse.jetty.util.thread.strategy.EatWhatYouKill runTask "" 336]
   [org.eclipse.jetty.util.thread.strategy.EatWhatYouKill doProduce "" 313]
   [org.eclipse.jetty.util.thread.strategy.EatWhatYouKill tryProduce "" 171]
   [org.eclipse.jetty.util.thread.strategy.EatWhatYouKill run "" 129]
   [org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread run "" 388]
   [org.eclipse.jetty.util.thread.QueuedThreadPool runJob "" 806]
   [org.eclipse.jetty.util.thread.QueuedThreadPool$Runner run "" 938]
   [java.lang.Thread run "" 834]]}}


I think it might be some kind of SSL issue? But I have no idea how to solve it. I can list the buckets using aws-cli on the command line without issue


if I have a fully qualified symbol, how do I get a non-qualified symbol? I want to strip the namespace off.


Whatever you’re doing here, it’s almost certainly not what you want.


You’re taking something that’s very specific and has well-defined semantics and turning it into something unspecific with loose semantics.


I’ve only ever seen people do this because they, they programmer, wanted things a certain way.


but I want the output as a symbol


i guess not this?

(def a 'clojure.string/split)
(symbol (name a))


that works 🙂


I think that's the most straightforward way too lol as Symbol has

final String ns;
final String name; 
so (unless I'm forgetting some hack) there's no mutating the ns (EDIT: not that anyone would want to anyways, I'm just diving into 'what's the most hypothetically direct you could get with this'), you end up needing to create a new symbol. The fastest hypothetical situation one could hope for is just to directly get name , and directly call some sort of simple Symbol(string name) constructor Well, name in this case, name indeed will call
public String getName(){
	return name;
and (symbol ..) will call
static public Symbol intern(String nsname){
	int i = nsname.indexOf('/');
	if(i == -1 || nsname.equals("/"))
		return new Symbol(null, nsname);
		return new Symbol(nsname.substring(0, i), nsname.substring(i + 1));
Granted, there's some extra checks there but there is no public constructor to directly give you Symbol(null,name) I don't believe, so that's your most direct constructor for this. And technically, yeah, there's some extra checks in Clojure's symbol and name that could be bypassed if you really wanted to by using java interop (assuming you know the type of everything, as that's the extra checks Clojure does; both symbol and name do type checks first and dispatch on that type of their argument to create the symbol or get the name, respectively) but the idea is the same; getting that new symbol will be some combination of grabbing the name , and passing it to a Symbol constructor, as done here. ...I have no idea why I'd dive into this, as you already have your answer and this is a small thing ahahahah I apologize. This sort of thing just interests me, as I just like when I can establish the 'limits' on something, and use that to feel comfortable knowing 'well, it doesn't really get better than this, so no matter what happens I don't feel like I can improve this solution, I can rest knowing I'm done thinking about this "forever"' Especially as someone who can end up bikeshedding too much without that sort of closure


fwiw, i also looked at the file to see if there might not be some interop / obvious better way 🙂


It’s not a single fn call for a reason, I think.


You’re taking something that’s very specific and has well-defined semantics and turning it into something unspecific with loose semantics.


It’s a good recipe for wasting time.


Hi, is it possible to have a catch all declaration in a compojure route? Something like: (POST "/api/invoke/:rest-of-thing/" [rest-of-thing req] (invoke-post rest-of-thing req)) where rest-of-thingcan be any uri like foo/bar/baz or /buz/3/5/id?


Nevermind, I just found the wildcard function. Just adding a * to the route will behave like I want: /api/invoke/* will match all routes that start with /api/invoke/


I’m testing a function that uses a core.async channel. For the tests, I wrote a simple timeout-chan function. Here is a simple version of its implementation:

(let [in-chan  (a/chan)]
    (a/go (a/<! (a/timeout 1000))
          (a/close! in-chan)
  (apply function-using-async in-chan))
Ultimately: keep the channel open long enough for me to pass things in and than close it. The problem: If you pass n items to the channel, and want to be sure n items get through before the channel closes, the tests might pass sometimes and not other times Q: how are people handling scenarios like this?


relying on timeouts doesn’t seem what you want. what kind of process are you trying to test?


I have a consumer function like

(defn consumer-fn [chan]
  ; take from chan 
  ; increment counter
  ; transform val from chan and return it
My goal is to test that the increment counter step in the above is working as expected


you shouldn’t need a timeout to check to if that’s working


for the test, you could use something like poll!


from a design perspective, it seems like consumer-fn might be doing too many things


typically, you try to separate the “flow” of your program from the “logic” of your program


which makes things easier to test, but more importantly, makes your system easier to reason about and easier to change


specifically, I would consider having your consumer-fn not take from a channel and then return a value


either take a value and return a value or take a channel and return a channel


preferably, taking a value and returning a value


> either take a value and return a value or take a channel and return a channel This is a good point, one which I am keen to look into.


I’m currently trying to understand poll! a little better


I guess poll! would make more sense if you’re taking a channel and returning a channel*


but since you’re returning a value, it might not be the right fit


if you want to put a certain number of items onto a channel, then onto-chan might make sense. you pass it a coll, and once all of the items from the coll have been put on the channel it will close the channel.


For clarification, if I want the channel to close after n items have been taken off the channel, would it be better to use to-chan?


to-chan and onto-chan deal with putting items onto a channel. they won’t know about items being taken off of a channel


So in the case of where it says that: > closing when exhausted What does “exhausted” mean in this scenario?


pretty sure that means if the sequence passed to to-chan ends, it closes the channel


but the channel isn’t guaranteed to be closed, because you could potentially pass an infinite sequence to to-chan. (eg. (to-chan (range)))


if you pass a channel tht has no buffer into onto-chan, then the channel that is returned will only be closed once all of the items have been received


since the channel will be a synchronization point without a buffer


i guess it’s worth pointing out that there’s a subtle distinction between 1. putting n items on a channel and then closing the channel 2. closing a channel after n items have been taken off the channel as @U1XTUTPMY alludes to, the difference is most obvious when you have a channel without a buffer


I have seen this pattern used in the wild:

(let [v _] (async/alts!! [chan (async/timeout 1000)]))
  (assert (nil? v))
  (is (= 5 (count v)))
  ; ...other assertions
If I understand the premise here correctly, this is just keeping the channel open long enough to give our items time to pass through the channel :thinking_face:


timeouts aren’t generally used for giving time for items to pass through a channel


they’re typically used if there is some time constraint that can’t be met


also, in a distributed system, you may send a request and the only way to detect failure might be to have a timeout.


> they’re typically used if there is some time constraint that can’t be met Do you have an example off hand of a scenario that required this? Just trying to better understand your suggestion :thinking_face:


this is the classic example of using timeout (and some of the other goodies)

(defn search [query]
  (let [c (chan)
        t (timeout 80)]
    (go (>! c (<! (fastest query web1 web2))))
    (go (>! c (<! (fastest query image1 image2))))
    (go (>! c (<! (fastest query video1 video2))))
    (go (loop [i 0
               ret []]
          (if (= i 3)
	    (recur (inc i)
	           (conj ret (alt! [c t] ([v] v)))))))))


basically, the goal is to return a response in 80ms or less.


if all the results have returned, don’t wait for the timeout, just return, otherwise, wait up to 80ms and return any results that are available


Are classes not valid keys in a case?


No, they are not compile time constants


(case Integer Keyword "keyword" Integer "integer") 
=> Execution error (IllegalArgumentException) at spectrum.repl/eval27661 (form-init14549903441455335896.clj:514).
No matching clause: class java.lang.Integer


they are not. case promises constant time dispatch and I don’t think that’s possible with classes


Hum, I think it might not, but it's also about the equality check here maybe


Integer gets evaluated, but then it gets compared to the non evaluated clauses


I don't think the reader can read a literal into a class that would make it equal, so probably not possible.


from the docs:

Unlike cond and condp, case does a constant-time dispatch, the
  clauses are not considered sequentially


But maybe if you did (str Integer) and your clauses were strings?


the expression gets evaluated, but the test constants do not


also from the docs:

The test-constants are not evaluated. They must be compile-time
  literals, and need not be quoted.  If the expression is equal to a
  test-constant, the corresponding result-expr is returned


Ya that's what I meant. So if you did (case (str Integer) ("java.lang.Integer" ...))


It might work


But there might also be a literal way to represent the class which I don't know off. Basically the evaluated result of expression gets compared to the read value of the clauses


maybe. you might have to do (.getName Integer) , but you’re probably better off using something other than case at that point


(get {Keyword "keyword" Integer "integer"} Integer) 


What I'm not sure is if tagged literal are possible targets for case


Tagged literals are a reader form, not a type


They are read into objects


I guess my question is, say I do a case on some custom object. Like (case (Person. "John") (#person "John" "John")) But I have a tagged literal for creating object of type Person. Would this now work with case? Since my clause is read into a Person object and my expression returns a Person object, would both object now be compared for equality?


No this will not work


Do we know why? Is it that the reader literal doesn't happen before the case macro? Or is it because the object returned by the literal will then be passed to the macro in a printed form?


No, person objects are not compile time constants


They cannot be stored in bytecode


Oh, does case compile to Java switch ?


Anyhow, I see what you mean, it has to be a valid byte code literal


It compiles to tableswitch bytecode


So how is Symbol and Keyword handled? To they compile to strings in the byte code for the comparison?


There is a lot of code to implement case - it is a nontrivial transformation and involves both a macro doing about half the work and the compiler doing more


I don’t recall all of the details


I see, I hadn't realized case* was a special form


@arohner I believe those “classes” are resolved as symbols.


(case 'Integer
  Integer :int
  String :str)


In Clojure, you can’t refer to classes as primitives – they’re referred to through symbols.

👍 4

So, to answer your question: I don’t think use case to dispatch as you would want.


Thanks. I’ve made it work with symbols of classnames


Curious what you did.


(let [c Integer]
  (case (symbol (.getSimpleName c))
    Integer :int
    String :str))


Classes are not constants (or unique - they are per-classloader) so you can’t use them as cases


I usually get the name of the class and dispatch on that string


Yeah. But I assume this would often be faster using a protocol. (I have zero data to back that up.)


Yeah, depends exactly what you’re doing


Whats the equivalent of a "rest" let destructure for map destructuring? For example, for list its simple: (let [[x & rest] [:a :b :c]] (println rest)) This prints (:b :c) as expected


However, I can't seem to find how to do it for map destructuring


so that: (let [{x :a & rest} {:a :a :b :b :c :c}] (println rest)) returns {:b :b :c :c}


Doesn't seem to work 😞


What do you want back?


I want the object thats left after remove :a from the original map (ie the rest)


That’s not how it works


so {:a :a :b :b :c :c} (pick :a out and return rest operation) => {:b :b :c :c}


That’s not a thing


You can dissoc :a from the full map in a second binding


ah gotcha, thats what I need thanks!


Hi! I have a weird compile error: > Syntax error (IllegalArgumentException) compiling . at (src/../run.clj:7:28). > Unable to resolve classname: [email protected] in this code

(Math/round (months-between-approx from to))
When I remove the call to Math/round, it is OK. The fn is:
(defn ^double months-between-approx [^Instant i1 ^Instant i2] (/ .. 30.5))
Why? Is there a problem with the ^double type hint? But it works until I try to round it.... Thank you!!!


Move ^double after the function name (so it's in front of the arglist).


Putting metadata ahead of the function name causes it to be evaluated (to the clojure.core/double function) and then added as a :tag I think. Putting it before the arglists will do what you want.


^ @holyjak

user=> (defn ^double foo [] 1.0)
user=> (+ 1 (foo))
Syntax error (IllegalArgumentException) compiling . at (REPL:1:1).
Unable to resolve classname: [email protected]
user=> (defn foo ^double [] 1.0)
user=> (+ 1 (foo))


Thanks a lot! Frankly, I never remember where to put the return value tag. My reasoning was that if it was before the arglist, it would be metadata on the arglist, not on the function. I should have just checked the docs 😅


And metadata on the arglist is exactly where you want it 🙂


user=> (defn ^double foo [] 1.0)
user=> (-> #'foo meta)
{:tag #object[clojure.core$double 0x187e2f02 "[email protected]"], :arglists ([]), :line 1, :column 1, :file "NO_SOURCE_PATH", :name foo, :ns #object[clojure.lang.Namespace 0x5b5babb "user"]}
user=> (defn foo ^double [] 1.0)
user=> (-> #'foo meta)
{:arglists ([]), :line 3, :column 1, :file "NO_SOURCE_PATH", :name foo, :ns #object[clojure.lang.Namespace 0x5b5babb "user"]}
user=> (-> #'foo meta :arglists first meta)
{:tag double}


For a lot of things, it will work before the function name -- when the metadata is the same evaluated as unevaluated. And of course there are situations where you want the metadata on the function instead of the arglist.

❤️ 4
👍 4
Chris K23:04:10

Just found this: clojure bot for eval clojure code on slack. Maybe we can have this on our group?


No, sorry, the Admin team are not granting tokens/integrations for any additional programs.


The restrictions on the free plan mean that it would be very hard for us to grant integrations to some programs but then have to deny so many others.


(and, to be honest, most remote code bots are open to all sorts of abuse, including causing them to spam channels and generally be rather annoying)


And, hey, every Clojure developer already has at least one running REPL on hand to try out code, right?

Chris K00:04:21

haha yeah It wasn't like I wanted to have this on, but in case the admins didnt' know about this


Hah, trust me, over the years we've been running this, we've seen most everything 🙂

Chris K00:04:24

yep that's true