This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-23
Channels
- # aleph (14)
- # announcements (2)
- # babashka (8)
- # bangalore-clj (2)
- # beginners (66)
- # calva (8)
- # cider (1)
- # clj-kondo (24)
- # cljdoc (3)
- # cljs-dev (3)
- # cljsrn (2)
- # clojure (197)
- # clojure-europe (1)
- # clojure-india (5)
- # clojure-italy (4)
- # clojure-nl (27)
- # clojure-uk (18)
- # clojurescript (56)
- # code-reviews (19)
- # core-async (86)
- # cursive (16)
- # data-science (1)
- # datomic (16)
- # docker (3)
- # events (1)
- # fulcro (101)
- # graalvm (7)
- # graphql (16)
- # jobs (1)
- # jobs-discuss (6)
- # kaocha (4)
- # luminus (1)
- # off-topic (93)
- # onyx (3)
- # pathom (9)
- # planck (2)
- # re-frame (8)
- # reagent (3)
- # reitit (3)
- # remote-jobs (3)
- # shadow-cljs (21)
- # test-check (3)
- # tools-deps (21)
- # vim (16)
Hello All 👋 I have planned to attend https://inclojure.org/ on Feb14th & 15th and looking for some company 🙂
There’s a section in the doc about this: https://cursive-ide.com/userguide/eap/formatting.html#matching-indentation-to-emacs, what I just realised is that it doesn’t cover storing the settings in the project. To do that, under Preferences | Editor | Code Style select Scheme: Project.
@i we have a styleguide.clj
which covers and documents the formatting and we ask every teammember to configure his editor / autoformatting so there’s no changes when applying autoformat to this file
seems like an open issue https://github.com/cursive-ide/cursive/issues/1403
Is there an HTTP client library where requests produce core.async
channels? If not, would there be interest in such a thing? (and if not, why not?)
I don’t know if such a library exists. I do know about https://github.com/mhjort/clj-gatling, the Clojure wrapper around Gatling where each step in the simulation can return a core.async channel. Probably a bit different use case (the http-kit call is in the go block - actually not completely sure if it’s a good idea to have a HTTP call in a go block? Is that different from I/O which is not recommended since it blocks the thread? I would think so actually). Maybe you can get some inspiration from there. I mainly wanted to mention that library cause I really love using it. Do you know about it? I would definitely be interested in such a library if it indeed a good idea to do http calls in a go block and it works reliably!
@seancorfield I have a http://java.net.http client for Java 11 that hands you channels of responses
@U050ECB92 great! I'll take a look and see whether I think what I was doing adds any value over what your library is doing. I started this before I moved to jdk 11.
the aleph library includes a client, and uses ztellman's manifold lib that integrates cleanly with core.async channels > For HTTP client requests, Aleph models itself after clj-http, except that every request immediately returns a Manifold deferred representing the response. https://github.com/ztellman/aleph
@U050ECB92 That explains why I can't find it 😆
@noisesmith I want something lightweight that avoids dragging in a bunch of libraries.
anything that returns a CompletableFuture can be easily adapted into something that returns a channel
and you can call put!
in a callback arg, that can get you pretty far too
Sounds like enough options out there that I don't need to bother with my own! Thank you everyone for the feedback/info.
(I was experimenting with this some time ago, as a wrapper around http-kit
's client library, but haven't pursued it because I don't know whether it's a good idea and whether the support burden of creating a FOSS library is worth it...)
@seancorfield Wouldn't it help to contrib to a lib like clj-http? they have callback style async support https://github.com/dakrone/clj-http#async-http-request and this can be added? Less maintenance burden 🙂
https://github.com/r0man/cljs-http already does return core async chans with the same api too
@U7ERLH6JX I don't do any cljs so I hadn't seen that. Will take a look thanks. As for clj-http
, we're trying to move away from that at work because it's too "heavy" and we're stuck on an old version because newer versions break stuff in our code (and after spending a lot of time debugging it, I just gave up).
I totally agree on the heavy part and have pretty much switched over to https://github.com/martinklepsch/clj-http-lite Also it’s Graalvm friendly which the original one isn’t unfortunately
I have something like this:
(def a {:func some.ns/foo})
And I would like to print some.ns/foo
docstring using a
. How can I achieve that?You have the value some.ns/func was pointing to, you don't have the var some.ns/func which is what the metadata is attached to
I see... maybe I could get all the vars in some.ns
, compare their values with (:func a)
, and see which one matches
To illustrate the problems with what you want to do ask yourself what should happen for
(ns a)
(defn f [])
(ns b)
(def g a/f)
In that case, a/f and b/g are bound to the same object, so assuming you could ask the object, which answer would it give?
In some cases, the compiler generates a class name which matches the var name for top level defined functions, but that doesn't address functions that are bound to vars in multiple namespaces, and functions creates other ways like via partial
Ah, I see. I somehow got something that works (at least in the REPL), but I guess it depends on how the initial some.ns/foo
was created?
(let [s (-> a
:func
class
str
(str/replace "class " "")
(str/replace "$" "/")
(str/replace "_" "-")
)]
(meta (find-var (symbol s))))
And for example, I could delete the a namespace, and the function bound to b/g would still have a class of a$f, which doesn't exist anymore, and doesn't match the only namespace the function is bound to a name in
It is a result of a kind of fundamental mistake in thinking about the relationship between names and the values they access
Honestly, I'm very confused. I'm going to read more carefully https://clojure.org/reference/var and https://clojure.org/reference/reader, are those the correct topics to better understand this?
Yes, I understand. I though that clojure would keep some data/metadata about in a
about some.ns/foo
. I think the better approach would be to simply add the the docstring when initializing a
I can get the docstring when using some.ns/foo
, I wanted to see if I could do it using a var a
defined with something like (def a some.ns/foo)
Yes. I managed to somehow do it like this
(let [s (-> a
:func
class
str
(str/replace "class " "")
(str/replace "$" "/")
(str/replace "_" "-")
)]
(meta (find-var (symbol s))))
So you can get back the originating ns and fn name, make a symbol of it and then resolve that back
Yup, so this should do it: `(-> (class some-ns/foo) (print-str) (clojure.main/demunge) (symbol) (resolve) (meta) (:doc))`
Alternatively, when you get the fn from the original var, you can copy the doc meta onto the fn meta or your new var
Or if you prefer to put it on the Var:
(alter-meta!
(def a some-ns/foo)
merge (meta #'some-ns/foo))
goodday/afternoon/evening, I am looking for the arcadia channel, clojurians working with clojure in the field of gaming?
I do not see any channel/room here by the name Arcadia. You are welcome to create one, or perhaps search under some other likely names if you can think of any that someone else may have created.
@didibus resolve
takes into account namespace aliases and class names:
user=> (require '[clojure.string :as str])
nil
user=> (resolve 'str/join)
#'clojure.string/join
user=> (resolve 'Exception)
java.lang.Exception
Neat, I've just run into the filename length limit of my file system, thanks Clojure compiler...
Compiling a namespace that uses a macro, which results in quite some nesting of functions
yeah, there is a ticket about this
core.match can get you there occasionally
definitely something we'd like to address
Also you'd think that decades into the 21st century, a modern file system like btrfs would allow for longer file names than 255 bytes...
Yea, me as well actually... One hard reset of the machine and it is often just unrecoverably dead
I have a basic question. Why don't I have to require
clojure.string
but I do have to require other clojure.*
libs?:
$ clj
Clojure 1.10.1
user=> (dir clojure.string)
blank?
capitalize
ends-with?
escape
includes?
index-of
join
...
user=> (dir clojure.set)
Execution error at user/eval150 (REPL:1).
No namespace: clojure.set found
user=> (require 'clojure.set)
user=> (dir clojure.set)
difference
index
intersection
join
...
you should not ever rely on any namespace being loaded (except clojure.core, which is auto-required)
(clj-kondo warns about not explicitly required namespaces since a release or two ago)
I'm puzzled why this is failing on our CI server but works locally:
((fn [{:keys [cron]} {:keys [id]}]
(format "%s %s"
id
(.URLEncoder/encode ^String (:timezone cron) java.nio.charset.StandardCharsets/UTF_8)))
{:cron {:timezone "Europe/Bratislava"}}
{:id 1})
;; on my computer (Mac OS)
;;=> "1 Europe%2FBratislava"
;; on the CI server (Linux)
;; Execution error (ClassCastException) at user/eval1458$fn (REPL:19).
;; sun.nio.cs.UTF_8 cannot be cast to java.lang.String
I can see that the URLEncoder/encoded
method is overloaded and compiler tries to call the other version (where string is the second arg) but I'm not quite sure I understand why...
I can't find a version of java where that function takes something other than a string
where does cron
get calculated?
you can avoid a bunch of issues like this by never using AOT
(which is easier than you might think in clojure)
Yes, it's java 8. @noisesmith what do you mean by not using aot; what would happen in that case?
https://docs.oracle.com/javase/10/docs/api/java/net/URLEncoder.html vs https://docs.oracle.com/javase/9/docs/api/java/net/URLEncoder.html fwiw
Yes, found that - thanks a lot @U050MP39D for the hint!
@U06BE1L6T I might misunderstand the problem, but when you don't use aot, clojure won't generate method calls based on a different vm from the one that is used at runtime
the problem here was he was actually trying to call a method that simply didn't exist on the version of the jvm he was deploying to. there is no #encode(String, Charset) in java prior to 10
OK - that's different
The issue is if you AOT with JDK 10 for example, the bytecode tries to call a JDK 10 class, even if that class exists on JDK8, when trying to call it AOT, it might fail, because JDKs ABIs are not always compatible from newer to older
If you don't AOT, compilation is delayed, so your code will get compiled not on the JDK used in your build, but the one in Prod, which means JDK versions of all compiled code will match
Just in general though, don't use a different JDK in development, CI, prod, etc. Make sure you run the exact same one, even from the same vendor
That'd be akin to using different versions of Clojure in all three, its just prone for issues
Yep, in this case that definitely make sense. However in some cases (on-prem) we have bunch of JDKs that needs to be supported and I generally just run it with JDK 11 (some other people with JDK 8 )
And probably on CI, you want to have them all, so you can run your tests and all on each to be safe
Well, ideally, you have multiple JDK on your desktop too, so you can test them all. I mean, that's just the burden you take to support them all.
But still, Java normally goes to greater length to make sure old works on new, but not the other way around. Modules being the exception here :
Same with Clojure versions by the way, not a lot of effort is made to have new work with old
Someone had recommended jenv once to make switching between JDK locally easier: https://www.jenv.be/
What's the way these days to comment on tickets in the Clojure JIRA? I've created an Atlassian account, but it's denying me access, and I'm not sure how to proceed.
That's also where you can create new issues, and if approved, an admin will create a corresponding Jira for it
https://clojure.org/community/contributing#_reporting_problems_and_requesting_enhancements
we are trying to reserve our (limited) jira accounts to those working on patches
but if you have a CA and are doing so, happy to make an account
https://ask.clojure.org/index.php/7102/transforming-fragments-non-namespaced-into-default-xmlns is the ask equivalent
is there a way to bit shift right a byte?
seems that it results in a long value
@roklenarcic no clojure function returns a byte directly, for integral types they all return longs
you can use interop, and with the right hinting etc. they can stay unboxed even, but it's not going to be the easy path
You can then call byte
, I think returning a java.lang.Byte object, perhaps? Not sure whether that achieves your goal or not.
of course nothing prevents you from converting
(cmd)user=> (byte (bit-shift-right 8 2))
2
(ins)user=> (type *1)
java.lang.Byte
the problem is that I’m bit shifting a negative value
also, if you are doing this with one byte, often the real task is over a large number of bytes that get handled in various ways - check out ByteBuffer for arbitrary parsing of arbitrary offsets of that array, and the byte-streams library https://github.com/ztellman/byte-streams
so I get a massive long which will probably convert to 0xff byte?
depends upon the long value, and how you convert to a byte. Some ways of converting to a byte simply keep the least significant 8 bits and discard the most significant bits, so would not always convert to 0xff byte
Clojure 1.10.1
user=> (bit-shift-left Long/MAX_VALUE 8)
-256
user=> (byte (bit-shift-left Long/MAX_VALUE 8))
Execution error (IllegalArgumentException) at user/eval3 (REPL:1).
Value out of range for byte: -256
user=> (unchecked-byte (bit-shift-left Long/MAX_VALUE 8))
0
seems to work ok. dunno how good an idea it is though
user=> (byte (bit-shift-right 2r10000001 1))
64
why would that be an issue? it looks like the expected usage of bit-shift-right to me
Does anyone know when a future
releases the thread that’s backing it? Is it once its Callable
returns some result, or after the first time someone derefs it? (assuming of course that it wasn’t cancelled for some reason)
It seems like ideally after the Callable finishes executing… but maybe that’s up to the executor vs. the future itself?
the thread is released as soon as the callable exits - it goes back into the pool in the clojure.core/future case
it is up to the executor, but I have never seen an executor that did it any other way
Yeah, that makes sense to me.
Just sanity-checking myself
thanks 👍
you can double check with jstack
or Ctrl-\
to see what's really running
technically it is an ExecutorService, Executor doesn't actually have methods that return futures
> technically it is an ExecutorService true
> Executor is a pretty great interface There is always beauty in simplicity
Hi, I have a small app that makes a few Rest API calls, through which it obtains an IP address. I'd then like to exec an ssh
command, replacing my current process. What's the best way to do that? clojure.java.shell
seems to run a subprocess and tries to wait, so my little app just appears to hang.
right, clojure.java.shell turns the output of a command into a string, so can't really do interactive
but you can use ProcessBuilder to make a Process, and use the inheritIO method to let a terminal user interact with the resulting application
this won't make the vm exit though - it just hands the terminal over to the child
you can't do the "replace the process" bit. the jvm doesn't provide the Posix exec call
there's a one liner I've got somewhere, I can even exec vim, edit a file, then exit back to a repl
the gotcha is you have to make the shell (which is reading form the same terminal) wait for the process to exit
@noisesmith, that sounds like a good workaround. Can you share the one-liner?
grabbing it now
user=> (-> (ProcessBuilder. ["nvim"]) (.inheritIO) (.start) (.waitFor))
0
that 0 is the exit code of neovim
you can of course add more args to that vector, or run /bin/sh if you need redirects etc.
the waitFor prevents the editor and the repl from fighting over the same characters on input
Awesome, thank you very much!
you can even continue to run other things in other threads while that executes (of course you probably want to make sure they aren't reading or writing stdio)
another option I guess would be to ask the system to launch a new terminal application with the built up ssh command as its initial command. xterm -e ssh X.X.X.X
or what have you
yeah, that's windowing system / ui specific though, where the processbuilder just relies on stdio being connected to any terminal
eg. it works inside tmux while sshd'd from another host
it's all files, right?
haha right - original usage was ssh, vim is "feature complete" for tty I figured
I guess. I just kind of assumed that when java says "inheritIO" it means inherit java streams for IO. not low level pass over the fd's. anyway it's cool
"The fundamental unit of information in Clojure is data." https://medium.com/@lwhorton/why-clojure-script-e4a69cc5168a So, is that different in other languages? How?
You may need to ask the author that question. Most programming languages I would say deal with data. One thing that many programming languages almost always deal with is mutable objects, whereas Clojure makes it easy to keep the default as dealing with immutable values, including collections, while maintaining pretty good efficiency of making new collections with small differences from existing collections, without mutating them.