This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-26
Channels
- # adventofcode (2)
- # announcements (7)
- # babashka (20)
- # beginners (77)
- # brompton (6)
- # calva (4)
- # clj-kondo (28)
- # clj-together (1)
- # cljdoc (2)
- # cljfx (10)
- # cljsrn (1)
- # clojure (77)
- # clojure-europe (33)
- # clojure-gamedev (12)
- # clojure-uk (11)
- # clojurescript (95)
- # clojureverse-ops (4)
- # core-async (4)
- # core-logic (1)
- # cryogen (2)
- # cursive (14)
- # data-science (3)
- # datomic (47)
- # duct (1)
- # emacs (7)
- # fulcro (51)
- # gratitude (8)
- # helix (14)
- # hoplon (4)
- # improve-getting-started (60)
- # jobs (1)
- # jobs-discuss (4)
- # joker (11)
- # lsp (99)
- # meander (62)
- # membrane (5)
- # news-and-articles (3)
- # off-topic (64)
- # pathom (3)
- # polylith (11)
- # practicalli (7)
- # react (1)
- # reagent (8)
- # reveal (15)
- # shadow-cljs (78)
- # specter (7)
- # sql (16)
- # tools-build (1)
- # tools-deps (29)
- # workspaces (1)
- # xtdb (17)
I've been playing with clojure for a while now... so I would think I would know the answer to my question by now... but no I don't! When I execute the following:
clj꞉hello-world꞉> (prn "hello")
"hello"
nil
I understand the "hello".... what is the nil for and how to get rid of it?nil
is the return value. prn
is a function that prints its argument(s) and returns nil
. You can't get rid of it. I'm curious why you'd want to, though?
tbf, when I was learning Clojure in the early days, I had precisely the same question. I couldn't understand why a nil was being output when I was simply "running" a function (coming from a java background, this confused me a lot!). It wasn't until later, with the help of others, that I learnt that everything is evaluated in Clojure and everything returns a value, it just that sometimes that value is nil and with the help of nil-puning, those nils are handled appropriately. So, @U022LK3L4JJ everything is fine, a nil is to be expected, it just means there's no "return" from the function, like a map, or a literal, or a vector or whatnot, the function evaluated, it did what it needed to do and then finished 😉
No need to fear the nils 🙂 Not like in Java etc., where it's often a source of NPE's. Clojure uses a technique called nil-puning
(which is a LISPy thing) to handle nils and reduce the chances of a NPE.
Thanks for that @U11EL3P9U!! @U4ZDX466T: I got stuck on this because I was trying to get a simple test function evaluated using lein test... like...
(deftest hello-world-test
(is (= "hello" (hello-world/hello))))
... and because of the nil it kept on failing even though I was printing the "hello"... in the end instead of using prn I had to use str and then the nil disappeared!!Yes, since as @U4ZDX466T alluded to, the prn
function is a function that outputs (to the console) a string. It does that, and nothing else (i.e., it has a side-effect, it mutates external state, with that state being the console 🙂 ). Once it has done outputting to the console, it returns nil (since it doesn't really know if that was successful or not, ultimately it just passes the request along all the way to the kernel for it to do something. Whether or not a string actually gets displayed on the console isn't it's concern!). So it returns nil
. The str
function, on the other hand, calls .toString()
on the something, which does return a string, i.e., the str
function evals and returns a String.
from with-out-str at http://clojuredocs.org
;; Instead of printing, the following will place the output normally
;; sent to stdout into a string.
neato.the core misunderstanding here is a common one when starting with the REPL - returning something and printing something look the same, because the Read Eval Print Loop implicitly prints all return values
all return values are printed, not all prints are return values :D
its not shorter but
(defn reverse-if [pred val]
(cond-> val
(pred val) (str/reverse)))
(for [name ["welcome" "to" "clojure"]]
(reverse-if #(>= (count %)) name))
(for [word ["Welcome" "to" "clojure"]]
(if (>= (count word) 5)
(str/reverse word)
word))
since there is nothing "wrong" with how you did it it all comes down to personal taste
I like the map
implementation. Can you use when
with reduce
in this case?
Maybe reduce
don't make no sense.
@U050ECB92 Do you mean like this?
I’m trying to pull values from a few keys here… what would be a good way to do this so that I can loop through or map over the values? For lack of better words. How would I go about placing ALL of my retrieved books titles and authors in a list on a website. Something similar to “for item in items”?
if you want maps out, select-keys
. if you want vectors, juxt
(select-keys {:author "Haruki Murakami",
:description "Really cool and something we should read",
:genre "fiction",
:id 3,
:own true,
:pages 500,
:reading "Yes",
:title "The Commendatore"}
[:author :title])
{:author "Haruki Murakami", :title "The Commendatore"}
((juxt :author :title) {:author "Haruki Murakami",
:description "Really cool and something we should read",
:genre "fiction",
:id 3,
:own true,
:pages 500,
:reading "Yes",
:title "The Commendatore"})
["Haruki Murakami" "The Commendatore"]
^^ examples on a single map
@alexmiller oh! Ok, that works. Much cleaner.
(map (juxt :title) (db/query (db/get-all-books)))
well if you've only got one attribute, then just (map :title ...)
really depends what you want out
Alex, no there’ll be more…but that gives me the general idea. I believe I can get what I want done now. Thank you 😛
Hi there!
I run my code using lein run
and get a syntax error, but error message is not clear. For example, I don’t see the line number where error happened. I don’t understand how to debug such errors and scary to think about more big application in Clojure.
Syntax error (ClassCastException) compiling at (/private/var/folders/8z/4psycrbn67d1wsb2sy41sjzm0000gn/T/form-init14777450300486844710.clj:1:126).
class java.lang.String cannot be cast to class clojure.lang.IFn (java.lang.String is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')
Full report at:
/var/folders/8z/4psycrbn67d1wsb2sy41sjzm0000gn/T/clojure-9691563272031495588.edn
How to debug such errors?java.lang.String cannot be cast to class clojure.lang.IFn
most likely means you are somewhere trying to invoke an expression with a string for a function, like ("abc" 123)
if you look at the full report /var/folders/8z/4psycrbn67d1wsb2sy41sjzm0000gn/T/clojure-9691563272031495588.edn
it should tell you where that's happening
the default for exceptions like this was changed to put them in a temporary file which is what is reported, rather than the stack trace
is it a regular thing for Clojure? Or may be there is some compiler flag to make it a bit easier ?
generally, the way to avoid debugging things by running your program at the command line, and instead use a REPL-connected editor to write and debug your code interactively
If I have an unused binding in a defn what can I do, like what do I replace it for?
i'm a big fan of using (defn foo [_the-thing] ...)
a name but prefixed with an underscore to keep the context of the thing you are ignoring. Note you don't have to do anything
Thank you, using _ worked! I didn't get any error but I got a warning about the unused binding
From the linter, I assume? Clojure itself doesn't care.
I get a wrong number of args error even if I'm not using the binding. Replicating this on a repl gives me the same error, how does it work?
Can you show the code? Sounds like you genuinely have the wrong number of arguments.
(defn -main [& _args] ..)
Any idea why clj fails while lein/project.clj seems ok?
{:deps {org.clojure/clojure {:mvn/version "1.10.1"}
incanter/incanter {:mvn/version "1.5.7"}
org.clojure/math.numeric-tower {:mvn/version "0.0.4"}
me.raynes/fs {:mvn/version "1.4.6"}
org.clojure/tools.cli {:mvn/version "1.0.194"}}
:paths ["src" "data"]}
(defproject cljds/ch1 "0.1.0"
:description "Example code for the book Clojure for Data Science"
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.10.1"]
[incanter/incanter "1.5.7"]
[org.clojure/math.numeric-tower "0.0.4"]
[me.raynes/fs "1.4.6"]]
:resource-paths ["data"]
:aot [cljds.ch1.core]
:main cljds.ch1.core
:repl-options {:init-ns cljds.ch1.examples}
:profiles {:dev {:dependencies [[org.clojure/tools.cli "1.0.194"]]}}
:jvm-opts ["-Xmx2G"])
this is the error "Error building classpath. Could not find artifact bouncycastle:bctsp-jdk14:jar:138 in central (
Looks like a Maven relocation, which tools.deps
does not support yet https://search.maven.org/artifact/bouncycastle/bctsp-jdk14
@alexmiller There's a JIRA issue for supporting artifact relocation?
sorry, I'm in debian clojure bof right now, but it's maybe the first TDEPS ticket
https://clojure.atlassian.net/browse/TDEPS-8 (which actually references that specific artifact!)
yep, that's the one
there are a couple things that are going to require work in similar areas - relocations, support for libs in groupIds that start with a number, etc. at some point I will work on those as a unit
despite its age, I am aware of this ticket and will get to it eventually
And folks can vote for it outside of JIRA via https://ask.clojure.org/index.php/7836/tools-deps-does-not-handle-maven-relocations
as you can see by the votes, surprisingly few people have hit this (as relocations are relatively rare)
One test depends on the result of another (the result is generated from 3rd party API)
Yeah, if one test depends on another test executing first, what you really have is one test with multiple act/assert stages.
Yeah, 2nd option is definitely better, but I’ll stick with the first for now :P Thanks @dpsutton
If you have to do this, you can still describe your subtests within a deftest
with testing
blocks:
(deftest my-test
(testing "my sanity"
(is (= 4 (+ 2 2))))
(testing "your sanity"
(is (= 4 (* 2 2)))))
There is also test-ns-hook
which allows you to control the order your tests are called. This is maybe a bit esoteric but you can read about in the https://clojure.github.io/clojure/clojure.test-api.html. Unless you really, really (really?) need it, I wouldn’t use it.