beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
inawarminister 2021-06-16T00:51:17.193400Z

Is there a way to print the sequence index inside a for function into a string?

(for [n (rest (read-column "resources\\in-file.csv" 0))]
        (if (string? n)
          (write-check-result (str "line" sequence-index "ok"))
          (write-check-result (spec/explain (string? n))))))
how do I acquire the value of sequence-index? Thank you

tws 2021-06-16T14:57:47.233200Z

on second look, maybe you can expand your use of spec to just spec the CSV file and validate it.

tws 2021-06-16T01:36:13.193500Z

i might try map-indexed instead (tho having a side effect in there seems offputting). but using for, you could always loop n over the count of columns, then use a :let to set the column contents

zackteo 2021-06-16T04:42:34.194300Z

What can I do to read a string like "[17877, 56808]\n2205309.80008291\n" ? read-string will only read the first part

alexmiller 2021-06-16T04:58:25.195Z

use read multiple times on a StringReader

seancorfield 2021-06-16T05:00:35.195300Z

user=> (require '[clojure.edn :as edn])
nil
user=> (let [input "[17877, 56808]\n2205309.80008291\n"]
          (with-in-str input
             (println (edn/read))
             (println (edn/read))))
[17877 56808]
2205309.80008291
nil
user=>
☝️:skin-tone-2: Another option.

alexmiller 2021-06-16T05:00:55.195500Z

seems like mostly the same option :)

zackteo 2021-06-16T05:19:35.197Z

Thanks 🙂 This works. But how would I store/hold the value for later use then?

seancorfield 2021-06-16T05:24:39.197600Z

@zackteo Do you just want to produce a sequence of things that were read, until you run out?

zackteo 2021-06-16T05:26:27.198800Z

That would be good but am thinking more about reading the values and putting them into a map. From which I can send as data to the frontend

seancorfield 2021-06-16T05:29:09.199500Z

user=> (let [input "[17877, 56808]\n2205309.80008291\n"]
          (with-in-str input
            (loop [xs [] x (edn/read {:eof ::done} *in*)]
               (if (= ::done x) xs (recur (conj xs x) (edn/read {:eof ::done} *in*))))))
[[17877 56808] 2205309.80008291]
user=>
You can build whatever data structure you want.

zackteo 2021-06-16T05:30:38.200300Z

Let me look into that! Thank you! :)

dabrazhe 2021-06-16T06:49:01.203600Z

How can I render numbers to have 2 decimals: n.nn ? eg 1.1 should be 1.10, 1 should be 1.00.

dabrazhe 2021-06-16T09:46:25.212500Z

It becomes a string. Would it be possible for the number to stay a number, like {:strike 41.00 :bid 4.40} ?

tvirolai 2021-06-16T09:59:22.212800Z

No, since the trailing zeroes don't carry any information. When printing them, they can be formatted in different ways but not like that

alexmiller 2021-06-16T11:01:42.219300Z

You can set scale if you’re using BigDecimals (M suffix on number literals)

1👍
tvirolai 2021-06-16T06:57:47.203700Z

format is your friend in this: https://clojuredocs.org/clojure.core/format

tvirolai 2021-06-16T06:58:20.203900Z

(format "%.2f" 1.1) => "1.10"

1👍
sb 2021-06-16T07:42:03.206Z

If I have a lookup index, but I would like to use two eg. {"a" {:a "a" :b: "b" ...}} index, not just “a”,.. “b” etc.. so what is the best way/ practice? (from performance view)

solf 2021-06-16T07:46:50.206100Z

You mean nested maps?

sb 2021-06-16T07:50:16.206300Z

I would like to add Indexes, maybe the juxt example more helpful (I don’t generate in this way the things, but the result is same):

;; Create lookup maps via a specific key

(defn index-by [coll key-fn]
    (into {} (map (juxt key-fn identity) coll)))
;; #'user/index-by

(index-by [{:id 1 :name "foo"} 
           {:id 2 :name "bar"} 
           {:id 3 :name "baz"}] :id)
;;=> {1 {:name "foo", :id 1}, 
;;    2 {:name "bar", :id 2}, 
;;    3 {:name "baz", :id 3}}

(index-by [{:id 1 :name "foo"} 
           {:id 2 :name "bar"} 
           {:id 3 :name "baz"}] :name)
;;=> {"foo" {:name "foo", :id 1}, 
;;    "bar" {:name "bar", :id 2}, 
;;    "baz" {:name "baz", :id 3}}

sb 2021-06-16T07:50:46.206500Z

