This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-21
Channels
- # announcements (39)
- # architecture (7)
- # aws (9)
- # babashka (111)
- # beginners (139)
- # bristol-clojurians (1)
- # calva (47)
- # chlorine-clover (5)
- # cider (17)
- # clj-kondo (26)
- # clojars (25)
- # clojure (251)
- # clojure-berlin (1)
- # clojure-dev (5)
- # clojure-europe (22)
- # clojure-france (1)
- # clojure-hungary (6)
- # clojure-losangeles (8)
- # clojure-nl (18)
- # clojure-spec (3)
- # clojure-uk (68)
- # clojured (32)
- # clojurescript (32)
- # core-async (10)
- # core-typed (120)
- # cursive (8)
- # datascript (10)
- # datomic (11)
- # docker (2)
- # emacs (6)
- # figwheel-main (4)
- # fulcro (10)
- # graalvm (92)
- # hoplon (2)
- # instaparse (9)
- # jobs (3)
- # jobs-discuss (31)
- # joker (2)
- # kaocha (1)
- # lambdaisland (5)
- # leiningen (10)
- # luminus (1)
- # lumo (14)
- # meander (30)
- # mid-cities-meetup (1)
- # midje (1)
- # off-topic (46)
- # pathom (22)
- # perun (2)
- # re-frame (10)
- # reitit (1)
- # remote-jobs (8)
- # shadow-cljs (71)
- # spacemacs (7)
- # sql (40)
- # tools-deps (31)
- # tree-sitter (11)
- # vim (14)
- # vscode (2)
- # xtdb (5)
how can i reify a functional interface? https://docs.oracle.com/javase/8/docs/api/java/io/FileFilter.html naively it would be
(reify
.FileFilter
(accept [^.File file]
(not (.isHidden file))))
is there a channel on here specifically to do with the clojure runtime as installed by homebrew? seems it now automatically installs openjdk 13, which is problematic because we're still all the way down on 8, which then makes this issue occur https://github.com/clojure-emacs/orchard/issues/20
@robert-stuttaford I'm a bit surprised by that since I've used homebrew to install and upgrade clojure
a lot on both macOS and Linux and never seen it install a JDK...
i know, right! i had to brew remove openjdk --ignore-dependencies
to fix it
β brew info clojure
clojure: stable 1.10.1.510
The Clojure Programming Language
/usr/local/Cellar/clojure/1.10.1.510_1 (11 files, 18.6MB) *
Built from source on 2020-02-21 at 05:06:22
From:
==> Dependencies
Required: **openjdk β**, rlwrap β
==> Analytics
install: 7,516 (30 days), 17,701 (90 days), 58,798 (365 days)
install-on-request: 7,425 (30 days), 17,484 (90 days), 58,045 (365 days)
build-error: 0 (30 days)
four hours ago π https://github.com/Homebrew/homebrew-core/commit/715900bfab494ccee4cadeea902d80ccce6e7a16
What JDK/JRE did you have installed before you tried to install Clojure?
openjdk 1.8
yeah, this homebrew change is going to catch a lot of people.
OMG! They switched from "any Java >= 1.8" to "openjdk"?
@alexmiller fyi π ^^
seems this person has been doing it to a bunch of brew recipes https://github.com/Homebrew/homebrew-core/commits?author=reitermarkus
Wow... I commented on the Clojure one but that's like an entire "campaign" π
going to be an interesting couple days for planet Clojure π
They (almost) gave a reason here: https://github.com/Homebrew/homebrew-core/issues/39837
neither is gravity, but here we are, stuck to the surface of the earth
Latest response @robert-stuttaford
Because we are migrating to openjdk. We want our libraries and code to run with the latest version of java/openjdk if possible.
This is going to break a LOT of people's experiences with Java-based HomeBrew projects.
If anything is broken for you, please open an issue, we will have a look. But since the migration campaign has started, we did not get that many bug reports.
So I guess you need to report your breakage π
thanks - i'll do so! i doubt they'll do anything with my info though, because the breakage is actually inside cider
Then I have very little sympathy π Sorry, I shouldn't be mean about CIDER but my life has been calmer since I no longer have to deal with nREPL/CIDER at all.
you're on a pure socket repl, right? i'm just so used to cider + clj-refactor, it'd be a mega yak shaving contest to ween myself off of it!
What do you use in cider/clj-refactor? And, yes, pure socket REPL -- zero dependencies (I don't even bother with Compliment since Atom/Chlorine does auto-complete pretty well on its own -- it will leverage Compliment if it's on the classpath for "better" auto-complete etc)
i lean heavily on cider's print-to-buffer and inline printing stuff, and clj-refactor's clean-namespace and a handful of other code munging tools, like introduce-let, expand-let and friends man, a clean dependency-free repl sounds like it must be fast!
Interesting. I find paredit and parinfer to be sufficient -- I guess I'm not a fan of tools that try to rewrite my code. And, yes, it's fast with no middleware and no dependencies -- and, best of all, it's the same dev/test experience regardless of whether the process is local or remote (I regularly connect my editor to socket REPL processes not running on my machine).
yeah, we basically just put cider and clj-refactor into our production apps π
Seems like they are closing any requests to revert back to any existing Java on system.
And here is one more curious discussion: https://github.com/Homebrew/homebrew-core/issues/49944
Hmm, I'd never heard of JAVA_VERSION
before reading that thread. I use JAVA_HOME
extensively to switch versions locally tho'...
Seems to me something Apple added. But still, someone's workflow is breaking and they couldn't care less.
> But still, someone's workflow is breaking and they couldn't care less. that observation doesn't seem fair tbh. The homebrew guys are underpaid/understaffed and essentially get routinely DDOSed with lazy requests from developers
The change -- from java >= 1.8 to (the latest) openjdk -- seems to be a bit of a knee jerk reaction, given that they've inflicted it on dozens of repos directly...
I agree that they are doing everyone a huge favor. I love how simple/hassle-free brew
is and often wished it was available on Linux/Windows.
brew is available on Linux -- I use it all the time.
But this seems like a co-ordinated effort. I wish they explained their reasoning in a blog post at least.
I will report back on feedback from my comments π
And the response was swift: "Because we can't test Java updates unless we're the ones shipping them. This has been going for a couple of weeks and no breakage has been reported."
(I resisted the temptation to ask "How often do people try to update their Homebrew setup?")
@i Yeah, like @hindol.adhya I'm not quite sure what you're asking there... can you elaborate?
@i sorry, I don't understand what you're saying about Python there...
Did you want this? https://docs.oracle.com/javase/tutorial/essential/regex/pre_char_classes.html
I can manually type them. I was just curious to see if clojure already defines such a const value.
I'm curious, why do you need that string?
(I'm thinking of scenarios where you can verify strings with regex or use test.chuck
to generate strings from regexes...)
come across this: https://github.com/zelark/nano-id/blob/3a3085c741a57c908f2a157e610aa6813ca93310/src/nano_id/core.cljc#L6
Do you need each character in a string? If not, you can do (into [] "abc...zABC...Z")
.
Is it possible to enable lazy evaluation of a def? (def val (this-form-is-evaluated-only-on-first-usage))
it would be better if I could use the variable form val, instead of invoked the val as a function (val) in the second approach.
delay
is your friend. https://stackoverflow.com/questions/11026335/do-lazy-variables-exist-in-clojure and http://clojuredocs.org/clojure.core/delay
It's not that different from a memoized function with no arguments - you still have to change the calling code.
also delay lets you use realized?
to ask if it's been forced yet, and it lets you use force
which is identity on non-delay values, but deref on a delay
I'm a big fan of delay
user=> (def d (delay (doto 42 println)))
#'user/d
user=> (realized? d)
false
user=> (= (force d) (force 42))
42
true
I guess I'm biased because I work with Reagent a lot. I don't like seeing @
where I don't expect an atom, especially when it's in a view. I immediately start thinking that it's a value that may change and that that change might trigger something, like re-rendering.
well, the existence of force
helps there too - but @
works on promises too, and futures, and both of those, like delays, only ever have one value (but will block until they have one)
That raises another question - why is clojure.lang.Var#getRawRoot
final? Along with a bunch of other methods.
Maybe the use case is, in clojure land, we mainly deal with (int-array [1,2,3]). When interop with java a function which passes in object[](1,2,3), we can use ints
to convert it back to int[]
.
I found a few calls to clojure.core/ints
in the Clojure code of the core.rrb-vector library. I do not know if it is needed there when it is used, but it appears to be used there when there really is a Java mutable array of type int
for the array elements, and perhaps the cast done by clojure.core/ints
is useful in producing better Java byte code then. Not sure.
I am pretty sure that a Java cast operation cannot change a Java array of long
into a Java array of int
, for example, and assuming that is true, that cannot be what the purpose of clojure.core/ints
is.
The only type of argument that I think it makes sense to call clojure.core/ints
on is an object that already is a Java array of primitive int
elements, but the cast is needed so that the JVM 'knows' it, too.
In Clojure-land, people mostly stick to vector
. They are not type-bound, e.g. [1 "two" 3.0]
is valid. int-array
deals with Java arrays.
I have never seen the function ints
used before. Not sure why it exists, other than what the doc string says. Not sure what kinds of arguments it accepts and can do something useful with.
Something I am constantly being affected by is {:pre [(spec/valid? :foo fn-argument)]}
failing without any meaningful error messages.
we have a very tiny library consisting of just a helper for that: https://github.com/nedap/utils.spec/blob/master/src/nedap/utils/spec/api.cljc
Usage would be {:pre {(check! :foo fn-argument)]}
and it gives you a Expound-backed report (https://github.com/bhb/expound) when the precondition fails
You also can build your own check!
quite trivially
And while i am able to load this file in REPL, I am not able to build uberjar (seems like original clojure.spec.alpha
is not loaded before I start overriding things with my implementation)
Overriding namespaces, or doing monkey-patching is quite frowned upon in the world https://twitter.com/stuarthalloway/status/1229856488560234497
You can use bindings though: https://github.com/bhb/expound/tree/e90a16162e97d16904d2353f46084e139b0e8f37#explain-out
=>
(set! spec/valid? valid?)
Execution error (IllegalStateException) at hermes.debug/eval29194 (form-init4832872063532060265.clj:1).
Can't change/establish root binding of: valid? with set
class java.lang.IllegalStateException
that's a set
ting not a binding
:)
It's certainly possible to perform the binding
in dev and prod alike
I totally understand why it is like so, it's clear that spec/valid?
just returned nil
in pre
check.
Because I've got deployed instance running, it's failing one of pre-checks and I have no way of knowing why it's actually failing.
@seancorfield just starting to trying out deps, sadly find this: https://github.com/Homebrew/homebrew-core/commit/715900bfab494ccee4cadeea902d80ccce6e7a16#r37414693
yeah, wtf
I literally just upgraded clojure via brew and was very confused to see it try and install jdk13
ticket filed at https://github.com/Homebrew/homebrew-core/issues/50536
I expect this could be the Nth issue related to those changes that they have heard about, and their answers haven't changed on how to handle it -- use JAVA_HOME
It makes it sound like Homebrew's intended usage is to never leave the Homebrew ecosystem. And if you need to do that, you better extend the ecosystem wide enough with taps.
Does this mean clj will be run with the jdk that homebrew installs by default?
clj will run with any jdk you want (just set JAVA_HOME)
this is about what gets installed for you by default
it used to be able to tell you already had a Java 8 installed and just proceed
now it will forcibly install adoptopenjdk 13
Looks like they've done it for Maven as well https://github.com/Homebrew/homebrew-core/issues/50531, which somehow seems even more clueless to me.
in general, I have found that the homebrew maintainers are not too familiar with the java ecosystem, which I'm not slighting them for, they can't know everything
but it's frustrating sometimes
I'm trying to send binary data (audio/wav) using http-kit, but it seems unless I set the content-type the server at the other side will ignore my request. Is there a way to set it?
basically I need to do this request in clojure:
curl -X POST "" -H "accept: application/json" -H "Content-Type: audio/wav" -d {}
fwiw homebrew users: I've recently been giving asdf
a spin for java and graal env management (and other tools now), maven works, clojure seems to work but for some reason is only parsing down to 1.9.0, so I'm going to add an asdf clojure as well real quick (and will post it in a threaded reply to this message here in a few hours).
oh, it looks like @U08JQ8RD0 maintains it! π wdyt about a PR that takes a bit more of an https://github.com/vic/asdf-clojure/blob/master/bin/list-all approach so other versions are available?
Is there a way to force java classes to reload in the REPL? I'd like to be able to edit the java source, then compile the class and reload it so the new class definition is bound to the class name symbol.
I think this would work: https://github.com/ztellman/virgil
> Now, as if by magic, every time the .java files on your :java-source-paths change, they will be recompiled within your REPL and all the namespaces that rely on those files will be reloaded.
Thanks. I may use that, though right now I'm using clj
not lein
. Maybe I'll look inside virgil and unwrap the magic.
Yeah, I started doing that some time ago (before I realized I didn't really need Java for my task), and it seemed that hooking it up to whatever you use should be pretty straightforward.
Yeah, it's doing (refresh-all)
at the core. I don't really want to reload all of the clojure namespaces, just get the new java class defs correctly loaded and bound.
Is there a way in Clojure to simply write some Java code inline? If not, what is the way to do this with minimum fuss? Not talking about calling some existing Java code somewhere else.
I know you said that you are not talking about calling some existing Java code somewhere else, but I believe that the minimum fuss way is to create the Java code you want to call as separate files, compile them to JVM byte code, and then use Java interop calls from Clojure.
I'd be interested to see the java code you want to inline. I think a lot of the time people just aren't aware of the clojure interop version. but yeah as andy said for the few instances where you can't use interop the minimum fuss way is to write a java class
I don't have a very specific thing in mind, but as a hobbyist I do problems from Project Euler and the thumb rule is the solution should run within a second. I can rarely clear the bar if ever. I want to basically right the hottest part in pure mutable Java.
there are things that are faster in java land than any equivalent in clojure land, but it's unlikely that that is what you're encountering. most likely you can get as fast as you need to writing optimised clojure
If you are looking to leverage mutability for performance, take a look at transients: https://clojure.org/reference/transients
@UG00LE5TN Yeah, tried that. Not fast enough. The only way it is fast enough is when I can do pure primitive math with absolutely no (un)boxing. There are basically two ways. Use the Java array types or restructure code to be loop/recur with primitives.
@U050MP39D Sometimes I can reach as close as 4x to let's say the Java version. But that's a lot of fuss. At that point I wish I can simply use some Java. But that is also a lot of fuss, π
fair enough, loop/recur with primitives was the kind of thing I was referring to so if you're down that low it probably is worth dropping to java. I would love to see an example though
On my phone but I will post back later. But I have recently started fiddling with clj-java-decompiler and that's a lot fun too. I am not an expert yet. Maybe I will uncover a few new ways of optimizing the Clojure versions.
You can use that to write java programs.
That seems unlikely to be a 'minimum fuss' approach π
but I've never tried it myself. Had never seen it before. Thx for the link.
That's hilarious, I think (glanced over the code and just read function names) that it's actually compiled the java as text π
private maven repos are effectively an authenticated http directory. as such, they don't generically have an api to "search". so I don't think that's actually a possible thing. some repos publish an index, but generally you won't get that with the most common filesystem/s3-based approaches
maven central index is at https://repo.maven.apache.org/maven2/.index/ for example
they publish both full and incremental updates
Where is clojure.core/import*
defined?
@dave.dixon it seems it (the symbol, but not var) is created via intern
here https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L60
(thanks for the correction from hiredman)
oh - that's not a namespace intern, just a symbol intern?
oh, so it's just a symbol constructor, got it https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Symbol.java#L54
thanks for the clarification
and it's a special form https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L117
Thanks. As a side note, how did you find that? Github search-foo has eluded me...
Find the import*
...
I used $ ag 'import\*'
in the cloned repo locally
Ahh, that's my fallback too.
I was surprised not to establish it was special via special-symbol?
as mentioned further down in the main topic
The really interesting thing about import* is it may be the only namespaced special form
I thought there were a few?
so that makes sense of this
user=> (special-symbol? 'import*)
false
user=> (special-symbol? 'clojure.core/import*)
true
^ that was my first stab at answering @dave.dixonβs question, but I didn't think to try with namespace haha
user=> (->> Compiler/specials keys (filter qualified-symbol?))
(clojure.core/import*)
Anyway, I'm still trying to find a way to reimport java classes. Just calling import
again doesn't pick up the new class definition.
Compiler/specials
should tell you
unless you do something special in the classloader
Zach Tellman does have a thing for this
import is a modification to the current ns, the fact that a class is loaded is a side effect of accessing it (loading is on-demand)
Does refresh-all
, which I'd like to avoid because it triggers side-effects.
if refresh-all triggers side effects you should fix your namespaces so it doesn't :D
It's just useful for dev. I have a dev namespace I'm working in for triggering various effects that rely on the Java. Not something to be used in production code.
you can blacklist a namespace from refresh-all
I'm going to have to hack virgil then, since I don't see that it exposes that. Also using not using lein
. Forking...
I thought this was exposed via clojure.tools.namespace itself
this is all you need https://github.com/clojure/tools.namespace#disabling-refresh-in-a-namespace
Yup, that did it. So the trick was in my dev namespace, first call disable-reload!
on that namespace, then virgil-watch
. Thanks, I think that's going to be a big efficiency boost.
if you want to use some unholy weirdness, probably excusable in dev-only mode
Yes. I just want the rapid REPL cycle, but including the java classes I'm hacking.
that's what virgil is for
I forgot - what's the github repo for the clj / clojure command line tools? I have a potential PR for the rlwrap config for clj
haha turns out my feature was already in there
way ahead of you :)
-s
flag which causes all input and output strings to be added to completion history, plus -b
for proper clojure symbol matching
I endeavored to understand and have good config when I wrote it :) and there have been some mods over time from people. I no longer remember anything about it :)
Hereβs something fun to play around with. π
user=> (extend-type (class +) IMonoidId (-monoid-id [this] 0))
nil
user=> (reduce + (-monoid-id +) [1 2 3])
6
Given that (+)
is 0
already...
Thatβs not the point of the example. The point is that you can extend protocols to functions this way. Itβs not about the details in the example. I just choose the monoid example cause it was easy.
I think putting "fun" and "monoid" in the same sentence was the problem :rolling_on_the_floor_laughing:
In spite of the fact that we take advantage of monoids in everyday programming all the time?
Who would have thought the associative and identity properties could be such a lightening rod under the word βmonoidβ?
Hereβs some more point.
user=> (defprotocol IInverse (-inverse [this]))
IInverse
user=> (extend-type (class inc) IInverse (-inverse [this] dec))
nil
user=> (defn inverse? [f g]
(= (-inverse f) g))
#'user/inverse?
user=> (inverse? inc dec)
true
I often do this move for singletons like
(def Thing (reify))
(extend-type (class Thing) ,,,)
and then it lol hit me that I could do it in this other devious way.reminds me a bit of this code where the function name is recovered from the class name: https://github.com/borkdude/spartan.spec/blob/ff7317d67ec15f188afb856d37090e5c9509374e/src/spartan/spec.clj#L118
for the same thing from the opposite direction, you can also extend a deftype / defrecord to IFn so it can be called like a function
just implement applyTo
for arglist and invoke
for each arity
But you could imagine tagging functions as Associative
or Commutative
in this way and win with algebra.
What would you do with functions tagged Associative
or Commutative
, out of curiosity? Some kind of run-time checks when those functions are passed as parameters into other reduce-like functions?
Same question (and maybe answer) for SideEffecting
?
I probably wouldnβt do this in serious practice but if Iβm experimenting Iβd use it to explore a space where those properties are of interest.
something like a reducer could automatically decide how to build a pipeline based on those tags
it's the sort of auto-optimization of steps that RH explicitly talks about disliking (eg. that talk where he discusses a query planner in the context of justifying how little optimization clojure attempts)
Optimizations and/or designs which leverage algebraic properties can be useful too. But most of this discussion is OT. I only wanted to share this one neat trick cause I thought it was just that. π
lein update-in :pedantic? vector :abort -- update-in :pedantic? second -- test ;; hack Friday
I am afraid to type that, even if you explained what it did π
another constraint: the function to update-in must be a resolvable symbol in clojure.core
koan: (-> {:pedantic? :warn} (update-in :pedantic? _ _) (update-in :pedantic? _))
must equal {:pedantic :abort}
It seems like a usage of lein
that deserves a longer comment than the plugin one would write to make it clear what was happening π
I wish you a shorter next week!
Sorry for the snark, I'm only showing the tip of the iceberg of more of a social/human situation. I got a bit frustrated that I can't really communicate where I'm coming from.
No offence taken :). The social stuff is often the hardest :(. Been there a number of times.