Fork me on GitHub
#clojure
<
2023-05-18
>
valerauko09:05:58

I'm observing a really weird behavior. In code like below

#?@(:cljs [:controllers [{:start #(rf/dispatch [::events/foo])}]])
If there is any namespaced keyword in the code (with a namespace alias that cannot be resolved on the CLJ side) this throws a compiler error saying it's an "Invalid token". Am I doing something wrong or is this a bug? (The same happens without the @ splat too.)

valerauko09:05:21

I can circumvent the error by as-alias requiring that namespace on the clj side as well but that's quite weird (requiring a cljs namespace in clj even if just as-alias)

p-himik11:05:24

The ::ns-alias/kw keywords are turned into :proper-ns/kw by the reader. The #? reader conditionals make the reader read all the forms in there and discard the ones that aren't suitable in the current mode. Assuming you have something like #?(:cljs [some.ns.with.events :as events]), the reader will read that form and discard it in the CLJ mode. When it comes to that #? in your OP, it will still have to read the whole form in order to be able to discard it. But it can't read it because the ::events part is not expandable - that alias has been successfully discarded.

👍 2
valerauko15:05:21

Okay I understand that reasoning. It's still super weird since I don't expect any of that code to be actually looked-at... To me at least resolving a namespace alias is much more eval than a read

pez11:05:39

How is it determined which files are being searched for on the classpath? I think that specifically I want to know if I can name it hello.clojure without fear that it will be included in the app unless I explicitly load it? Some more context in đŸ§”

pez11:05:35

As a complement to Rich comment forms, I sometimes place code in a “scratch” file side by side with the files that implement a namespace. So for src/app/hello.cljc I create a file src/app/hello.calva-repl. To make it play nicely with Calva, I place an ns form at the top, like (ns app.hello (:require ...)). Calva happens to by default treat .calva-repl files as Clojure files + give them some extra treatment.

pez11:05:12

Calva happens to by default treat .clojure files as Clojure files too. So I am thinking maybe give that “extra treatment” to those too. As this would effectively promote to use .clojure for these scratch/fiddle files, I want to know that it is fine using this extension.

pez11:05:51

Ping @U0510902N and @U5FV4MJHG who started me on this fiddle file thing several years ago with some episode of #CKKPVDX53. What file extensions do you use for these files?

igrishaev11:05:41

What are you looking for is called profiles. Usually, a dev profile extends the project settings such that there are some additional paths in classpath. These paths contain dev modules with various things: starting and stopping the system, running migrations, calling services.

igrishaev11:05:17

But when you compile the project with uberjar, these modules don't present in the classpath so they're just ignored

igrishaev11:05:42

if you use lein, add this to the project.clj

:profiles 
{:dev {:source-paths ["env/dev/src"]
       :main dev}}
then create a new file
mkdir -p env/dev/src
touch env/dev/src/dev.clj
step into dev.clj and add (ns dev)

igrishaev11:05:39

then run lein repl and you'll get into the dev namespace loaded

pez11:05:18

@U1WAUKQ3E These files are in directories on the classpath.

pez11:05:24

I could use dev profiles too, and often I do. But it is often more convenient to have the files side-by-side with the implementations.

nate16:05:15

@U0ETXRFEW So cool to hear you've been using fiddle files. I'm still a big fan of them and use them every day in my projects. I've always used the usual .clj extension for my fiddle files. I've usually kept them off in a dev/ directory that's only on the classpath during development (and so is ignored in release builds). I have also put them in a separate directory not on the classpath (usually in projects where I'm the only one with fiddles), as the REPL doesn't care if files or forms are on the classpath. It's an interesting idea to keep fiddle files right next to the files they are for. If you're adding another extension to Calva, how about .fiddle? or .rich?

pez16:05:20

Thanks, @U0510902N. I did want to ask you if you are using any special file extension. I have been considering .fiddle , actually.

neumann16:05:03

@U0ETXRFEW I work with them the same way as Nate. If you're using an uberjar, it is worth mentioning that you can strip out files from the uberjar when you create it, so that may be another way to keep your fiddle files out of your release.

pez16:05:06

Thanks, @U5FV4MJHG. I’ll have a look what goes into the uberjar.

