Fork me on GitHub

(This is likely a cljs, cljsbuild or version clash problem, but it was triggered by moving to clojure 1.9.0-beta1, so posting here)... Moving to the new Clojure beta caused cljsbuild to fail with:

Sep 19, 2017 1:46:59 PM println
SEVERE: /home/deg/Documents/git/projects/trilystro/target/cljsbuild-compiler-1/cljs/core.js:3579: ERROR - Parse error. primary expression expected
case ##Inf:
This is in the function cljs.core/hash


hi guys, what’s your preferred dsl/library for interacting with SQL?

Alex Miller (Clojure team)12:09:25

@deg This is a known thing re cljs - might ask over in #clojurescript or #cljs-dev on status


Thx, will do.


@alexmiller - Yup, @mfikes had the answer on #cljs-dev. But, looks like this will bite all ClojureScript projects that try the beta, until ClojureScript is updated to match. Can a warning be added to the beta release notes, meanwhile?

Garrett Hopper15:09:03

@sfalcon I personally prefer using Yesql over a Clojure DSL for SQL. It allows you to write everything in actual sql files and gain all SQL tooling from that.


will have a look thank you

Garrett Hopper15:09:30

I was just looking into that the other day @bostonaholic. What's the reloading situation like?


HoneySQL gave us the advantage of being able to programmatically build up SQL queries. Like have a base one and then add a join onto that and a different where clause to filter and such. Not sure how you'd do that with YesQL

Garrett Hopper15:09:39

Any opinions on tools.namespace reloading (possibly reloaded.repl) vs plain repl reevaluation? I'm using reloaded.repl at the moment, but I'm starting to feel as if going back to plain repl evaluation might be simpler. Though I'm not sure if changed to my ring handler would be picked up without restarting the server.


interesting, so the trend is to use libraries that use SQL as data structures as opposed to what Korma (for example) does


I used Korma before but something about the DSL feels off to me, will have a look at those libraries as well thank you


@sfalcon @michaeldrogalis elaborates a bit more on this Korma vs HoneySQL (data-centric vs otherwise) on the (very nice) Clojure Remote keynote: Thanks for that, mr. Drogalis!


I'm quite confused about this example...I have one function that appears to return a long, yet when I call inc (or any other numerical function) on it the compiler tells me it's an Object: What am I missing here?

Alex Miller (Clojure team)17:09:20

by default the params and return vals of all functions are of type Object

Alex Miller (Clojure team)17:09:36

you’ll need to type hint the return to get something different

Alex Miller (Clojure team)17:09:44

(defn foo ^long [String string] ...)


Ah, that's a simple answer. Thanks, Alex.

Alex Miller (Clojure team)17:09:54

the inner loop of foo will used boxed longs as written now, but that could be rewritten with loop/recur to use primitive longs


type will also always box the object so it will never return a primitive type


Oh, interesting. I always default to thinking reduce would be more performant through using the Iterator interface.


@bronsa, that's not true


i'm talking about Long vs long


You can see in this example that it returns a Java long. What am I misunderstanding?


primitive means a primitive long type, java.lang.Long is a boxed object, that's the distinction i was making


I think you mean Clojure long vs. Java long...


;; => (type (foo "baz"))
;; => java.lang.Long


notice the capital L in your output


The capital L refers to a boxed long?


there's no such thing as a clojure long


@bronsa sorry, you're right about that. I for some reason thought there was clojure.lang.long


the jvm has a primitive long type (which is not an object type) and a boxed class java.lang.Long, type will never return long even if a function returns a primitive long, because type only works on objects and thus will cause a primitive value to be boxed


Gotcha. And I assume class and instance? are the same?


If type can't give you the correct type of primitives, is there anything that can?


Well, :warn-on-boxed will.


it would have to be a macro that interopped with the compiler, or a compiler feature


That's a compiler feature, though.


no function can because it would have to accept both objects and primitive values, and the clojure compiler would cause values to be either boxed or unboxed as it deems appropriate, so not retaining the real type


@sophiago yeah, but it doesn't do what @didibus was asking


A little annoying when you want to validate you're not using boxing


if that's all that you care about than as @sophiago said, warn-on-boxed/`warn-on-reflection`


@sophiago what are you calling a compiler feature? I get it now, never mind


@didibus (set! *unchecked-math* :warn-on-boxed)


Ya, I guess.


And whats with this:

(defn ^long foo [x] (int x))
(type (foo 12))
=> java.lang.Integer


that's not ac correct type hint


move it from foo to the argvec


