This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-18
Channels
- # announcements (2)
- # babashka (35)
- # beginners (59)
- # calva (17)
- # cider (3)
- # clerk (7)
- # clj-kondo (21)
- # cljfx (9)
- # cljs-dev (76)
- # clojure (98)
- # clojure-austin (3)
- # clojure-brasil (1)
- # clojure-europe (11)
- # clojure-gamedev (4)
- # clojurescript (14)
- # consulting (7)
- # cursive (6)
- # datascript (4)
- # datomic (12)
- # emacs (18)
- # events (2)
- # graalvm (9)
- # humbleui (3)
- # hyperfiddle (18)
- # jobs (4)
- # missionary (12)
- # nextjournal (2)
- # nrepl (7)
- # off-topic (31)
- # practicalli (2)
- # rdf (6)
- # releases (2)
- # scittle (10)
- # xtdb (9)
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.)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)
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.
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
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 đ§”
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.
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.
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?
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.
But when you compile the project with uberjar, these modules don't present in the classpath so they're just ignored
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)
@U1WAUKQ3E These files are in directories on the classpath.
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.
@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
?
Thanks, @U0510902N. I did want to ask you if you are using any special file extension. I have been considering .fiddle
, actually.
@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.
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.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.
@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.
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. đ
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 relevantSince 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
I guess it equally speaks to the perils of println based debugging đ
For printing values, I almost exclusively use prn
instead of println
. println
is mostly for printing text.
Right. They are very new to Clojure. 3 days old actually
How do other people pronounce that? I always see it as "porn", but somehow I don't think that was intended. đ
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"}
?(update-keys data (comp keyword name))
But I would ask "why do you want to do this?"
If it's to produce JSON, all the JSON libs have a way to produce unqualified keys.
(some do it by default, some need an option to do it)
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
How are you communicating between frontend and backend? EDN or JSON?
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 ""}}
(I would update the FE code to use namespace destructuring but I like qualified keywords đ )
(let [{:recipe/keys [recipe_id public prep_time name img favorite_count uid]} ex] ..)
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
(that example was just so you could use local symbols for the elements of the qualified recipe data)
You can use qualifiers on keys
and/or individual elements if you have mixed qualifiers.
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.
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.
Also update-vals
See https://github.com/clojure/clojure/blob/master/changes.md#3-new-functions-and-namespaces for other Clojure 1.11 goodness.

yikes i've been using 1.11 forever and i never realized what an amazing qol improvement it was
@sritchie09 saw your talk https://www.youtube.com/watch?v=B9kqD8vBuwU&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!
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
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).
i grabbed the csv writing code to handle a channel rather than a full collection and said âhuhâ
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
Yeah... that certainly makes me tilt my head and go "hmmm..." :thinking_face:
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:.
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
ah so I guess that's out of the question on Windows, then.
See https://ask.clojure.org/index.php/12916/libs-clojure-alphas-causing-filename-extension-long-windows
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?)
It is, and I can run clj
in Powershell without issues :thinking_face:
what is the rest of the stacktrace like? like where in the process is the error arising
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)
ok so it can't find the clojure
executable
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
I used the MSI installer -- and that seems to work well (it also installs deps.clj)
(that way you don't need to install a package manager if you don't already have one)
Awesome, thank you!
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)
@U04TQR7C24D it works for me yeah
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=>
That's on Powershell. A similar invocation of add-libs
also fails.
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 đ
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=>
I also get the same root error
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=>
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?
a lot of this will be fixed in the next alpha when we start passing args over stdin
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...