I would like to use two index, of course I can solve that in some way in clojure, just what is the best?

sb 2021-06-16T07:53:16.206800Z

eg {[“a” “b”] {…} [“c” “d”] {…}} I hope in this way more understable

2021-06-16T07:53:39.207Z

There is at least one problem with #_ as a test-skipper — it is not possible to get a warning that the code base has such tests 😉

solf 2021-06-16T07:55:12.207200Z

I’m not sure if I understand correctly. Something like this?

(index-by [{:id 1 :name "foo"} 
           {:id 2 :name "bar"} 
           {:id 3 :name "baz"}]
          (juxt :id :name))
;; => {[1 "foo"] {:id 1, :name "foo"},
;;     [2 "bar"] {:id 2, :name "bar"},
;;     [3 "baz"] {:id 3, :name "baz"}}

solf 2021-06-16T07:55:37.207400Z

Replacing a simple keyword like :name by (juxt :id :name))

sb 2021-06-16T07:56:07.207600Z

Yes, something similar, but I would like to search by first and second argument too (indepently)

sb 2021-06-16T07:56:23.207800Z

I would like to find all “bar” in the map

sb 2021-06-16T07:56:57.208Z

of course I can do like map or for cycle to do that.. is there any faster solution?

sb 2021-06-16T07:57:40.208200Z

{[1 "foo"] {:id 1, :name "foo"},
;;     [2 "bar"] {:id 2, :name "bar"},
;;     [3 "baz"] {:id 3, :name "baz"}}
-> get all “bar” from map, is that possible in Clojure?

solf 2021-06-16T07:57:57.208400Z

Well yeah it’s possible, but it’s not going to be performant

indy 2021-06-16T07:58:00.208600Z

Fastest is to just copy the same values for the keys "foo" and "bar" and have it in the same map sort of like how DB indexing is done. References to the values would be efficient but that is place oriented programming which clojure discourages

1👍
solf 2021-06-16T07:58:03.208800Z

we will need to filter

solf 2021-06-16T07:58:24.209100Z

I would make multiple indexes yeah

sb 2021-06-16T07:59:42.209500Z

Ok, in this case I do it in this way. Thanks!

km 2021-06-16T08:42:58.210500Z

Any idea why this doesn't work? ((symbol "+") 2 2) => 2

2021-06-16T08:45:59.210700Z

