This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # beginners (26)
- # biff (28)
- # calva (13)
- # clj-commons (4)
- # clj-kondo (3)
- # clojure (45)
- # clojure-austin (17)
- # clojure-europe (8)
- # clojure-finland (1)
- # clojurescript (14)
- # code-reviews (3)
- # emacs (33)
- # helix (4)
- # holy-lambda (7)
- # joyride (5)
- # keechma (1)
- # meander (4)
- # membrane (3)
- # missionary (22)
- # nbb (1)
- # off-topic (1)
- # pathom (4)
- # rdf (24)
- # releases (2)
- # sci (3)
- # shadow-cljs (12)
- # tools-deps (14)
Why doesn’t this work?
➜ ~ clojure Clojure 1.11.1 user=> (.getDecoder java.util.Base64) Execution error (IllegalArgumentException) at user/eval1 (REPL:1). No matching field found: getDecoder for class java.lang.Class user=> ^D ➜ ~ java -version openjdk version "19" 2022-09-20 OpenJDK Runtime Environment Temurin-19+36 (build 19+36) OpenJDK 64-Bit Server VM Temurin-19+36 (build 19+36, mixed mode, sharing)
(java.util.Base64/getEncoder). I think the real question is does that code you found work, and if so, how?
Looking at 4clojure exercises. Can someone explain why this solution is equivalent to the
I understand that
(fn [a b] ((vec a) b))
vecconstructs a vector. The docs don’t mention anything about using a vector as a function though. Is this a typical thing to do in clojure?
Vectors implement IFn, for invoke() of one argument, which they presume is an index and look up in themselves as if by nth, i.e. vectors are functions of their indices.
Ah… I see. I missed that part. Kind of like using a map as a function with a key as the argument for lookups. I guess that makes sense.
Hah. So it looks like
is an even more concise way to write it. No need to cast the list to a vec.
(fn [a b] (a b))
Oh but lists and seqs cannot be called as a function. So that would only work if a is a vec.
The reason for the difference by the way is that clojure tries to make it harder to accidentally write non-performant code. Vectors support quick lookup by index but sequences do not: seqs and lists must be traversed from the head.
Hmm… interesting. Just tried it in a real repl and, yeah, it gives the exception you mentioned.
It’s weird that https://4clojure.oxal.org/#/problem/21 said that
(fn [a b] (a b)) passes the tests,
Not sure why the 4clojure implementation accepts that. I think it does not use the Java Clojure implementation (might be using clojurescript or SCI but I haven’t looked into it). The different clojure implementations have some notable and some subtle differences.
That’s good to be aware of. I’m glad I asked. I learned a whole lot from this one topic.
how do I add something to the end of a list? I'm trying to write a macro that adds a finally expression in the end
Because lists are linked lists, it's a bit complicated to add at the end - popular options (to my knowledge) include "reverse, conj, reverse" and concatting the list and a list containing the element to be 'appended'. Having said that, with a macro, a thing that happens sometime is unquote-splicing into a list with the appended thing after that; see as an example
with-out-str in clojure.core
In macro-land you also have the option of
user> (let [xs '(1 2 3)] `(~@xs 4)) (1 2 3 4)
That also seems to work fine in a normal function context. (clojurescript too)
(defn append [m x] `(~@m ~x)) (append '(1 2 3) 4) ;; (1 2 3 4) (append [1 2 3] 4) ;; (1 2 3 4)
yup that’s true, just gets a little more awkward in larger expressions to unquote everything inside the backticked form
Well I was only really suggesting it as a very simple implementation of
append (without multiple traversals of the collection). I don't think you would want to litter your code with a bunch of unquote splicing.
Ya this is always annoying when doing macros. You need to either build things up bottom up, think recursively where you call cons on the way back up. Which basically reverses things, because it puts them on a stack and then pops them into the list. Or you can use the tricks others told you about.