(defn foo ^long [..


Damn, all this time, using the wrong syntax lol


it's only wrong for primitive type hints


but I suggest using it even for non primitive type hints


Primitive type hints have a different syntax?


both primitive and non primitive can work in either place


but because the metadata on var names will get evaluated, you'd have to (defn ^{:tag 'long} foo .. (i.e. explicitly quoting it)


otherwise you're tagging foo with the value of the long function rather than with the long symbol

Alex Miller (Clojure team)18:09:22

var meta is evaluated. Function type hints are not.


moreover, the compiler will not emit primitive versions of the function if you tag the var meta rather than the argvec

Alex Miller (Clojure team)18:09:24

I think the takeaway is that you should nearly always type hint the function return, not the var


@alexmiller sorry i''m not understanding, are you saying what I've said is wrong? because it isn't :)


s/nearly// IMO

Alex Miller (Clojure team)18:09:40

no, I’m trying to agree with you :)


misunderstood what you meant by "function type hints" then


Hum, so would the resulting cast be around the var access instead of the function return?

Alex Miller (Clojure team)18:09:12

I meant “the type hints interpreted by defn”


yep gotcha


Actually, I'm definitly a bit confused about type hints. I've noticed somtimes you can type hint wrongly, and all works, no warnings or errors, sometimes you get runtime type errors.


