Fork me on GitHub
#clojure
<
2022-02-22
>
Jon Eskin08:02:21

If any Emacs users are using deps-new or clj-new, I made a wrapper with a Magit-style interface for using them within Emacs to create projects. I included a couple cool templates I've come across but I'm looking for worthy additions if anyone knows any 🙂 https://github.com/jpe90/emacs-clj-deps-new

🙌 1
simongray09:02:05

Nice. You should probably put this in #announcements rather than here.

nixin7214:02:35

Anyone have experience building jars in GitHub Actions CI? I'm trying to make a workflow to build a jar file, but the compilation fails in GitHub Actions but runs fine locally.

Run clojure -J-Dclojure.main.report=stderr -T:build uber
  clojure -J-Dclojure.main.report=stderr -T:build uber
  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
  env:
    JAVA_HOME: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.14-101/x64
    CLOJURE_INSTALL_DIR: /opt/hostedtoolcache/ClojureToolsDeps/1.10.3-1029-3-6/x64/lib/clojure

... Download deps ...

Execution error (IOException) at java.io.UnixFileSystem/createFileExclusively (UnixFileSystem.java:-2).
No such file or directory

Full report at:
/tmp/clojure-5272109133831685895.edn
{:clojure.main/message
 "Execution error (ExceptionInfo) at clojure.tools.build.tasks.compile-clj/compile-clj (compile_clj.clj:92).\nClojure compilation failed\n",
 :clojure.main/triage
 {:clojure.error/class clojure.lang.ExceptionInfo,
  :clojure.error/line 92,
  :clojure.error/cause "Clojure compilation failed",
  :clojure.error/symbol
  clojure.tools.build.tasks.compile-clj/compile-clj,
  :clojure.error/source "compile_clj.clj",
  :clojure.error/phase :execution},
 :clojure.main/trace
 {:via
  [{:type clojure.lang.ExceptionInfo,
    :message "Clojure compilation failed",
    :data {},
    :at
    [clojure.tools.build.tasks.compile_clj$compile_clj
     invokeStatic
     "compile_clj.clj"
     92]}],
  :trace
  [[clojure.tools.build.tasks.compile_clj$compile_clj
    invokeStatic
    "compile_clj.clj"
    92]
   [clojure.tools.build.tasks.compile_clj$compile_clj
    invoke
    "compile_clj.clj"
    63]
   [clojure.lang.Var invoke "Var.java" 384]
   [clojure.tools.build.api$compile_clj invokeStatic "api.clj" 232]
   [clojure.tools.build.api$compile_clj invoke "api.clj" 209]
   [org.corfield.build$uber invokeStatic "build.clj" 248]
   [org.corfield.build$uber invoke "build.clj" 209]
   [build$uber invokeStatic "build.clj" 11]
   [build$uber invoke "build.clj" 10]
   [clojure.lang.AFn applyToHelper "AFn.java" 154]
   [clojure.lang.AFn applyTo "AFn.java" 144]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$apply invoke "core.clj" 662]
   [clojure.run.exec$exec invokeStatic "exec.clj" 48]
   [clojure.run.exec$exec doInvoke "exec.clj" 39]
   [clojure.lang.RestFn invoke "RestFn.java" 423]
   [clojure.run.exec$_main$fn__205 invoke "exec.clj" 178]
   [clojure.run.exec$_main invokeStatic "exec.clj" 174]
   [clojure.run.exec$_main doInvoke "exec.clj" 139]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :cause "Clojure compilation failed",
  :data {}}}

Execution error (ExceptionInfo) at clojure.tools.build.tasks.compile-clj/compile-clj (compile_clj.clj:92).
Clojure compilation failed

Error: Process completed with exit code 1.

Alex Miller (Clojure team)14:02:34

I assume this works if you run it locally?

Alex Miller (Clojure team)14:02:24

this is a pretty old version of tools.build now, and I have fixed some bugs and error reporting in compile-clj since then, although not sure anything of that is related

nixin7214:02:26

Yea, runs as expected locally. I'll try upgrading the vresion of tools.build :thumbsup:

Alex Miller (Clojure team)14:02:14

my 2 initial hypotheses are: • something to do with creating the temp dir where compile-clj does its compiling • something in your code that creates a dir in top-level side-effecting def during compiling which works locally but doesn't elsewhere

nixin7214:02:25

Okay, so updating tools.deps doesn't do it. Would this likely be the issue then? https://github.com/nixin72/shan/blob/master/src/shan/config.clj This file creates some files at the top-level

Alex Miller (Clojure team)15:02:28

if any of those dirs doesn't exist or you don't have perms, it would fail like this

Alex Miller (Clojure team)15:02:40

generally side effecting code in defs like this is bad (as it is run during compilation)

nixin7215:02:02

Ahh, I didn't realize that would be run during compilation. I'll change this up and add the checks to setup the files/directories elsewhere.

Alex Miller (Clojure team)15:02:01

compilation just is a side effect of load, so all the code you compile will be loaded