👍 2
pez16:05:11

This is a bit boring:

; Evaluating file: core.calva-repl
; ------ REPL Error while processing ---------------------------------------------
; (cljs.core/load-file "/Users/pez/Projects/tests/shadow-w-backend/src/main/core.calva-repl")
; can only load .cljs and .cljc files
I don’t really need to load the files, but I tend to do it by habit.

pez16:05:41

So, if I don’t exclude these on-the-classpath fiddle files, they go into the uberjar of a “default” build (at least the basic example in the https://clojure.org/guides/tools_build): Often that’s fine, right? I guess this is on my original question. It’s not loaded just because it’s in there, has been my assumption.

neumann22:05:17

@U0ETXRFEW I do believe that for a namespace to be loaded, it has to be referenced by another loaded namespace. Likewise, for a namespace to be compiled AOT, it has to be referenced by another namespace using AOT. If you aren't distributing a jar for public consumption, you may not need to care about "extra" files in the jar.

pez06:05:14

Thanks, @U5FV4MJHG. That makes sense and is how I have assumed things work. Though, at least in the editor tooling environment I have seen files being loaded, that I can’t figure out how the REPL found them. So started to second guess. I’ll stop worrying now. 😃

craftybones17:05:05

A pair I was helping out today ran into this little bit of trouble. They were debugging(with a println) and they had a simple (every? desired-nums candidates)

user=> (println #{1 2 3})
#{1 3 2}
nil
user=> (println #{"1" "2" "3"})
#{3 1 2}
This took them on a spin for a while before they finally realised that they weren’t getting a set of numbers but a set of strings. Admittedly this isn’t a flaw per se and I am not sure why I am typing this in, but I thought it might be relevant

craftybones17:05:56

Since both the set of numbers and the set of strings printed the same way, they went down an incorrect rabbit hole before eventually finding out what the problem was

craftybones17:05:25

I guess it equally speaks to the perils of println based debugging 😄

phronmophobic17:05:44

For printing values, I almost exclusively use prn instead of println. println is mostly for printing text.

craftybones17:05:57

Right. They are very new to Clojure. 3 days old actually

phronmophobic17:05:25

> (prn #{1 2 3} #{"1" "2" "3"})
#{1 3 2} #{"3" "1" "2"}

👍 2
skylize00:05:44

➕ to prn almost always.

skylize00:05:33

How do other people pronounce that? I always see it as "porn", but somehow I don't think that was intended. 😄

Patrix01:05:51

I usually pronounce it “prin”, sounds like “prim”

BuddhiLW19:05:37

Is there a built-in, or simple way to accomplish:

{:namespace/a "a"
   :namespace/b "b"
   :namespace/c "c"}
to
{:a "a"
 :b "b"
 :c "c"}
?

enn19:05:55

(update-keys m (comp keyword name))

seancorfield19:05:57

(update-keys data (comp keyword name))

seancorfield19:05:00

Jinx!

😂 6
seancorfield19:05:12

But I would ask "why do you want to do this?"

seancorfield19:05:34

If it's to produce JSON, all the JSON libs have a way to produce unqualified keys.

seancorfield19:05:48

(some do it by default, some need an option to do it)

BuddhiLW19:05:03

I wrote my front-end before my I wrote my backend. So, all destructing I did was not namespaced. My backend, though, is all namespaced. So, I'm converting the values from the end-point to a format native to my front-end

seancorfield19:05:34

How are you communicating between frontend and backend? EDN or JSON?

BuddhiLW19:05:30

So far, I have this, in which ex is the response from the endpoint.

(let [ex [{:recipe/recipe_id "a1995316-80ea-4a98-939d-7c6295e4bb46"
             :recipe/public true
             :recipe/prep_time 5
             :recipe/name "Avocado Salad"
             :recipe/img " 
 cipe/vegie-salad.jpg"
             :recipe/favorite_count 5
             :recipe/uid ""}]]
    (associate-by-kkeyword-value :recipe/recipe_id ex))

  ;; => {:a1995316-80ea-4a98-939d-7c6295e4bb46
  ;;     #:recipe{:recipe_id :a1995316-80ea-4a98-939d-7c6295e4bb46,
  ;;              :public true,
  ;;              :prep_time 5,
  ;;              :name "Avocado Salad",
  ;;              :img " 
 cipe/vegie-salad.jpg",
  ;;              :favorite_count 5,
  ;;              :uid ""}}

seancorfield19:05:53

(I would update the FE code to use namespace destructuring but I like qualified keywords 🙂 )

BuddhiLW19:05:16

I like them too

seancorfield19:05:43

(let [{:recipe/keys [recipe_id public prep_time name img favorite_count uid]} ex] ..)

🙌 2
BuddhiLW19:05:56

Maybe it won't take as much time as I'm thinking. I will do it slowly, but certainly, as I build the backend and test integration

seancorfield19:05:29

(that example was just so you could use local symbols for the elements of the qualified recipe data)

BuddhiLW19:05:46

Is this considered associative destructing?

seancorfield19:05:13

You can use qualifiers on keys and/or individual elements if you have mixed qualifiers.

BuddhiLW19:05:39

Very good, I was looking for something like this at first. Thank you so much

seancorfield19:05:41

Qualified keywords are idiomatic -- but they weren't popular in the early days of Clojure... Spec has made them much more popular I think, and a general consideration that they provide additional context in naming.

BuddhiLW19:05:13

I went through the re-frame course, from Jack Schae doing the events and subscriptions qualified. I think it's much easier to reason about it. Even more so, when you have different things/moments acting on a specific topic. For example, when you change navigation by clicking on a menu, or when you finish a form and you must be redirected. Both navigate the site, but the navigation events will likely be in different event namespaces. I generally, will put nav/redirect and modal/redirect . So, the context makes it very legible in this case, indeed.

2
👍 2
stand22:05:01

Is update-keys a clojurescript thing? I don't see it in clojure.core.

enn22:05:17

it’s new-ish, I forget the version

seancorfield22:05:33

Also update-vals

valerauko14:05:38

yikes i've been using 1.11 forever and i never realized what an amazing qol improvement it was

Zach λ21:05:33

@sritchie09 saw your talk https://www.youtube.com/watch?v=B9kqD8vBuwU&amp;feature=youtu.be about "moldable physics and lispy microworlds on youtube, really interesting. I live in durham so I wish I knew it was going on!

Sam Ritchie21:05:08

Thank you!! I’ll have an announcement about the project soon in #C041G9B1AAK 
 let me know what you’re interested in, happy to help build anything

dpsutton22:05:01

wild. i’ve never seen clojure.core/when-first before.

til 16
verysweat_g 2
seancorfield22:05:02

It's surprisingly uncommon for a macro that has been in core since 1.0... We don't have a single instance of it at work (despite having a codebase that dates back to 1.3 alpha releases).

dpsutton22:05:23

i don’t think i’ve registered that it exists

dpsutton22:05:40

i grabbed the csv writing code to handle a channel rather than a full collection and said “huh”

valerauko23:05:02

I think it might be because of how confusing https://clojuredocs.org/clojure.core/when-first is

;; Note that the 'when' switches on the truthiness of the sequence, not the
;; truthiness of the elements within the sequence.

user=> (when-first [a [nil 2 3]] 
         (print (str "Picked: " (prn-str a))))
Picked: nil
nil

seancorfield00:05:55

Yeah... that certainly makes me tilt my head and go "hmmm..." :thinking_face:

BuddhiLW19:05:42

Well, that should be interpreted as "there exist a 'first' element", no matter which value it translates to, even nil. We are testing if first exist, not it's value :face_with_cowboy_hat:.

Ben Lieberman22:05:20

Are there people using add-lib on Windows? I can get it working just fine in WSL but running it on Windows 10 I get

Execution error (IOException) at java.lang.ProcessImpl/create CreateProcess error=2, The system cannot find the file specified

hiredman23:05:04

it requires being able to shell out to the clj command

Ben Lieberman23:05:33

ah so I guess that's out of the question on Windows, then.

hiredman23:05:57

could be, but different error message

jjttjj23:05:14

Oh yeah you're right, sorry

hiredman23:05:26

more likely clj isn't installed, or isn't installed in a way that the clojure process can find it (path? is path a thing in windows?)

Ben Lieberman23:05:23

It is, and I can run clj in Powershell without issues :thinking_face:

hiredman23:05:23

what is the rest of the stacktrace like? like where in the process is the error arising

Ben Lieberman23:05:44

java.lang.ProcessBuilder/start (ProcessBuilder.java:1143)
clojure.java.process/start (process.clj:94)
clojure.java.process/start (process.clj:57)
clojure.core/apply (core.clj:669)
clojure.java.process/exec (process.clj:134)
clojure.java.process/exec (process.clj:128)
clojure.core/apply (core.clj:667)
clojure.tools.deps.interop/invoke-tool (interop.clj:34)
clojure.tools.deps.interop/invoke-tool (interop.clj:14)
clojure.repl.deps/add-libs (deps.clj:48)
clojure.repl.deps/add-lib (deps.clj:57)
user/eval10001 (NO_SOURCE_FILE:19)
clojure.lang.Compiler/eval (Compiler.java:7177)
clojure.core/eval (core.clj:3221)
clojure.core/eval (core.clj:3217)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.core/apply (core.clj:667)
clojure.core/with-bindings* (core.clj:1990)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.main/repl (main.clj:438)
clojure.main/repl (main.clj:459)
clojure.main/repl (main.clj:369)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:84)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:56)
nrepl.middleware.interruptible-eval/interruptible-eval (interruptible_eval.clj:152)
nrepl.middleware.session/session-exec (session.clj:218)
nrepl.middleware.session/session-exec (session.clj:217)
java.lang.Thread/run (Thread.java:833)

Ben Lieberman23:05:21

ok so it can't find the clojure executable

chucklehead23:05:57

The official Clojure for Windows just registers shell aliases in PowerShell, so there is no clojure executable for createprocess. If you're okay with a non-official installer, installing via scoop and https://github.com/littleli/scoop-clojure would probably work for you. It basically installs https://github.com/borkdude/deps.clj as clj.exe/clojure.exe

seancorfield23:05:49

I used the MSI installer -- and that seems to work well (it also installs deps.clj)

seancorfield23:05:14

(that way you don't need to install a package manager if you don't already have one)

2
Ben Lieberman00:05:31

Awesome, thank you!

Bastian09:05:28

Does the msi installer work for you? I'm getting (when calling add-lib): Execution error at clojure.java.process/exec (process.clj:144). ; Process failed with exit=1 clj꞉user꞉> clojure.java.process/exec (process.clj:144) clojure.java.process/exec (process.clj:128) clojure.core/apply (core.clj:667) clojure.tools.deps.interop/invoke-tool (interop.clj:34) clojure.tools.deps.interop/invoke-tool (interop.clj:14) clojure.repl.deps/add-libs (deps.clj:48) clojure.repl.deps/add-lib (deps.clj:57)

seancorfield16:05:11

I get this -- which seems to indicate incorrect formatting for the arguments somewhere:

PS C:\Users\seanc\clojure> clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version """1.12.0-alpha3"""}}}'
Clojure 1.12.0-alpha3
user=> (require '[clojure.repl.deps :refer [add-lib]])
nil
user=> (add-lib 'hiccup)
Unreadable arg: "{:lib hiccup, :procurer #:mvn{:repos {central {:url }, clojars {:url , :clojure.exec/invoke :fn}"
Execution error at clojure.java.process/exec (process.clj:144).
Process failed with exit=1
user=>

seancorfield16:05:56

That's on Powershell. A similar invocation of add-libs also fails.

Ben Lieberman16:05:21

Yeah I actually spoke too soon, I see the downloads begin but then the process ultimately fails. I just walked away from my computer right before that happened 😅

seancorfield16:05:23

And I get the same thing on cmd.exe:

C:\Users\seanc>clj -Sdeps "{:deps {org.clojure/clojure {:mvn/version ""1.12.0-alpha3""}}}"
Clojure 1.12.0-alpha3
user=> (require '[clojure.repl.deps :refer [add-lib]])
nil
user=> (add-lib 'hiccup)
Unreadable arg: "{:lib hiccup, :procurer #:mvn{:repos {central {:url }, clojars {:url , :clojure.exec/invoke :fn}"
Execution error at clojure.java.process/exec (process.clj:144).
Process failed with exit=1
user=>

Ben Lieberman16:05:00

I also get the same root error

Ben Lieberman16:05:12

If I specify a desired version for a lib I also get this additional output

(add-lib 'ring/ring {:mvn/version "1.10.0"})
Unreadable arg: "{:existing #:org.clojure{clojure {:mvn/version 1.12.0-alpha3, :deps/manifest :mvn, :parents #{[]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\clojure\\\\1.12.0-alpha3\\\\clojure-1.12.0-alpha3.jar]}, spec.alpha {:mvn/version 0.3.218, :deps/manifest :mvn, :dependents [org.clojure/clojure], :parents #{[org.clojure/clojure]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\spec.alpha\\\\0.3.218\\\\spec.alpha-0.3.218.jar]}, core.specs.alpha {:mvn/version 0.2.62, :deps/manifest :mvn, :dependents [org.clojure/clojure], :parents #{[org.clojure/clojure]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\core.specs.alpha\\\\0.2.62\\\\core.specs.alpha-0.2.62.jar]}}, :add #:ring{ring #:mvn{:version 1.10.0}}, :procurer {:paths [src], :deps #:org.clojure{clojure #:mvn{:version 1.12.0-alpha3}}, :aliases {:deps {:replace-paths [], :replace-deps #:org.clojure{tools.deps.cli #:mvn{:version 0.9.35}}, :ns-default clojure.tools.deps.cli.api, :ns-aliases {help }}, :test {:extra-paths [test]}}, :mvn/repos {central {:url }, clojars {:url , :libs #:org.clojure{clojure {:mvn/version 1.12.0-alpha3, :deps/manifest :mvn, :parents #{[]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\clojure\\\\1.12.0-alpha3\\\\clojure-1.12.0-alpha3.jar]}, spec.alpha {:mvn/version 0.3.218, :deps/manifest :mvn, :dependents [org.clojure/clojure], :parents #{[org.clojure/clojure]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\spec.alpha\\\\0.3.218\\\\spec.alpha-0.3.218.jar]}, core.specs.alpha {:mvn/version 0.2.62, :deps/manifest :mvn, :dependents [org.clojure/clojure], :parents #{[org.clojure/clojure]}, :paths [C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\core.specs.alpha\\\\0.2.62\\\\core.specs.alpha-0.2.62.jar]}}, :classpath-roots [src C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\clojure\\\\1.12.0-alpha3\\\\clojure-1.12.0-alpha3.jar C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\core.specs.alpha\\\\0.2.62\\\\core.specs.alpha-0.2.62.jar C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\spec.alpha\\\\0.3.218\\\\spec.alpha-0.3.218.jar], :classpath {src {:path-key :paths}, C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\clojure\\\\1.12.0-alpha3\\\\clojure-1.12.0-alpha3.jar {:lib-name org.clojure/clojure}, C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\core.specs.alpha\\\\0.2.62\\\\core.specs.alpha-0.2.62.jar {:lib-name org.clojure/core.specs.alpha}, C:\\\\Users\\\\benl\\\\.m2\\\\repository\\\\org\\\\clojure\\\\spec.alpha\\\\0.3.218\\\\spec.alpha-0.3.218.jar {:lib-name org.clojure/spec.alpha}}, :basis-config {:extra {:deps #:org.clojure{clojure #:mvn{:version 1.12.0-alpha3}}}}}, :clojure.exec/invoke :fn}"
Execution error at clojure.java.process/exec (process.clj:144).
Process failed with exit=1
user=>

seancorfield17:05:47

Since it says "Unreadable arg", I think this is a quoting issue, when shelling out to the clojure command, as part of invoke-tool -- @U064X3EF3 are you aware of any Windows-related issues with invoke-tool and quoted arguments?

Alex Miller (Clojure team)17:05:25

a lot of this will be fixed in the next alpha when we start passing args over stdin

4
👍 4
seancorfield16:07:29

Now that Alpha 4 is out and 1.11.1.1347 (CLI), if deps.clj and the .msi installer get updated to use the latest CLI, this can be retested against 1.12's latest Alpha and hopefully it will work now...

jjttjj17:07:50

Can confirm that this works on windows now for me with the latest msi!

2