Fork me on GitHub
#clojure
<
2022-01-11
>
tami507:01:23

Does anyone know how I can get map out of specifying the namespace? I was expecting using (select-keys fields [:article/keys]) would work 😄 is there a function that does that in core?

tami508:01:45

for now I will just convert it all and select from it`(reduce-kv #(assoc-in %1 [(keyword (namespace %2)) %2] %3) {} fields)`

p-himik08:01:23

Not sure I fully understand what you want, but if you retrieve items from a map fewer times than there are items in the map, it might be better to just convert the keys you're using: (keyword (name :article) (name :keys)).

flowthing08:01:02

What does fields look like?

pavlosmelissinos09:01:42

You want to get the subset of a map that belongs in a specific ns, is that right? e.g. for

{:foo/bar 1
 :foo/baz 2
 :bar 3
 :baz 4}
and ns :foo you want to get
{:foo/bar 1
 :foo/baz 2}
I don't think there's anything in core that does that... This is how I'd do it:
(defn select-keys-of-ns [m ns]
  (into {} (filter #(= (name ns) (namespace (first %))) m)))

(select-keys-of-ns {:foo/bar 1
                    :foo/baz 2
                    :bar 3
                    :baz 4
                    :zoo/baz 5}
                   :foo)
;; => #:foo{:bar 1, :baz 2}

Nom Nom Mousse13:01:16

I have a question about futures. In the below code I start a bash process in a future and when it is done I have a callback-function which updates an atom (`app-state/jobresult`). I call .get on the future. Will the function initiated by the watcher of app-state/jobresult also happen in a future or will the main thread take over from there?

(defn add-completion-dispatch [java-proc jobid job]
   (.thenApply
    (.onExit java-proc)
    (reify java.util.function.Function
      (apply [this p]
        (reset! app-state/jobresult [jobid (.exitValue p) job])))))

(defn dispatch! [jobid]
  (tap> {:tap-id :starting-job :tap-data {:jobid jobid}})
  (swap! app-state/jobid->jobstate assoc jobid :in-progress)
  (let [job (@app-state/jobid->job jobid)
        ...
        bb-process (->process job)
        jobfuture (add-completion-dispatch (:proc bb-process) jobid job)]
    (read-process bb-process :err jobid)
    (read-process bb-process :out jobid)
    (.get jobfuture)))

p-himik13:01:36

Watchers are always run in the same thread that's doing swap!/`reset!`.

Nom Nom Mousse13:01:21

Ah, that explains it all. Is there a way to pass control over to the main thread again? That is what I hoped to do by just updating an atom.

Nom Nom Mousse13:01:08

Yes, something like: Instead of calling reset! from the callback, just do:

...
    (read-process bb-process :out jobid)
    (.get jobfuture)
    (reset! app-state/jobresult [jobid (.exitValue p) job])))
That is, provided .get is blocking. I'll need to read the docs.

p-himik13:01:17

I don't know what you're trying to achieve, but feels like you're overcomplicating things. What are you trying to achieve exactly?

Nom Nom Mousse13:01:44

I want to start bash jobs in futures and when they are done I want some result processing to be done (in the main thread).

p-himik13:01:28

Do you need to start multiple jobs in parallel? Why is it important that you do your processing in the main thread specifically?

Nom Nom Mousse14:01:16

1. Yes. 2. To simplify debugging. When errors happen in futures they just seem to disappear.

p-himik14:01:48

Regarding errors - this is a good read: https://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions I'm not sure whether Thread/setDefaultUncaughtExceptionHandler applies to completable futures (probably not), but you can experiment and figure out. In either case, it's always a good idea to call some form of get on all futures, or join or what have you, exactly for correct error propagation. If you deal with that correctly, then suddenly you don't care about watchers being run in different threads anymore.

🙏 1
p-himik14:01:28

And if you want to wait on multiple futures, you can either store them all in a non-lazy collection and then iterate and get each one, or you can use allOf: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#allOf-java.util.concurrent.CompletableFuture...-

🙏 1
Nazral13:01:50

Hi! I've been using https://github.com/SpaiR/imgui-java (java bindings for Dear ImGui, a C++ library) in Clojure for quite some time, and it's great, I can even do live coding a la figwheel (wrapping the call to ImGui in a future and then just changing my UI's functions in the repl), however if I mess up one such functions then not only the UI completely freezes (fair enough), but even the repl ends up crashing with a SIGABRT. Is there a way to catch these exceptions?

leifericf14:01:12

Hello, fellow Clojurians! I'm hearing a lot of buzz about Rust these days, and my passionate Rust friends tout its speed, facilities for memory safety and concurrency in particular. Those aspects are also major selling points for Clojure, in addition to its leanness, interactive programming, macros and metaprogramming affordances inherited from Lisp. I recognize that I might be swearing in church here, but I'm wondering whether someone has spent some time with both Rust and Clojure, and is able to compare their overlap and highlight differences? Especially when it comes to memory management and concurrency. Has anyone written anything like that? I don't have enough experience with either of them (yet) to do it justice. And it would be very useful to have such a comparison available when advocating for the adaption of Clojure, and functional programming more broadly.

p-himik15:01:26

I can't really answer your question, but FWIW I'm personally very hesitant to pick up Rust for anything involved, mainly due to posts at https://drewdevault.com/ (you can search for mentions of Rust there - not just in titles though). In particular, Rust is too big and it's getting bigger, and the rate at which it happens is far larger than I'd like.

Chase15:01:58

I like Rust but definitely still prefer the simplicity and interactive repl style development of Clojure. But if I had a need for no GC I would reach for Rust as it did feel I could punch above my weight for such tasks. I don't trust I can do it safely in C (and C++ but I haven't tried that one).

leifericf15:01:59

@U2FRKM4TW: Thanks for the link! I got a good chuckle out of this quote from one of the posts: > "Go is the result of C programmers designing a new programming language, and Rust is the result of C++ programmers designing a new programming language."

🙂 2
😂 1
leifericf15:01:24

@U9J50BY4C: Thanks for chiming in, and for sharing that gist! Looks interesting at a glance. I'm going to read through it more carefully later this evening after work.

Chase15:01:36

I believe @U04V15CAJ (a highly prolific Clojurian) has explored Rust for some things recently so he can probably give you a more up to date comparison if he doesn't mind me calling him in here.

👍 1
borkdude15:01:37

Rust and Zig kind of serve in the same domain. Zig might be more aligned with the Clojure philosophy whereas Rust is more like Scala (big on the type system to guarantee correctness + safety).

1
Chase15:01:58

An interesting topic I think between the two is how Clojure avoids the problems of state and mutation through pure functions and immutability while Rust approaches it through the borrowing/ownership rules (preventing shared mutable access to a variable). I think this was explored a bit here: https://without.boats/blog/notes-on-a-smaller-rust/

👍 1
borkdude15:01:59

But Rust is useful for probably a pretty different subset of applications than Clojure.

bpiel15:01:54

@U01PE7630AC I've spent many years with Clojure. I've also spent about a year writing a lot of Rust, trying it out for a personal/startup project (I ended up deciding it wasn't a fit for my needs). I haven't written anything on the topic, but can say a little now, and answer any other specific questions you might have. I'll simplify with bullet points. - Speed: Rust is generally accepted to be faster than Clojure. Personally, I've rarely ever needed something faster than Clojure (because Clojure is fast), but in this case I thought my needs might be extreme enough to warrant Rust (or C, C++, zig etc). - Memory Safety & Concurrency: Rust's approach (ownership&references) is completely different from Clojure's (ex atoms). Rust's approach is (almost always) enforced by the compiler. It creates (for me at least) a HUGE learning curve, which might be insurmountable if not for Rust having by far the most helpful compiler error messages I have ever seen. Tangent: Everything around the dev experience (quality of tooling, package mgmt, docs, compiler error messages etc) is EXCELLENT. Overall, Rust has done those things better than any other language I've ever worked with. - Macros & Metaprogramming : Rust's macros are hygenic, making them completely different than Clojure's. I found them easy to work with for simple things, but too difficult for more complex things. Technically, I believe Rust and Clojure macros to have about the same capabilities, but to acheive anything beyond simple requires delving into complexities that I didn't want to get into. - Re: borkdude's comment: "But Rust is useful for probably a pretty different subset of applications than Clojure." That is how I see it, but I would say most in the Rust community would disagree -- they want to use Rust for everything. I think they are lunatics. But, I think most choices that (non-Clojure) programmers make are completely insane, so... - When would I reach for Rust? Only as an alternative to C/C++; when Clojure is just not a fit. WebAssembly is an interesting case here -- Rust's capabilities there are very good. But, if I'm doing any sort of work where the JVM and/or javascript is appropriate, then, hands down, I am reaching for Clojure/clojurescript.

❤️ 3
5
Cora (she/her)16:01:02

I did rust for a few months and very much agree with all of that

👍 2
Cora (she/her)16:01:52

also a big for "Rust is more like Scala"

bpiel16:01:29

OH and... not having paredit (or similar) is infuriating

👍 2
quoll16:01:03

Interesting thread, but would it be better in #other-languages?

andy.fingerhut16:01:27

Maybe, but at least it is all in a thread 🙂

😄 5
quoll16:01:58

Since the comparison to Scala came up, the big question I have with Rust is if dependencies are handled better than with Scala. Everything I’ve written has been small and self contained, so I haven’t had to depend on much yet, and crates have been easy for me to work with. I figure that it’s somewhere in the midpoint between the ease of Clojure, and the disaster that is Scala.

borkdude16:01:04

Rust is source based, whereas Java/Scala deps are usually byte-code based. You always compile all the sources on your own machine, so no binary compatibility issues.

👍 1
borkdude16:01:07

There is no VM in Rust-land and no IR

borkdude16:01:13

at least not exposed

quoll16:01:25

Yes, that’s the compelling reason to use it

borkdude16:01:11

(I read something now about MIR but I don't think that affects what I said about deps)

quoll16:01:44

But I’ve had to deal with dependency issues with C/C++ projects in the past, which is why I was thinking that it the difficulty might be somewhere in the middle

leifericf16:01:24

@U051N6TTC: Thanks for pointing that out! I was not aware of the channel #other-languages until you mentioned it. Noted for future posts! I apologize for instigating this in the wrong channel.

👍 1
Cora (she/her)17:01:58

and having a lock file that includes all dependencies and transitive dependencies means it's repeatable, too

seancorfield17:01:06

Rust was one of the "learn a new language every year" experiments for me (well every "year or two" 🙂 ) and as someone who spent a decade doing C++ (in the '90s), I think if I had to go back to that sort of problem space -- systems programming -- I'd be happy to use Rust for it. But I'm also thankful to have escaped that space and that, since my C++ days, my arc has been Java -> Groovy -> Scala -> Clojure so I don't have to worry about memory management, etc. I think Rust is a very impressive language -- in many ways, it is what I had hoped Go would be (an earlier "learn a new language" experiment) -- but right now there's no problem on my plate that I can't solve with Clojure (and feel happier while doing so). I do worry about Rust's speed of expansion/development as a language tho', as others have mentioned above.

👍 1
quoll17:01:28

@U02N27RK69K Yes, I’m aware. I’ve used it.

Cora (she/her)17:01:41

oh, I misread your comment then 😅

mpenet20:01:33

Go and Rust are very different. Personally I would only use rust in cases where I cannot afford the use of a GC. Then about golang, you can be somewhat productive in a matter of hours with it, with Rust it takes a bit more effort.

didibus02:01:37

Cool discussion. But I feel Clojure is best qualified as FUN AS HELL. And if you don't find that true, then that's that, use something else. And from that angle, it doesn't really matter if another language has compelling features lol, unless it were to be EVEN MORE FUN! Personally, I've struggled finding anything as fun as Clojure that doesn't provide similar or better interactive development and capability for extension (with easy macros, function closures, protocols, late binding, etc.) The fun for me comes from the live interactive development workflow, the ease in navigating the code (like someone else said, pareinfer and company), and the ability to try out almost anything since the language can easily be extended for whatever crazy fun things, as in trying all kind of new constructs and ways to model and tackle problems. Rust kind of fails on both, but especially on the former. Now it can be debatable if Rust is functional as well. Depending on which FP we're talking about. But Rust does not lean on pure function, immutability, recursion, laziness, and all that. Though it does have closures and being able to pass function as values. Yes its types can bring back some of the guarantees, but the feel you get from using it is different, because it achieves independence between function using another strategy than immutability. And that means it also offers imperative looping which require mutation, etc. Apart from that, I'd be repeating what others have said. It's weird to compare the two, since their runtime is so different. When you can afford managed memory, Rust seems like just a pain in the **s. Why deal with all those type constraints if you can happily have a GC.

😁 3
👍 1
2
leif15:01:14

The Programing Research Laboratory at Northeastern University is conducting a study on the usability of visual and interactive syntax for ClojureScript. Participation involves filling out a questionnaire and is expected to take about 30 minutes. The questionnaire consists of multiple choice and free form responses. All questions are optional and responses are anonymous. If you are interested in participating, please visit: https://study.visr.pl (Chrome Recommended) To learn more about visual and interactive syntax for ClojureScript, please visit: https://prl.ccs.neu.edu/blog/2022/01/06/introducing-visual-and-interactive-syntax-realized-visr-for-clojurescript-and-javascript/ If you have any questions, please contact: <mailto:[email protected]|[email protected]>

👍 2
👀 1
Nom Nom Mousse17:01:10

Really cool stuff. Watching your video now :thumbsup:

Drew Verlee19:01:21

I have a .cljc file requiring via #?(:cljs (:require-macros [foo])) and the ns foo is also a .cljc file. This relationship is resulting in shadow-cljs's build complication failing with the error "failed to require macro-ns foo it was required by foo." I'm having trouble juggling the cljc stuff on top of the business use case i have. any pointers on the former?

noisesmith19:01:36

why put macros in cljc instead of clj?

thheller19:01:43

@drewverlee what is the rest of the error? like a stacktrace? what happens if you open a clojure repl and (require 'foo)? most probably there is just something in the .cljc file that clojure doesn't like (eg. something that should be behind a #?(:cljs ...) conditional)

noisesmith19:01:45

@drewverlee what "relationship" are you talking about?

Drew Verlee19:01:06

it seems i have a git conflict that is causing the files to be invalid. magit is going to send me into an early grave. sorry for the confusion.

hlship20:01:48

Is there an existing equivalent to https://github.com/ruedigergad/test2junit but for deps.edn? It seems like a natural option to add to https://github.com/cognitect-labs/test-runner.

Alex Miller (Clojure team)20:01:45

clojure actually has some support for this in clojure.test.junit already. there are some outstanding tickets for test-runner to look at test output options and it is something I want to address eventually, but have not worked on it yet

Alex Miller (Clojure team)20:01:54

some prs there too that I haven't reviewed

emccue20:01:46

Does anyone know why / an alternative to parsing spaces in cli args? (specifically tools.cli)

R.A. Porter21:01:01

I'm not sure if it applies in this case, but you can usually substitute commas for whitespace. Can be a bit hard to read, though.

emccue20:01:25

i’m trying to provide an api that looks like this

jproject run --aliases=build --java-opts="--enable-preview --release 17" build/Build.java compile

emccue20:01:55

i’m also open to alternatives like maybe -J--enable-preview -J--release=17 or something, but im not particularly thrilled by that syntax in particular

emccue20:01:22

(though it does seem to be to some degree a standard way - so maybe worth matching - but i also don’t know how to pull that off in tools.cli)

xceno22:01:32

I'm trying to work with a native library, but I just can't make it work with CLJ. As a sanity check I tried the same in a Java application, but there it works. Long story short, I made this gist with an explanation: https://gist.github.com/Xceno/958eb0340136fdd775838b9bef48f234 My feeling is, that it has something to do with the runtime environment, but I'm not sure. I have to check if I'm allowed to share specifics about the native lib. For now, most is redacted. Anyway, I hope someone can at least point me in a direction to debug this further

hiredman22:01:20

since you have a working java version, are you using the same jvm when running both?

hiredman22:01:06

my guess, based on https://bugs.launchpad.net/ubuntu/+source/sun-java6/+bug/325506 is that when using the java version you are using a jvm packaged by a third party, and when running on the clojure version you are using a jvm that debian packaging has fiddled with

xceno23:01:07

Not the same JVM instance, but the same JDK-11 (Amazon Coretto). However, I start both processes without any arguments or JVM parameters. The thing is, my app is deployed as datomic ion and I have no control (and no idea) how and with what params it's actually run. That's why I need to load the library from a relative path at runtime in the first place. And if it has any additional, transitive deps I need to place them in my projects resources as well later

hiredman22:01:45

actually, I bet what is going is the java side of the native library extracts the shared library in a static init block, and the clojure code's :import isn't enough to trigger the static init, so no extracted so to load

hiredman23:01:23

if you add something like (Class/forName "somethingNative.LicenseManager") before the call to System/load that might take care of it

xceno23:01:28

Huh, that's a great idea! Let me try this real quick

hiredman23:01:04

hmmm, I guess it wouldn't be exactly what I described, because then the System/load would throw an error

xceno23:01:06

Hm yeah it doesn't fix the error. The class that blows up always does so at swig_module_init() , but I only got the decompiled function headers, so no idea what's happening in there. About the different JVM instances: I also tried setting the CLJ JVM's java.library.path to the exact thing that my Java JVM uses, but it doesn't fix things either (which I think is odd)

phronmophobic00:01:40

@U012ADU90SW, Is this a c library or a c++ library? fwiw, the c interop libraries based on JNA and project panama are sometimes easier than using java wrapper libraries: • my go to library, https://github.com/cnuernber/dtype-next/ • I've used https://github.com/Chouser/clojure-jna/ a few times and was happy with it • uses project panama, https://github.com/IGJoshua/coffi

xceno09:01:08

It's a C++ library and the Java wrapper is provided by the vendor. I'm just trying to use it. I'm currently using dtype-next for other stuff in my project and absolutely love it! coffi looks great, but I'm stuck with JDK11 for the time being.