symbols in clojure implement function interface to work as a getter for associative collections: ((symbol "+") {'+ 42} :not-found) ;; => 42

2021-06-16T08:47:40.211Z

in your example it simply tries to look up for symbol '+ in 2 which is not a collection and falls back to return second argument as “not found” ((symbol "+") 2 3) ;; => 3

2021-06-16T08:49:35.211200Z

I think you want to resolve the symbol before calling it as a function. For that you could rewrite your expression like that: ((resolve (symbol "+")) 2 2) ;; => 4

1❤️1✅
km 2021-06-16T08:53:57.211400Z

hmm.. ((resolve '+) 2 2) seems to work, but not ((resolve (symbol "+")) 2 2)

2021-06-16T09:07:46.211600Z

works for me, what is the output of (resolve (symbol "+"))?

km 2021-06-16T09:10:33.211800Z

hmm! it wasn't working in a clojurescript environment. I switched to clojure and it works

km 2021-06-16T09:13:13.212Z

I think my final code will run on clojure, so I should be fine. In clojurescript, however;

(resolve (symbol "+"))
Encountered error when macroexpanding cljs.core/resolve.
AssertionError: Assert failed: Argument to resolve must be a quoted symbol
(core/and (seq? quoted-sym) (= (quote quote) (first quoted-sym)))
	cljs.core/resolve (core.cljc:3417)
	cljs.core/resolve (core.cljc:3414)
	clojure.core/apply (core.clj:671)
	clojure.core/apply (core.clj:662)
	cljs.analyzer/macroexpand-1*/fn--2641 (analyzer.cljc:3883)
	cljs.analyzer/macroexpand-1* (analyzer.cljc:3881)
	cljs.analyzer/macroexpand-1* (analyzer.cljc:3868)
	cljs.analyzer/macroexpand-1 (analyzer.cljc:3932)
	cljs.analyzer/macroexpand-1 (analyzer.cljc:3928)
	cljs.analyzer/analyze-seq (analyzer.cljc:3965)
	cljs.analyzer/analyze-seq (analyzer.cljc:3945)
	cljs.analyzer/analyze-form (analyzer.cljc:4154)
	cljs.analyzer/analyze-form (analyzer.cljc:4151)
	cljs.analyzer/analyze* (analyzer.cljc:4207)
	cljs.analyzer/analyze* (analyzer.cljc:4199)
	shadow.build.compiler/analyze/fn--12348 (compiler.clj:264)
	shadow.build.compiler/analyze (compiler.clj:252)
	shadow.build.compiler/analyze (compiler.clj:211)
	shadow.cljs.repl/repl-compile/fn--14038/fn--14039 (repl.clj:462)
	shadow.cljs.repl/repl-compile/fn--14038 (repl.clj:435)
	shadow.cljs.repl/repl-compile (repl.clj:433)
	shadow.cljs.repl/repl-compile (repl.clj:430)
	shadow.cljs.repl/process-read-result (repl.clj:521)
	shadow.cljs.repl/process-read-result (repl.clj:497)
	shadow.cljs.repl/process-input (repl.clj:681)
	shadow.cljs.repl/process-input (repl.clj:659)
	shadow.cljs.devtools.server.worker.impl/fn--14568 (impl.clj:754)
	shadow.cljs.devtools.server.worker.impl/fn--14568 (impl.clj:744)
	clojure.lang.MultiFn.invoke (MultiFn.java:234)
	shadow.cljs.devtools.server.util/server-thread/fn--14231/fn--14232/fn--14240 (util.clj:284)
	shadow.cljs.devtools.server.util/server-thread/fn--14231/fn--14232 (util.clj:283)
	shadow.cljs.devtools.server.util/server-thread/fn--14231 (util.clj:256)
	java.lang.Thread.run (Thread.java:829)

dabrazhe 2021-06-16T09:46:25.212500Z

It becomes a string. Would it be possible for the number to stay a number, like {:strike 41.00 :bid 4.40} ?

tvirolai 2021-06-16T09:59:22.212800Z

No, since the trailing zeroes don't carry any information. When printing them, they can be formatted in different ways but not like that

Sebastian 2021-06-16T10:06:25.217100Z

Is there a better way to write this? I want to extract some values from a list of arguments ({arg-name :some-keyword1 :arg-value "somevalue1"} {arg-name :some-keyword2 :arg-value "somevalue2"}), and turn those into key value pairs for a new map {:some-keyword1 somevalue1 :some-keyword2 :somevalue2) . Currently my approach is to extract both values into a vector while mapping over each argument. I then convert it to a map using into. However it does seem like there might be an easier way of converting it to map, without having to create multiple vectors first

(defn get-args-value [args keywords]
  (mapv (fn [arg]
          (let [arg-name (:arg-name arg)
                arg-value (Integer/parseInt (get-in arg [:arg-value :value]))]
            (if (contains? keywords arg-name)
              [arg-name arg-value]
              [])))
        args))

(defn get-values [args keywords]
  (into {} (get-args-value args keywords)))

Kuldeep Sengar 2021-06-16T10:34:42.217600Z

(def datum '({:arg-name :some-keyword1 :arg-value "somevalue1"} {:arg-name :some-keyword2 :arg-value "somevalue2"}))

(reduce (fn [init data] (assoc init (:arg-name data) (:arg-value data))) {} datum)
how about this ?

Sebastian 2021-06-16T10:50:16.217900Z

Yea, that might actually do it! Thanks

2021-06-16T11:00:27.218100Z

right, because in clojurescript resolve is a macro and accept only quoted symbol.

alexmiller 2021-06-16T11:01:42.219300Z

You can set scale if you’re using BigDecimals (M suffix on number literals)

1👍
2021-06-16T11:03:18.219500Z

a bit shorter version based on transducers (into {} (map (juxt :arg-name :arg-value)) datum)

1🙌
ryan 2021-06-16T11:41:21.220700Z

Can probably combine function into one, like:

(defn get-args-value [args keywords]
	(->> args
		(filter #(contains? keywords (:arg-name %)))
		(map (juxt :arg-name :arg-value))
		(into {})))

olaf 2021-06-16T11:45:47.223400Z

shadow-cljs+reagent: App created with https://github.com/reagent-project/reagent-template. 1. I split my code from project.core in src/cljs/project/core.cljs in another different namespace (path src/cljs/project/lib.cljs ns project.lib ). 2. Imported lib from core.cljs as [project.lib :as lib] 3. Changed .edn file as follow

;; shadow.cljs.edn
{:lein         {:profile "+shadow-cljs"}
 :builds       {:app {:target     :browser
                      :output-dir "resources/public/js"
                      :asset-path "/js"
                      :modules    {:app {:entries [project.core]}
                                   :lib {:entries [project.lib]}} 
I got this error during shadow-cljs app compilation
[:app] Configuring build.
[:app] Build failure:
two modules without deps, please specify which one is the default
{:a :app, :b :lib}
ExceptionInfo: two modules without deps, please specify which one is the default

olaf 2021-06-16T11:52:12.224500Z

I don't know how to declare the deps. Lib is just a library with some functions, core.cljs uses them to display stuff

John Preston 2021-06-16T11:53:39.225400Z

How can I import a Java class at runtime? I have a class which is only present in some environments, so I want to load it and use a static method if it's available, otherwise I want to do something else 🙂

2021-06-16T12:08:46.225500Z

you can import it, like so:

(import java.util.Base64)

2021-06-16T12:09:08.225700Z

Then you can call static methods on it, like so:

(Base64/getDecoder)
;; => #object[java.util.Base64$Decoder 0x5b577674 "java.util.Base64$Decoder@5b577674"]

2021-06-16T12:10:04.225900Z

If you're not sure whether the class is available, you should wrap that in a try/catch

John Preston 2021-06-16T12:10:40.226100Z

I tried that but the compiler blows up with ClassNotFoundException, like it's trying to load the class before runtime

John Preston 2021-06-16T12:11:02.226300Z

I might have found a solution using the Reflect API 🤞

2021-06-16T12:13:52.226500Z

I ran it from a REPL, and it works, but maybe it's a macro, in which case what you said makes sense... You can check in clojuredocs,there's an example for loading classes dynamically...

2021-06-16T12:14:12.226700Z

;; For cases when 'import' does not do it for you, i.e. "live-coding"
;; You can use the DynamicClassLoader, ClassReader and the Resolver.

(def dcl (clojure.lang.DynamicClassLoader.))

(defn dynamically-load-class! 
  [class-loader class-name]
  (let [class-reader (clojure.asm.ClassReader. class-name)]
    (when class-reader
      (let [bytes (.-b class-reader)]
        (.defineClass class-loader 
                      class-name 
                      bytes
                      "")))))

(dynamically-load-class! dcl "java.lang.Long")
(dynamically-load-class! dcl 'org.joda.time.DateTime)

;; From that point the dynamically loaded class can be
;; used by the Reflector to invoke constructors, methods and to get fields. 

2021-06-16T12:14:27.226900Z

that example is from the clojuredocs page on import

2021-06-16T12:14:37.227100Z

hope that helps!

John Preston 2021-06-16T12:14:41.227300Z

Thanks I'll take a look at this! 😄

1👍
Endre Bakken Stovner 2021-06-16T13:06:04.229100Z

I've read all your replies, thanks!

Endre Bakken Stovner 2021-06-16T13:11:05.229300Z

It seems to me that csrf-tokens should be used for POST requests, but I do not see an easy way to get the csrf-token when I am sending requests from the command line. Perhaps this is a question for #ring rather

Apple 2021-06-16T13:59:59.229600Z

if you have to you could expose an api over http get to allow clients to get the token. i'm not sure one way or another if that's safe practice.

2021-06-16T14:00:22.229800Z

how is this different from set/intersection? you don't need to compare every map to every map, you just need to check which maps are present in the other set (it will be most efficient if the smaller set is the first arg)

2021-06-16T14:03:01.230Z

never mind, it's fast regardless of arg order

cmd)user=> (time (s/intersection #{{:a 0}} (into #{} (map (partial hash-map :a)) (range 10000))))
"Elapsed time: 5.630487 msecs"
#{{:a 0}}
(cmd)user=> (time (s/intersection (into #{} (map (partial hash-map :a)) (range 10000)) #{{:a 0}}))
"Elapsed time: 4.806462 msecs"
#{{:a 0}}

Endre Bakken Stovner 2021-06-16T14:05:42.230200Z

I do not know either. Or since it is one user/one server I could add a password, but then I'd need to read up on how to send/store these safely.

2021-06-16T14:09:45.230400Z

what's that doing that you wouldn't get from

user=> (Class/forName "java.lang.Number")
java.lang.Number

2021-06-16T14:11:56.230700Z

I am probably missing something, because to me the one liner literally does what is asked for here but I'm sure the steps the other code takes are important to some use case

2021-06-16T14:55:47.233Z

using the medley library:

(def datum '({:arg-name  :some-keyword1
              :arg-value "somevalue1"}
             {:arg-name  :some-keyword2
              :arg-value "somevalue2"}))

(->> datum
     (medley.core/index-by :arg-name)
     (medley.core/map-vals :arg-value))
;; => {:some-keyword1 "somevalue1", :some-keyword2 "somevalue2"}

tws 2021-06-16T14:57:47.233200Z

on second look, maybe you can expand your use of spec to just spec the CSV file and validate it.

Yair Taboch 2021-06-16T15:00:26.234100Z

i have java iterator and i want to make something like (map my-func java-iterator) is it possible?

jkxyz 2021-06-16T15:04:35.234300Z

(map my-func (seq java-iterator)) should work

Yair Taboch 2021-06-16T15:05:58.234500Z

Don't know how to create ISeq from: com.mongodb.MongoCursorAdapter 😞 (MongoCursorAdapter implements Cursor which implements Iterator + closable)

dpsutton 2021-06-16T15:06:59.234800Z

try iterator-seq

1😲
Yair Taboch 2021-06-16T15:08:26.235200Z

thanks! may i ask what it does?

dpsutton 2021-06-16T15:09:15.235500Z

check out (doc iterator-seq)

dpsutton 2021-06-16T15:09:34.235700Z

But high level it just turns the results of an iterator into the clojure seq abstraction

dpsutton 2021-06-16T15:26:24.235900Z

I suspect it has to do with the fact that the import is at runtime but there are functions that must be compiled that use it.

Yair Taboch 2021-06-16T15:30:23.236100Z

awesome. thanks 🙂

piyer 2021-06-16T16:26:51.236800Z

(-> [{:a 1}]
    (map :a))

;; expecting it to return (1)

piyer 2021-06-16T16:27:24.236900Z

I know (map :a) would return a lazy fn, what is the better way to do this?

2021-06-16T16:29:25.237100Z

(map :a) returns a transducing function, not a lazy one

dpsutton 2021-06-16T16:30:32.237300Z

i think you need a thread last here

2021-06-16T16:30:44.237500Z

-> expands to put the previous line in the first position:

user=> (macroexpand '(-> [foo] (map :a)))
(map [foo] :a)

1👍1➕
dpsutton 2021-06-16T16:30:51.237700Z

you're constructing the form (map [{:a 1}] :a)

piyer 2021-06-16T16:32:23.238Z

(->> [{:a 1}]
    (map :a))

piyer 2021-06-16T16:32:30.238200Z

that works!

piyer 2021-06-16T16:32:37.238400Z

dumb mistake

2021-06-16T16:32:51.238700Z

@munichlinux also, -> and ->> are pretty "dumb" tools, they are form rewrites my favorite example:

user=> (->> (+ a b) (let [a 19 b 23]))
42

2🤯
2021-06-16T16:33:12.238900Z

that's not good code, but the way it should surprise you might show you something about those macros

1➕
piyer 2021-06-16T16:35:53.239200Z

well, I like the pipeline that -> helps me to build, what is a better approach, use comp ?

dpsutton 2021-06-16T16:38:44.239400Z

in my head that is officially called the Noisesmith Demonstration

1😆
2021-06-16T16:39:47.239600Z

@munichlinux it's fine to use -> / ->> for building pipelines, that is what they are for, but be aware that they are not "chaining" tools per se, they are tools for convolving forms

2021-06-16T16:40:12.239800Z

so there are corner cases, and the substitution follows textual rules, not program logic rules

1👍
2021-06-16T16:42:21.240100Z

there are a few very common bugs that arise from treating the arrow macros as if they were semantic (they aren't, they are syntactic) here's a classic:

user=> (macroexpand '(-> foo (fn [x] (frob x))))
(fn* foo ([x] (frob x)))
obviously I wanted to provide foo as an arg to the fn. instead, because of the textual rewrite rules, I just used the symbol foo as the name of a new anonymous function without calling it

piyer 2021-06-16T16:43:56.240400Z

so, you would use as-> here?

seancorfield 2021-06-16T17:03:51.240600Z

as-> is intended for use inside -> pipelines for occasional steps that have an argument that is not in the first or last position.

seancorfield 2021-06-16T17:04:45.240800Z

Read https://stuartsierra.com/tag/dos-and-donts for the posts on the threading macros.

1👍
seancorfield 2021-06-16T17:06:56.241200Z

And in the case of calling an anonymous function, the common “trick” is to add extra parens:

(-> foo
    ((fn [x] (frob x))))
although in this case you could simply do
(-> foo
    (frob))
(or just (-> foo frob) but I like the parens to make it really clear it’s a fn call)

Jacob Rosenzweig 2021-06-16T19:44:44.245400Z

Can someone help me deconstruct the parameters for this function?

(defn draw-board!
  "Draw the given board to the canvas."
  ([id board scale theme] (draw-board! id board scale theme 0))
  ([id board scale theme y-cutoff]
   ...))
Is this basically chaining on the second arity definition?

Jacob Rosenzweig 2021-06-16T19:46:39.246Z

It reminds me of constructor chaining in C#.

dpsutton 2021-06-16T19:47:18.246900Z

there's a three arity version and a four arity version. The three arity just calls the four arity version with a y-cutoff parameter with value 0. It's a common pattern for providing defaults or overridable parameters

Jacob Rosenzweig 2021-06-16T19:47:33.247200Z

Yeah we do that a lot at work with classes.

Jacob Rosenzweig 2021-06-16T19:47:40.247500Z

We use that instead of DI frameworks.

2021-06-16T20:00:21.250200Z

It's called function overloading, in this case it's done by arity. So sometimes that specific one is called arity overloading. Where you overload the definition of the function to mean different things based on the number of arguments. But often the implementation is shared, and only parameters differ, thus providing defaults for the smaller arity versions. It's a kind of polymorphism.

dpsutton 2021-06-16T20:06:03.250700Z

that's an excellent explanation but i do not see how it is polymorphism

2021-06-16T20:08:10.251Z

it's polymorphic by argument count

Antonio Bibiano 2021-06-16T20:49:56.257100Z

Hello peeps, i'm moving my first steps in clojure and sometimes I find that it can be useful to know some java concepts to quickly understand an error or do some operation, e.g. (Integer/parseInt "1") might come very quickly to a java developer that know about how Java interop works. So I was wondering if you have any pointers to some java reference material. I can find my way through a large java codebase even, but i'm missing that "working knowledge". Do you think there's any resource like that, also how much java do you think is important to know to be proficient in clojure?

seancorfield 2021-06-16T20:54:15.258400Z

Probably the most useful “Java skill” when learning Clojure is reading/understanding stacktraces. Some understanding of classpaths and dependencies is also useful.

seancorfield 2021-06-16T20:55:17.259100Z

I’m not sure what you’re after for “some java reference material” tho’? https://clojure.org/reference/java_interop

Antonio Bibiano 2021-06-16T20:58:51.262200Z

I was thinking something like a book that i can use to reference java concepts etc. Because many java books that I found are very long and detailed

Antonio Bibiano 2021-06-16T21:00:14.262600Z

actually one book, "Java a beginner's guide"

Antonio Bibiano 2021-06-16T21:04:10.263Z

maybe something like the "In a nutshell" series by oreilly?

seancorfield 2021-06-16T21:11:21.263700Z

I don’t think you need much Java to become effective in Clojure. Lots of people come to Clojure with zero Java experience.

seancorfield 2021-06-16T21:13:47.264500Z

Most Java material is going to be focused on classes, encapsulation, and often mutable member data — none of which is applicable to Clojure.

Antonio Bibiano 2021-06-16T21:15:55.265100Z

Understood, that’s nice to hear :)

seancorfield 2021-06-16T21:16:23.265500Z

If you want to avoid Java interop for turning strings into numbers/data/etc, there’s clojure.edn/read-string which will also read vectors of numbers and various other things.

Antonio Bibiano 2021-06-16T21:18:00.267Z

I guess I’ll keep practicing my clojure and leave this Java stuff for when the need comes

alexmiller 2021-06-16T21:19:39.267200Z

https://www.braveclojure.com/java/ is useful

alexmiller 2021-06-16T21:20:55.267700Z

and this paid course from Eric is probably also very good (but I haven't seen it) https://purelyfunctional.tv/courses/jvm-clojure/

Antonio Bibiano 2021-06-16T21:24:10.268800Z

Ah nice, I’ll check these out!

seancorfield 2021-06-16T21:51:00.270Z

(and the section showing Java interop by using String and methods on it is outdated too: clojure.string is a better way to work with strings that avoids Java interop)

practicalli-john 2021-06-16T22:06:40.270100Z

I'd suggest you dont need more understanding that is covered in the Java interop section of the http://Clojure.org website. https://clojure.org/reference/java_interop Depending what kinds of applications and services, you may not need any Java interop at all. The most common thing I use is the code you mention in your question and only because jetty web server is very fussy about types.