This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-23
Channels
- # babashka (18)
- # babashka-sci-dev (42)
- # beginners (84)
- # calva (11)
- # cider (5)
- # clj-kondo (11)
- # cljdoc (70)
- # cljs-dev (34)
- # clojure-europe (1)
- # clojurescript (3)
- # conjure (1)
- # core-async (29)
- # data-oriented-programming (10)
- # emacs (13)
- # fulcro (8)
- # gratitude (2)
- # honeysql (1)
- # introduce-yourself (4)
- # kaocha (10)
- # missionary (8)
- # nrepl (4)
- # off-topic (27)
- # portal (32)
- # releases (11)
- # tools-deps (11)
- # xtdb (19)
Bug in the docs for https://clojuredocs.org/clojure.core/quote If I run the example there (quote 1 2 3 4 5) I get
user=> (quote 1 2 3 4 5)
Syntax error (ExceptionInfo) compiling quote at (REPL:1:1).
Wrong number of args (5) passed to quote
It should be noted that quote shorthand `() works fine.
user=> (quote 1 2 3 4 5)
Syntax error (ExceptionInfo) compiling quote at (REPL:1:1).
Wrong number of args (5) passed to quote
user=> (list 1 2 3 4 5)
(1 2 3 4 5)
user=> '(1 2 3 4 5)
(1 2 3 4 5)
It used to work on Clojure 1.5... let me see what other versions it works on...
OK, it changed in Clojure 1.8:
$ for v in 1 2 3 4 5 6 7 8 9 10 11; do echo Clojure 1.$v; clojure -M:1.$v -e '(quote 1 2 3 4 5)'; done
Clojure 1.1
user-loaded
1
Clojure 1.2
user-loaded
1
Clojure 1.3
user-loaded
1
Clojure 1.4
user-loaded
1
Clojure 1.5
user-loaded
1
Clojure 1.6
user-loaded
1
Clojure 1.7
user-loaded
1
Clojure 1.8
user-loaded
Exception in thread "main" clojure.lang.ExceptionInfo: Wrong number of args (5) passed to quote {:form (quote 1 2 3 4 5)}, compiling:(NO_SOURCE_PATH:1:1)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875)
...
I updated the example on that page.
(anyone can update examples if they create an account)
'()
has always been ()
but (quote)
` used to be nil
(up until Clojure 1.8)
$ for v in 1 2 3 4 5 6 7 8 9 10 11; do echo Clojure 1.$v; clojure -M:1.$v -e "['() (quote)]"; done
Clojure 1.1
user-loaded
[() nil]
Clojure 1.2
user-loaded
[() nil]
Clojure 1.3
user-loaded
[() nil]
Clojure 1.4
user-loaded
[() nil]
Clojure 1.5
user-loaded
[() nil]
Clojure 1.6
user-loaded
[() nil]
Clojure 1.7
user-loaded
[() nil]
Clojure 1.8
user-loaded
Exception in thread "main" clojure.lang.ExceptionInfo: Wrong number of args (0) passed to quote {:form (quote)}, compiling:(NO_SOURCE_PATH:1:6)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875)
Where do the docs say (quote)
is the same as '()
?
You misunderstand the equivalence...
'some-form
is a reader shorthand for (quote some-form)
but that is a singular Clojure form.
When things happen in the reader, they happen on a (single) per-form basis.
(list x y z)
will evaluate the arguments, '(x y z)
will not
Because (quote (x y z))
is (x y z)
-- the literal form.
user=> (def x 1)
#'user/x
user=> (def y 2)
#'user/y
user=> (def z 3)
#'user/z
user=> (list x y z)
(1 2 3)
user=> '(x y z)
(x y z)
BTW, your avatar keeps reminding me of https://en.wikipedia.org/wiki/London_Underground#/media/File:Underground.svg (I'm from the UK).
Something to keep in mind is http://clojuredocs.org is a third party documentation site with user contributed examples
http://clojure.org is the definitive source, but it is very spare
(and they've been contributed over a ten year period, roughly, while Clojure has changed over that time -- while it is mostly backward compatible, and especially so around actual officially documented behavior, there is still a lot of undefined behavior that has changed, usually with undocumented and unintended behavior becoming illegal)
Another way this could be explained - cons is a function. A function evaluates its arguments. lazy-seq is a macro. It does not evaluate its arguments. It emits code. That code is the form, wrapped in a thunk, which is passed to a LazySeq constructor. When you realize a lazy seq the thunk is realized internally.
Not sure where exactly the compiler is failing. It doesn’t say the line number just app.core/eval13726 (NO_SOURCE_FILE:1)
Well, basically I’m just trying to pull a path parameter out of the request and return it…
I spent the last 2 days figuring out how this can be achieved there’s just no where an easy to follow tutorial
int?
won't work until you add
{:coercion coercion-spec/coercion
:middleware [coercion/coerce-request-middleware]}
options to your router or routeyou might want to add coercion/coerce-exceptions-middleware
for better error messages coercion related
yap I noticd that only later but I got it working by now… boy there is just way too much stuff to digest
I guess so… I only wish their documents were a bit more hands-on… there is not a single example about extracting path parameters. Now I’m reading up on map deconstruction. I think that is what is going on in the lambda, right?
see the “Associative Destructuring” section from https://clojure.org/guides/destructuring
there's no need to use :keys for only one key
that’s true…. still exploring 🙂
I think I’m getting it
Hello! I heard that pr-str
and read-string
has bad performance. How about clojure.tools.reader.edn/read-string
performance?
Bad is quite subjective. If function calls are on the critical execution paths and that is not the performance required it is simple to test function performance with https://github.com/hugoduncan/criterium Otherwise,the execution speed of a function may not matter
I understand thanks. Anyway, what is the fastest way to serialize Clojure data structures in ClojureScript? We still can compare how those libs are faster relative to each other.
How do you want to read it? #transit is a format designed for fast serialization / deserialization. But it's not human readable.
I only case to pack it and unpack it at another end of the network. It has to be performant.
If you don't need to encode arbitrary clojure data structures, you might find even faster options.
Thanks, everyone for the nice advice. I will test and measure all those options :smiling_face_with_3_hearts:
Hello. I have a function that takes in an item and then constructs a query (executed on Postgres db) to get the last_updated flag for this item. I need to get the last updated for multiple items so my idea was to map over a collection items and make a call for each one (map (fn [item] (get-last-updated item))
. However, this doesn't seem to work. It is returning nil
in the resulting collection. If I call it for one (get-last-updated (first items))
item it gives me the correct timestamp. Anyone know what could be causing this?
It could have something to do with the function. Does it need an environment to work? Like does it need a DB connection to be established first, or something to be setup?
Map is lazy, so maybe it escapes the environment and that's why the function returns nil.
You could try replacing map
for mapv
The connection it might. I tried replacing it with mapv
and pmap
but same result
I would add a println or something inside get-last-updated, just to be sure it is being called properly
And it be good if you printed the item it receives, so you can see if that works too.
Hi, newbie question: What is the proper use for repl to reap the benefits, especially in say a reagent project? For example: 1. For a normal CLI project, you can evaluate a line of code, a block or a whole file and run the repl...is there more? 2. For clojurescript (say reagent) project, how do you take advantange of the repl? You already have hot-reload type of feature: that is if you change code you can immediately see the changes on the browser. What does the REPL offer in this case? Thanks
Correct, the REPL lets you evaluate arbitrary code and hot-swap existing defs and defns for new ones.
This is true in Clojurescript as well, even if you use reagent. Not sure what a function does if you pass it nil
? Just try it in the REPL and see for yourself.
Want to inspect some state in your app? Why not look it up in the REPL?
Now you're saying you've got hot-reload setup for Clojurescript on save? So I'm assuming you've got figwheel or shadow-cljs setup?
Those are effectively more complex REPLs. They use the same underlying principle and technology to hot-reload the app in the browser while maintaining some of the application state between reloads. That's the difference with just refreshing the page.
What the REPL also is often used in Clojure and Clojurescript is for your IDE features. It'll often give you auto-completion, jump to definition, ways to inspect thrown error and have the error highlighted where it was thrown on the code. Show the documentation for a function, show the macroexpansion of a macro, etc. So maybe you don't need it, but your IDE might benefit so it can give you all these additional features.
This might show it a little, it is doing react-native with expo, but it shows a bit why the REPL is nice even if it hot-reloads as you save: https://youtu.be/bSi7GpcSsYU?t=309 The REPL bit starts at 5:09
In his case, he's mostly showing to use it for inspection, but he's also getting auto-complete and all other kind of features due to it. And you can use it to explore and experiment with functions and all that as well to learn APIs quickly and test things.
If you use Cursive, you owe it to do one thing. Make a shortcut for eval bound to say Ctrl+Enter or something super easy. I don't know why Cursive doesn't have shortcuts for them by default, but without them, it is really hard to start to use a REPL workflow
Assign yourself easy shortcuts for all the functions mentioned here: https://cursive-ide.com/userguide/repl.html#interaction-with-the-editor
Oh, and never type in the actual REPL window. Always use those commands that you now have shortcuts for, and you use them when inside the actual source code files.
Ya, so like once you've got your shortcuts, the idea is you can put your cursor anywhere (right after the form) and Ctrl+Enter (say that was your shortcut) and it'll evaluate that form and show the result in the REPL window. You can also reload things by reloading the NS. And I think Cursive doesn't automatically run what you eval in the context of the file. That means you need to use its Switch NS command to switch your REPL to the namespace of the file you are in and then you can Ctrl+Enter into it.