what happens in (defn ^{:tag 'long} foo ..) case is that foo returns an Object and at callsite it might get unboxed as a long, if the compiler deems it useful/necessary


@didibus yeah, this (afaict) is because of clojure's GIGO attitude. I don't particularly like it in this case (I think we could safely warn at compiler time) but it's gotten a bit better than it used to be

Alex Miller (Clojure team)18:09:36

it’s not GIGO, it’s because it’s a hint, and the hint might be wrong

Alex Miller (Clojure team)18:09:58

you might not know it’s wrong till runtime


I'd consider it GIGO when the type hint can't ever be right, not to warn


So does a wrong hint detected by the compiler reverts it back to using reflection?

Alex Miller (Clojure team)18:09:10

so you can fall back to Object


well, if something is definitely not a type/class at compile time then it's not a type hint


I can't see how the compiler accepting a funcntion as at type hint w/o warning/erroring out is not GIGO

Alex Miller (Clojure team)18:09:56

I’m in full support of that being an error


patch incoming then :)


(gah, I can't write function anymore apparently, fifth time I write funcntion)


(defn foo ^String [x] (int x))
This still works, no warning or error.


that is not the case I'm arguing should warn


that is a validly formed type hint, it's just a nonsensical one


what if int got redefed to return a string


then that hint would be correct at some point

Alex Miller (Clojure team)18:09:20

it’s the (defn ^long foo ...) one


it’s more like (defn foo ^clojure.string/join [x] (int x)) - the hint is a function not a type


Right, well ya, that I agree should even more so be warned or even error


But, about the other one, I understand maybe it compiling, but why does it work once its compiled to jvm byte code?


depends on your definition of working!


once you start doing interop, the compiler will assume that type hint to be correct


and will dispatch to String methods


if it can't match one, it will use reflection

Alex Miller (Clojure team)18:09:01

@bronsa patch welcome for or whatever other jira is out there for this problem


but if, say, Integer and String had 2 methods with identical signatures, than that would fail at runtime


I mean, in java you can't type the return to string and have it return int. So does clojure ignore the hint amd still returns Object?


type hints are not static types


the compiler enforces type hints only if/when it needs to


and for function return types, it only enforces them when that value is used in an interop form


e.g. (.foo (bar)) will enforce the type hint on the return type of bar (at callsite of foo!) but (identity (bar)) won't


because it would be useless


type hints are only to prevent reflection (and in some cases, boxing), they're not to enforce static types


and are not guaranteed to cast/box/unbox


I see, okay, that explains I think the inconsistency of wrongly typed type hints I've seen. It'll fail at runtime with java interop.


an example of this behaviour is

user=> (deftype Foo [a])
user=> (deftype Bar [a])
user=> (defn ^Foo x [] (Bar. 1))
user=> (x)
#object[user.Bar 0x4983159f "[email protected]"]
user=> (.a (x))
ClassCastException user.Bar cannot be cast to user.Foo  user/eval158 (NO_SOURCE_FILE:8)


the incorrect type hint doesn't cause (x) to fail, it causes host interop on (x) to fail


Whats the idea of not enforcing the hint to always box/unbox or cast ? I don't see a negative in enforcing, except you'd know quicker that you hinted it wrong


well, the short answer is: type hints are not type assertions, the long(er) answer is: the compiler might now better or enforcing could affect redefinition


and if you want enforcing I guess spec is better suited at that


(defn foo ^String [x] (int x))
(type (foo 12))
Id expect this to be equal to
Object foo(Object x) { return (String)((int) x); }
and fail at the cast at runtime


no, again, type hints are neither type assertions nor type casts


they sometimes act like either, but at the discretion of the compiler


to do what you want, use (cast String (int x))


I'm not talking static checks. But runtime type errors. Ok, ya I understand, so they're unpredictable and mostly for interop and certain unboxing situation.


as to enforcing at return type vs callsite -- I believe it's a performance compromise of sorts


to enforce at return type would require emitting checkcasts at every callsite


vs only when needed


I understand how they work now. Thank you.


I guess I'll restrict their usage to only when the compiler warns for boxing or needs it to dispatch.


that is when you should be using them, yes


Some people use them as programmer hints, like documentation. But that had mislead me, because sometimes the hint is wrong, yet all works. I see that's a pretty bad use of them now. Spec is the way to go.


Ha, had to step away for a phone call. Glad to see this discussion continuing 🙂


I actually had a related question. Is anyone familiar with Zach Tellman's primitive-math library? I'm wondering exactly how it differs from using unchecked-math in clojure.core. I'm not sure how long the latter has been around, but was under the assumption that library was still useful for providing reflection warnings for math operations.

Alex Miller (Clojure team)19:09:08

The warn-on-boxed stuff was kind of done about the same time as primitive-math (independently). The warn-on-boxed stuff will cover you in most situations, but it’s not perfect and won’t catch all cases (particularly in return paths). I have not looked at primitive-math closely enough to know for sure, but it may be useful in some cases that are not well-caught by warn-on-boxed.

Alex Miller (Clojure team)19:09:19

I have nothing against it :) (but there is some overlap)


That's pretty much exactly what I told someone in a GitHub issue who was trying to tell me they're exactly the same (with more color that reflection could occur in the return paths) so happy to know I was mostly right 🙂


Oh, I suppose I should also mention that afaik primitive-math is more comprehensive. For example, it includes equality and bitwise operators.


@alexmiller Hi! I was just reading you blogpost and tried to use no.disassemble with boot but requiring the dependency doesn’t seem to be enough (some jvm flag is missing I think, looking a the lein plugin)


Could you guide me on how to set it up? Or is there another tool I can use for the same purpose?


it requires an instrumenting agent at startup


lein-disassemble is an easy @hmaurer then lein repl then (require '[no.disassemble :refer [disassemble]])


@reborg I would like to use it with Boot


actually, could this cause an issue with boot’s approach of loading dependencies after the JVM is started? @seancorfield


since I would need to pass the agent flag to the JVM that will be running boot


You'd specify the Java agent option via BOOT_JVM_OPTIONS. Pass -javaagent:/path/to/the/nodisassemble.jar


(you'd need to run Boot at least once without that in order to download the JAR to .m2/repository and then you'd have the (long) path to the JAR)


@seancorfield thanks. So something like this? BOOT_JVM_OPTIONS='-javaagent:~/.m2/repository/nodisassemble/nodisassemble/0.1.3/nodisassemble-0.1.3.jar'


Sorry, yet another boxing question... Are there best practices for converting characters to numbers? Using the primitive-math casting operators throws an error so I have to switch to those from clojure.core. Not sure if this is something to log an issue with over the primitive-math casts or whether it falls under one of those cases where I'm just not being warned about reflection when using the core versions.


@hmaurer Example

(! 687)-> BOOT_JVM_OPTIONS="-javaagent:/Users/sean/.m2/repository/nodisassemble/nodisassemble/0.1.3/nodisassemble-0.1.3.jar" boot -d nodisassemble repl
Initializing NoDisassemble Transformer
boot.user=> (require 'no.disassemble)
boot.user=> (in-ns 'no.disassemble)
#object[clojure.lang.Namespace 0x5c26a243 "no.disassemble"]
no.disassemble=>  (println (disassemble (fn [])))
//  (version 1.5 : 49.0, super bit)
public final class no.disassemble$eval2043$fn__2044 extends clojure.lang.AFunction {
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public disassemble$eval2043$fn__2044();


I think you'll need the full path, not ~


@seancorfield yep I just realised that. It works now


Unrelated question (well, related to the discussion we had earlier on uberjars): how do you usually deploy boot applications to production?


I love Boot for experimenting with new libraries 🙂 No need for a project folder or anything 🙂


Yes it’s brilliant!


Mostly we build uberjars. @alexmiller's comment about them being "evil" notwithstanding, it's the most convenient way so we only need Java and the JAR file on the target system.


(that said, we still also deploy .clj source files since we use them inside other apps that predates our uberjar approach)


Could you imagine a jar downloading its dependencies on startup using boot? Or am I misunderstanding something?


Don't do that, even if you could. Try to have reproducible builds, which leaves zero chance of anything having differed. Better to resolve all things beforehand, and then copy those in one go to your hosts. That's the only way to be 100% sure all hosts are perfectly in sync.


So we still have boot repl available on production too (and boot whatever-task stuff as well)


@hmaurer What do you gain over having the source of the project there and just doing boot run or whatever?


What would that JAR be?


Nothing it seems


I should have asked: would it make sense to use boot run from source in production


Define "make sense". There are pros and cons 🙂


What would be the cons? 🙂


The cons include deploying all your source etc rather than just a single file (which may make your build process more complex); requiring Boot be installed on all your servers; requiring that your servers can access Maven Central and Clojars at all times; ...


That last one was enough for us to run our own Archiva instance acting as a caching proxy for Clojars (before Clojars got the nice, new, redundant CDN implementation for the repo) and all of those together with a desire to move processes to Docker pushed us to use uberjars instead.


(that said, we haven't actually made the move to Docker yet)


@alexmiller sorry to ping you, but wrt to my last question do you know whether something like (map (comp long char) "foo") is one of those cases where the compiler doesn't throw an error on boxing? I suspect this may be the case since all the primitive-math version of long does is call unchecked-long from clojure.core, which throws an error where as cc's long does not.

Alex Miller (Clojure team)20:09:45

anything you do with seq functions will only use objects


just curious, what does (comp long char) accomplish that long doesn’t?

Alex Miller (Clojure team)20:09:05

I don’t think it will do anything different


Yeah, I just realized since I used map to convert from a string I should probably mention I get the same erorr with just (primitive-math/long \a) whereas (long \a) doesn't throw a boxing warning.

Alex Miller (Clojure team)20:09:31

the boxed warnings will only happen if you’re calling a numeric operation

Alex Miller (Clojure team)20:09:41

and map is not one of those


My clarification was meant to say it happens outside of being passed to a higher order function.


@noisesmith I'm using Zach Tellman's primitive-math library so for that long you do actually need to cast to a char first


but it is a char already?

Alex Miller (Clojure team)20:09:44

long is handled in RT, so it’s not caught by the warnings in Numbers


I assume it has to do, again, with being an argument to map.


@alexmiller thank you. That's exactly what I needed to know.

Alex Miller (Clojure team)20:09:44

I think you’re going to end up passing a Character object into RT.longCast(Object)


so if you just use (map long "abc") with clojure.core/long it just works, but you need (comp long char) instead because of primitive-math?

Alex Miller (Clojure team)20:09:17

none of these options are going to giving you a sequence of primitive values regardless, so I’m not sure it really matters


Yes, that's what I was trying to determine.


yeah- you can’t put a primitive on the stack, so if you are using map it’s boxed, guaranteed


Sorry, I just provided a bad example to begin with, but got the answer I needed.

Alex Miller (Clojure team)20:09:18

it’s hard to recommend something different, b/c it matters a lot what you’re going to do with the result


(I guess you could make an array transducing context and use a map transducer - or would the map transducer still force the boxing?

Alex Miller (Clojure team)20:09:54

(although we’ve talked about primtiive transducing options)

Alex Miller (Clojure team)20:09:07

if your goal is to produce a collection, you could either use a Java long[] or a primitive vector of longs. In general, the latter tends to force boxing on use anyways (through the vector APIs) so you primarily get only memory savings.


Hmm. Does this "primitive transducing" discussion have any bearing outside of a higher-order context? Before Justin brought that up I assumed I was stuck with boxing for chars, but I'm not sure whether you're suggesting something from the java.lang.Character.

Alex Miller (Clojure team)20:09:15

generally, if I’m trying to super optimize all this stuff, I’d use long-array or maybe int-array here (depends on whether you just care about ascii or full unicode)

Alex Miller (Clojure team)20:09:34

this is a particularly tricky area of Java


Right. I'm not going so far with optimization here to use unboxed sequences (and have found vector-of to be almost always useless for the reason you mentioned).



user=> (doto 'primitive-math require in-ns)
primitive-math=> (long \a)

ClassCastException java.lang.Character cannot be cast to java.lang.Number  clojure.lang.RT.uncheckedLongCast (
primitive-math=> (long (char \a))

ClassCastException java.lang.Character cannot be cast to java.lang.Number  clojure.lang.RT.uncheckedLongCast (
primitive-math=> (map (comp long char) "hello")

ClassCastException java.lang.Character cannot be cast to java.lang.Number  clojure.lang.RT.uncheckedLongCast (


I’m sure I’m doing something silly here


Your first two cases were the behavior I was asking about here. The third one for some reason works for me.


No. Scratch that. You're correct on all counts.


There is also Long/parseLong, but that only works for numerical strings. Similar to (map #(Character/digit %) "123")


Err, sort of similar. You get the point.


@sophiago it seems like without using clojure.core/long etc. the easiest way to get a number from a char in a string is

=> (Character/codePointAt "foo" 0)


but that may be doing something wrong with unicode contexts



=> (Character/codePointAt "☃" 0)


This is for hashes so I'm fine with just ascii


Oh, it doesn't seem to work in higher-order functions, e.g. (map-indexed #(Character/codePointAt %2 %1) "foo") so I'd need to use loop/recur. Plus I'm not even sure it saves me from boxing wrt to the individual elements.


the boxing would depend on what you do in your consuming function, and I would use (map #(f (Character/codePointAt s %)) (range (count s))) - if f knows how to use a numeric value unboxed, it would work I bet


primitive-math=> (let [s "hello, world!"] (map #(inc ^int (Character/codePointAt s %)) (range (count s))))
(105 102 109 109 112 45 33 120 112 115 109 101 34)


Oh, duh 😛


Thanks. I'll compare. I sort of suspect it's not worth it since I'm just dumping them into a sequence, but will test.


@noisesmith postmortem: worth adding a helper function for, but not significantly faster for any use cases and slower for some. Regardless, thanks for the tip.


If you deploy an uberjar, you can still have a REPL in production of course (start it with the Socket REPL Server options) -- or just run the uberjar with no options (we don't AOT, and we set :main to clojure.main so an uberjar can run clojure.main to get a REPL -- or we can use -m my.namespace to run the -main in that namespace).


@seancorfield can you start a repl in a running production system if you didn’t start the uberjar with the socket repl server option?


there’s a namespace to use to start the socket server by hand, and of course you can use to make an nrepl server instead


@noisesmith can you plug into a running jvm like that? I am not familiar with how those things work


The clojure process can call the functions to start a server. If you really need to monkey your way in, a debug connection could be used to access clojure via interop from the java side and make it do so I guess…


In the past we've had a way to tell a process to start a REPL (and to stop it again) so we can have a REPL open when we need it.


(that has varied depending on the process)


Mostly, for debugging, we'd just restart a process with the socket REPL server JVM options if we needed that. Or just start a standalone REPL while ssh'd into the server, for local interactions.


(running a REPL server in a live, production process comes with all sorts of caveats about security and risk and so on and so forth... we have -- occasionally -- applied a hot fix via the REPL by sending a new function defn but... "ultimate power" and all that... generally not recommended practice at all 😐 )


This is the power of a lisp machine. 0 downtime deploys are much easier if you can live reload code this way.


aka "extensive downtime deploys when you mess it up" 😉


@U0MDMDYR3 Heh, just send the old defn back into the running image 🙂


I have no qualms about leaving a localhost nrepl on production servers. It’s invaluable.


@seancorfield we maintain our processes listening on localhost nrepl ports and use ssh to control them. in rare circumstances we apply hotfixes or debugging that are urgent or otherwise problematic. just another component that spins up an nrepl server. There are caveats and we don't do it lightly, but the power has saved my company a lot of money over the last 4 years.


@norman @bja Glad to hear of others using a live localhost REPL for this!


yeah - it requires discretion, but can lead to sorting out weird production issues faster


When we had just a few production nodes, we would hot patch fixes regularly. There’s also nothing like being able to instrument or sample live data. Obviously you need to know your tools well and tread lightly, but there’s nothing like being able to go from bug report to fixed in production in 5 minutes.


@norman doesn’t it become a bit of a nightmare if you apply ad-hoc patches on production?


like, don’t you lose track of what code is running?


After the fire is out we will get packages built and deployed, but that could be a day or two later


Now we just have too many production nodes to do this, but our infrastructure for fixes is more sophisticated


Today it could take half a day to get a fix committed, built in CI, approved by QA and deployed by ops


in the best case


I miss the old days 🙂


We still use prod nrepl, just not for fixes


Hand fixing 3 heads takes a couple minutes. Patching 20 is less fun manual. It all depends on the scale


@hmaurer if you maintain the git commit as a value in your running code, you can sync your local version. You now have a nice base with which to apply a fix, test it, roll back if process demands, then push the fix through proper channels.


Yes, I would always commit changes for reference