nixin7215:02:37

Ahh that fixed it! Still got other issues in my CI, but the jar compiles fine now! Thank you so much!

Alex Miller (Clojure team)15:02:48

in the future, feel free to ask on #tools-build instead...

nixin7215:02:25

Will do :thumbsup: I looked for a general CI channel or github actions one, but only saw specific CircleCI so I wasn't sure where best to ask.

jaide15:02:36

A coworker is asking if there's any Clojure projects in the wasm space. Anything come to mind? Recall hearing a bit about that a few years ago

quoll15:02:13

I’m curious about this myself. I can call WASM via the Java and JavaScript interop, but don’t know of any libraries that make this easier (I’ve been considering writing a utility for this). I’d love to see Clojure compile to WASM, but since there isn’t an official GC in WASM that isn’t really feasible for the moment.

lispyclouds15:02:53

I guess theres https://github.com/helins/wasm.cljc but only deals with manipulating the WASM file.

jaide15:02:09

Found https://hasgeek.com/inclojure/2020/sub/wasm-on-clojure-6CuxGMcGY4otVcGgyJSBF7 and if projects like Babashka or Node Babashka use graal and graal can target WASM then that could be a suitable pipeline

ribelo15:02:43

wasm has no gc so it doesn't really make sense

quoll15:02:34

There are GCs being developed, but they’re not there yet. And I don’t see them being anywhere near as good as Shenandoah

ribelo15:02:35

Liz has a clojure like syntax and is transpiled to zig, so can be compiled to wasm

ribelo15:02:29

i would like to see some kind of typed clojure for wasm, something like assemblescript

vemv19:02:40

What's a performant way to get all the :foo and :bar keys at once, grouped into two vectors?

(let [[foos bars] (mystery-fn [{:foo 1 :bar 2} {:foo 3 :bar 4}])]
  (is (= [1 3] foos))
  (is (= [2 4] bars)))
with little/no intermediate collections

kraf20:02:02

How do you know you'll get [foos bars] and not [bars foos]? Sorry if this is a noob question, I assumed it's not deterministic

vemv20:02:55

depends on mystery-fn :) its signature could be (mystery-fn [:foo :bar] coll) and the [:foo :bar] order would be honored

bortexz22:02:40

faster than:

[(mapv :foo coll) (mapv :bar coll)]
?

vemv22:02:26

I ended up doing sth to that effect, however traversing the coll N times might have some performance impact I had in mind a fn that would traverse the coll just once, building N transient vectors that would grow as the traversal progresses

bortexz22:02:09

yeah I tried that on repl, I think it might end up being slower for small N keywords

bortexz22:02:13

at least was slower on my computer for the foo/bar example:

(defn mystery-fn2
  [coll]
  (loop [foos (transient [])
         bars (transient [])
         rem coll]
    (if-not (seq rem)
      [(persistent! foos) (persistent! bars)]
      (let [i (first rem)]
        (recur (conj! foos (:foo i))
               (conj! bars (:bar i))
               (rest rem))))))
also not really extensible to N keywords, maybe a reduce with a map {key transient-coll}

vemv22:02:17

rest uses the seq abstraction, which is sometimes slower than reducing over the same coll

vemv22:02:50

(further optimize at your own discretion - probably my code will remain as-is ;p)

👌 1
hiredman19:02:42

or (reduce (fn [a m] (reduce (fn [a [k v]] (update-in a [k] (fnil conj []) v)) a (keys m)) {} ...)

hiredman19:02:56

I usually think of that kind of operation as being "facet" because the first time I saw it pulled out as a reusable pattern was https://aphyr.github.io/tesser/tesser.core.html#var-facet

🙂 1
p-himik20:02:41

Why is :y 2 in the result there? Shouldn't it be 2.5?

vemv20:02:58

TIL! perhaps I'll keep my code dumb for now - partly I was asking to make sure I wasn't just forgetting some basic idiom

hiredman20:02:27

Basically juxt for folds

danielglauser21:02:29

Is it poor form to include percent signs in symbol names? For example: foo% meaning the percentage of foo.

😐 1
phronmophobic22:02:41

seems reasonable to me

danielglauser22:02:34

Thanks. Looks like folks on my team are already using foo-pct so I’ll go with that. I prefer to stick with conventions when they are established even if they aren’t how I’d normally do things.

👍 2
ghadi22:02:32

i bet people are generally unaware that you can use % in a symbol

1
lsenjov00:02:21

It already breaks a lot of people’s brains that you can use *?! in symbols

lsenjov00:02:56

You can technically use . in clj, but it breaks in shadow-cljs

emccue00:02:58

percent of what? Maybe you can just do foo÷bar

emccue00:02:29

that way the name of the numerator and the denominator are preserved

danielglauser00:02:32

@U3JH98J4R Naming it foo-ratio was one of the suggestions.

Björn Ebbinghaus16:02:04

I would argue, that percent = ratio * 100 So a number „in percent“ is different to the ratio.