This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-01
Channels
- # adventofcode (2)
- # announcements (3)
- # babashka-sci-dev (79)
- # beginners (76)
- # biff (2)
- # calva (32)
- # cider (2)
- # clj-kondo (42)
- # clj-on-windows (17)
- # clojure (28)
- # clojure-belgium (1)
- # clojure-berlin (1)
- # clojure-europe (95)
- # clojure-nl (4)
- # clojure-norway (4)
- # clojure-uk (5)
- # clojurescript (27)
- # conjure (5)
- # cursive (3)
- # data-science (16)
- # datomic (67)
- # graalvm (12)
- # hyperfiddle (36)
- # jobs (3)
- # jobs-discuss (1)
- # kaocha (2)
- # klipse (1)
- # leiningen (28)
- # lsp (16)
- # luminus (3)
- # malli (10)
- # nrepl (3)
- # off-topic (57)
- # other-languages (18)
- # re-frame (4)
- # reitit (8)
- # releases (1)
- # remote-jobs (1)
- # scittle (4)
- # shadow-cljs (7)
- # test-check (1)
- # tools-deps (4)
- # vim (11)
- # xtdb (25)
Is there a nice way to map collections that will return a flattened one? So (map vector [1 2 3] [4 5 6]) → [1 4 2 5 3 6]
That's better. Thanks! 🙂
but a more general note, you almost never need flatten
. I still haven't found one case where it's the appropriate solution, so if you happen to reach for it or something similar, it's almost a hint there's a better more specific solution
Good point, thanks!
hi guys, is there maybe a function that trims character from string but not blank space
if someone worked in php, there is such function which by default trims blank space, but you pass arbitrary characters as well
Dependency:
[org.apache.commons/commons-lang3 "3.12.0"]
(StringUtils/strip "a foo a" "a")
=> " foo "
You could just use clojure.string/replace
with a regular expression:
(str/replace "a foo a" #"^[a]|[a]$" "")
You can make your own, using @U922FGW59's suggestion.
(defn trim
([string] (trim "\\s" string))
([char string]
(str/replace string
(re-pattern (str "^[" char "]*|[" char "]*$"))
"")))
(trim (trim "a" "aaa foo a")) ;; => "foo"
Is there any json library that keeps ordering ? i.e. enforces array-map?
I do not know, but a nitpick: if it did use array-map to preserve ordering of the input key/value pairs, then if in memory you did an assoc
on one of those array-map
instances, and it had over 8 keys in it, it is nearly certain that it will return a hash-map, with the key/value ordering lost.
If you want something that reads json, and then lets you change the data, and spit out json at the end, I would think you would want something that used a data type other than Clojure's built-in array-map. Either that, or you would need to be very strict in how you updated such array-map's if you wanted order to be preserved, e.g. create brand new array-maps from the existing ones, with different key/value pairs.
If there were a json library that used this ordered-map data structure in this library, that would make it easier to update ordered-maps without losing the input order: https://github.com/clj-commons/ordered. I do not know if such a json library exists.
There are places in Clojure's implementation (a very very few) where the fact that array-map preserves order is used explicitly.
@US3NQ875H what sort of situation are you in where you need map ordering?
this is a bit common on the frontend, libs are written that consume maps where the order of the keys is important
i think in cheshire you can have an encoder for a type you make that in clojure looks like a list of mapentries, and cheshire would render that as a json map, preserving your order
Some non-clojure language generates a query result returned in a certain order, making it non trivial to figure out the expect order. Passing through the clojure backend it looks like we’re shuffling results once they contain more than 8 columns 😂
clojure does array->hash-map promotion after your persistent map gets to be ~8-10 items big. if you are consuming a json map you could write a decoder that returns vectors of mapEntries, thus preserving order and you can write protocol functions to make it a proper type that acts exactly like a persistent map. or tell the producer to stop screwing around and give portable data representations
How can I add 2 numbers from my Atom and pass it to the Sum ?? (defonce app-state (atom {:first-number 0 :second-number 0 :sum 0})) (defn sumNumbers [] #(swap! app-state assoc :sum (+ :first-number :second-number)) ) Or can anyone sent me a link where is article about it. Thank You!!
i wouldn't personally store the derived state in my atom. It makes it possible to get out of sync which can be a pain. but you could sum them by doing the following.
(defn sumNumbers []
(swap! app-state update :sum #(+ (:first-number %) (:second-number %)))
editted to remove nested hash functionresponsible for numbers have inputs: [:input { :type "number" :class "number-Input" :value (:first-number @app-state) :on-change #(swap! app-state assoc :first-number (-> % .-target .-value)) }] 🙂
And I want to make button to sum it and to show it 🙂
if you use 3 backticks (grave accent) before you paste code it comes across a bit nicer to read
ok I will remember 🙂
NICE 😄
[:input
{
:type "number"
:class "number-Input"
:value (:first-number @app-state)
:on-change #(swap! app-state assoc :first-number (-> % .-target .-value))
}]
(defn sumNumbers []
#(swap! app-state assoc :sum (+ :first-number :second-number)) )
What's wrong with that? Isn't that exactly what you want?nope. you need access to the value of :first-number
so you need to use update instead of assoc
I will learn 10000x more from You guys then from internet 🙂
Ah, now I understand what you mean
Well @U040ULRJL3B we are guys and girls from the internet
@U922FGW59 You are guys and Girls from Slack 🙂
@U02SD8PATK2 your code
(defn sumNumbers []
#(swap! app-state update :sum #(+ (:first-number %) (:second-number %)))
throws syntax error, it has nested #()s.@U040ULRJL3B I would consider just derefing the numbers rather than the sum of the numbers that you synchronize.
instead of
(let [sum (:sum @app-state)])
do
(let [sum (apply + ((juxt :first-number :second-number) @app-state))]
or something similar
might have to be an explicit fn
though
(defn sumNumbers []
#(swap! app-state update :sum (fn [x] (+ (:first-number %) (:second-number %)))
Tip: Embrace pure functions, and write this one first. And make sure it works:
(update-first-number current-state new-first-number)
Then you can use that in your event handler: #(swap! app-state update-first-number (.. % -target -value))
Ok I see now I dont get it at all and I try to master making functions tomorrow 🙂 Thank You for Your time!! Have a good night
another option is to add a helper for getting target and just comping it and utilizing the update :first-number
(def evt->val #(-> % .-target .-val)
(partial swap! app-state update :first-number (comp + js/Number evt->val))
I made it!!
(defn sum-numbers []
(swap! app-state assoc :sum(-> ( + (edn/read-string(:first-number @app-state )) (edn/read-string(:second-number @app-state ))))))
And quick question is there any good tutorial on the net with ClojureScript? I would like to make some hard stuffs 😛
Is there any reason why you save your numbers as strings? You have to parse them with each call of sum-numbers
. I suggest you to use helper by @U02SD8PATK2 and then just this function:
(defn sum-numbers []
(swap! app-state assoc :sum (+ (:first-number @app-state)
(:second-number @app-state))))
this inputs saves numbers as a string [:input { :type "number" :class "number-Input" :value (:first-number @app-state) :on-change #(swap! app-state assoc :first-number (-> % .-target .-value)) }] I dont know yet why, but they do it. this is my atom: (defonce app-state (atom {:first-number 0 :second-number 0 :sum 0}))
HTML inputs (text fields) only deal with strings, yes. However, if you want to deal with numbers, it makes sense to convert the text input to a number in the on-change
event. This gets more complicated quickly, as you need to validate that the text actually is a number, and decide what to do if not. Typical UI stuff.
A good idea might be:
• Keep the input text as string
• Whenever it changes, try to parse it into a number (integer)
• When parsing works: Store the parsed number in the state and do whatever you need to do (sum...)
• Otherwise, you can give your user feedback that they need to change their input
Again, I recommend to break this down into smaller chunks, use pure functions to implement those, test these functions, then put them together.
Instead of trying to do everything in one #(swap! ... assoc ...)
, make your event handler smaller by just calling swap!
with a pure function and the current text input:
(defn update-text-input [state text-input]
;; This is a _pure_ function. Here you can:
;; - Save the text
;; - Convert to a number
;; - Compute sums
;; - ...
;; And return the updated state.
,,,)
#(swap! app-state update-text-input (.. % -target -value))
@U922FGW59 i found solution:
(defn numberInput [changeValue]
[:input {:type "number" :value (changeValue @app-state)
:on-change (fn [e]
(let [new-value (js/parseInt (-> e .-target .-value))]
(swap! app-state
(fn [data]
(-> data
(assoc changeValue new-value)
))
)
)
)
}
]
)
is there any prettier for clojure in vsc??
Are you using Calva?
when i have at last line something like this: )))))}] it's looking bad for me, but if it have to be like this I won't complain and just train coding more 🙂
@U040ULRJL3B i highly recommend getting used to the stacked parens and ending syntax. The style you posted above is c style code and you will not miss it when you get used to the stacked parens. I spent most of my 15 years of coding in c style languages and i know it is a bit hard to give up but I think you’ll be glad if you do.
To me it is often also a sign of too complex code if you end up with a bunch of closing brackets
For instance,
(swap! app-state
(fn [data]
(-> data
(assoc changeValue new-value)
))
)
Could be written as: (swap! app-state assoc changeValue new-value)
Nesting level 1 instead of 4 🙂Nice 😄, I took it from tutorial and didn't think it have to be refactored
What usually happens to namespaced keywords outside of a context that supports them?
Remove the namespace? {:foo/a 1 :bar/b 2} -> {"a": 1, "b": 2}
Keep the namespace as part of the key string? {:foo/a 1 :bar/b 2} -> {"foo/a": 1, "bar/b": 2}
Nested context? {:foo/a 1 :bar/b 2} -> {"foo": {"a": 1}, "bar": {"b": 2}}
Something else? I don't really know.
It depends on what the consumer needs.
If you're producing JSON from Clojure hash maps, most of the JSON libraries have settings to control this. We use org.clojure/data.json
at work (pure Clojure, zero dependencies, fast enough for most use cases).
By default data.json
drops the ns:
seanc@Sean-win-11-laptop:~/clojure$ clj -Sdeps '{:deps {org.clojure/data.json {:mvn/version "RELEASE"}}}'
Downloading: org/clojure/data.json/maven-metadata.xml from central
Downloading: org/clojure/data.json/maven-metadata.xml from sonatype
Clojure 1.11.1
user=> (require '[clojure.data.json :as json])
nil
user=> (json/write-str {:foo/bar 1 :foo/quux 2})
"{\"bar\":1,\"quux\":2}"
user=>
Is it better to work with strings of the whole namespace qualified keyword in case you've got a map like {:foo/a 1 :bar/a 2}
?
Work with whatever is best for the consumer of the data - which use generally keywords within Clojure code.
yep. so for example, if you have necessary context in your namespace such that your data needs it to make sense then you can just convert it to a string in json which is valid.
{
"filter/name": "some-name",
"user/name": "some-user",
}
if you had some shape like this it wouldn't work to drop the ns.