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 youon second look, maybe you can expand your use of spec to just spec the CSV file and validate it.
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
What can I do to read a string like "[17877, 56808]\n2205309.80008291\n"
? read-string
will only read the first part
use read
multiple times on a StringReader
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.seems like mostly the same option :)
Thanks 🙂 This works. But how would I store/hold the value for later use then?
@zackteo Do you just want to produce a sequence of things that were read, until you run out?
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
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.Let me look into that! Thank you! :)
How can I render numbers to have 2 decimals: n.nn ? eg 1.1 should be 1.10, 1 should be 1.00.
It becomes a string. Would it be possible for the number to stay a number, like {:strike 41.00 :bid 4.40}
?
No, since the trailing zeroes don't carry any information. When printing them, they can be formatted in different ways but not like that
You can set scale if you’re using BigDecimals (M suffix on number literals)
format
is your friend in this: https://clojuredocs.org/clojure.core/format
(format "%.2f" 1.1) => "1.10"
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)
You mean nested maps?
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}}
I would like to use two index, of course I can solve that in some way in clojure, just what is the best?
eg {[“a” “b”] {…} [“c” “d”] {…}} I hope in this way more understable
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"}}
Replacing a simple keyword like :name
by (juxt :id :name))
Yes, something similar, but I would like to search by first and second argument too (indepently)
I would like to find all “bar” in the map
of course I can do like map or for cycle to do that.. is there any faster solution?
{[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?Well yeah it’s possible, but it’s not going to be performant
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
we will need to filter
I would make multiple indexes yeah
Ok, in this case I do it in this way. Thanks!
Any idea why this doesn't work? ((symbol "+") 2 2) => 2
symbols in clojure implement function interface to work as a getter for associative collections: ((symbol "+") {'+ 42} :not-found) ;; => 42
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
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
hmm.. ((resolve '+) 2 2)
seems to work, but not ((resolve (symbol "+")) 2 2)
works for me, what is the output of (resolve (symbol "+"))
?
hmm! it wasn't working in a clojurescript environment. I switched to clojure and it works
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)
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)))
(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 ?Yea, that might actually do it! Thanks
right, because in clojurescript resolve
is a macro and accept only quoted symbol.
a bit shorter version based on transducers
(into {} (map (juxt :arg-name :arg-value)) datum)
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 {})))
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
I don't know how to declare the deps
. Lib is just a library with some functions, core.cljs
uses them to display stuff
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 🙂
you can import
it, like so:
(import java.util.Base64)
Then you can call static methods on it, like so:
(Base64/getDecoder)
;; => #object[java.util.Base64$Decoder 0x5b577674 "java.util.Base64$Decoder@5b577674"]
If you're not sure whether the class is available, you should wrap that in a try/catch
I tried that but the compiler blows up with ClassNotFoundException, like it's trying to load the class before runtime
I might have found a solution using the Reflect API 🤞
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...
;; 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.
that example is from the clojuredocs page on import
hope that helps!
Thanks I'll take a look at this! 😄
what's that doing that you wouldn't get from
user=> (Class/forName "java.lang.Number")
java.lang.Number
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
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"}
i have java iterator and i want to make something like (map my-func java-iterator)
is it possible?
(map my-func (seq java-iterator))
should work
Don't know how to create ISeq from: com.mongodb.MongoCursorAdapter 😞 (MongoCursorAdapter implements Cursor which implements Iterator + closable)
try iterator-seq
thanks! may i ask what it does?
check out (doc iterator-seq)
But high level it just turns the results of an iterator into the clojure seq abstraction
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.
awesome. thanks 🙂
(-> [{:a 1}]
(map :a))
;; expecting it to return (1)
I know (map :a)
would return a lazy fn, what is the better way to do this?
(map :a)
returns a transducing function, not a lazy one
i think you need a thread last here
->
expands to put the previous line in the first position:
user=> (macroexpand '(-> [foo] (map :a)))
(map [foo] :a)
you're constructing the form (map [{:a 1}] :a)
(->> [{:a 1}]
(map :a))
that works!
dumb mistake
@munichlinux also, ->
and ->>
are pretty "dumb" tools, they are form rewrites
my favorite example:
user=> (->> (+ a b) (let [a 19 b 23]))
42
that's not good code, but the way it should surprise you might show you something about those macros
well, I like the pipeline that ->
helps me to build, what is a better approach, use comp
?
in my head that is officially called the Noisesmith Demonstration
@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
so there are corner cases, and the substitution follows textual rules, not program logic rules
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 itso, you would use as->
here?
as->
is intended for use inside ->
pipelines for occasional steps that have an argument that is not in the first or last position.
Read https://stuartsierra.com/tag/dos-and-donts for the posts on the threading macros.
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)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?It reminds me of constructor chaining in C#.
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
Yeah we do that a lot at work with classes.
We use that instead of DI frameworks.
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.
that's an excellent explanation but i do not see how it is polymorphism
it's polymorphic by argument count
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?
Probably the most useful “Java skill” when learning Clojure is reading/understanding stacktraces. Some understanding of classpaths and dependencies is also useful.
I’m not sure what you’re after for “some java reference material” tho’? https://clojure.org/reference/java_interop
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
actually one book, "Java a beginner's guide"
maybe something like the "In a nutshell" series by oreilly?
I don’t think you need much Java to become effective in Clojure. Lots of people come to Clojure with zero Java experience.
Most Java material is going to be focused on classes, encapsulation, and often mutable member data — none of which is applicable to Clojure.
Understood, that’s nice to hear :)
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.
I guess I’ll keep practicing my clojure and leave this Java stuff for when the need comes
https://www.braveclojure.com/java/ is useful
and this paid course from Eric is probably also very good (but I haven't seen it) https://purelyfunctional.tv/courses/jvm-clojure/
Ah nice, I’ll check these out!
(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)
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.