This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-12
Channels
- # beginners (102)
- # boot (5)
- # cider (1)
- # cljs-dev (15)
- # cljsjs (1)
- # cljsrn (20)
- # clojure (104)
- # clojure-austin (1)
- # clojure-europe (8)
- # clojure-italy (39)
- # clojure-nl (17)
- # clojure-spec (38)
- # clojure-uk (23)
- # clojurescript (34)
- # cursive (31)
- # data-science (5)
- # datomic (3)
- # emacs (28)
- # joker (1)
- # kaocha (5)
- # klipse (1)
- # leiningen (1)
- # off-topic (66)
- # quil (4)
- # reagent (35)
- # ring-swagger (1)
- # rum (1)
- # shadow-cljs (121)
- # test-check (1)
- # tools-deps (33)
- # uncomplicate (2)
- # vim (15)
- # yada (1)
(def client {:namae "Super Co."
:location "Philadelphia"
:description "The worldwide leader in plastic tableware."})
@ULUNR1TKQ you cannot "change" the value, you can only override it by binding it to something else. Let bindings are effectively constants
(let [{:keys [name ,,,]} my-data
name (str name " - edited")]
,,, )
You can also have defaults when destructuring associatively.
(let [{:keys [a b] :or {b 42}} {:a 1}] [a b])
; => [1 42]
also remember you can destructure without :keys
user> (let [{name :namae :keys [location description] :as hello} client]
[name location description])
["Super Co."
"Philadelphia"
"The worldwide leader in plastic tableware."]
(let [{:keys [namae location description] :as hello} client
namae "hello"]
(println namae location "-" description))
@ULUNR1TKQ it works for me:
(let [{:keys [namae location description] :as hello} {:namae "Juraj" :location "EU" :description "<empty>"}
namae "hello"]
(println namae location "-" description))
;; =>
hello EU - <empty>
nil
Anybody have tips and tricks on how to deal with nested spec that has same key but different spec predicate?
I guess you're talking about unqualified keys and the same key appearing at different "levels" of a map? In that case you could just use different namespaces for the key specs:
(s/def :a/my-key int?)
(s/def :b/my-key boolean?)
(s/def ::b (s/keys :req-un [:b/my-key]))
(s/def ::nested (s/keys :req-un [:a/my-key ::b]))
(s/valid? ::nested {:my-key 10 :b {:my-key true}})
;; => true
(s/valid? ::nested {:my-key false :b {:my-key true}})
;; => false
sorry to bother, if I have a vector [100 200 300]
and I need to minus 400 from it so that to return [0 0 200]
or minus 200 to return [0 100 300]
, how can I do so ?
@godwin.ko (defn subtract-every [n x] (map #(- % n) x)))
@godwin.ko it's hard to read it right but you mean to subtract x from every element y where x <= y and the total sum of all decrements from all the elements is the number you get as an input?
Did you mean that if you give it [100 200 300]
and you minus 400 you should return [0 0 200]
? That is subtract 100 from first number, since 400 is bigger than 100, then subtract 200 from next number because you still want to subtract a total of 400 but have only subtracted 100 so far, etc.?
@andy.fingerhut ops, you’re right, my bad, typo
Do you always want a vector to be returned, or would a lazy sequence be better in any use case you have in mind, because the 'consumer' of the return value might in some case only need the first few elements?
Perhaps use reduce
? - this is the best I could quickly come up with?
(first (reduce (fn sub [[acc x] y]
(let [decrement (min x y)
new-y (- y decrement)]
[(conj acc new-y)
(- x decrement)]))
[[] 200]
[100 200 300]))
;;=> [0 100 300]
(defn cascading-subtract [x [y & ys]]
(let [z (- y x)]
(if (neg? z)
(cons 0 (lazy-seq (cascading-subtract (- z) ys)))
(cons z ys))))
it might be fun to practice a few clojure fns while shell-scripting: https://github.com/borkdude/babashka
an exercise I just did had me create my own filter function and I came up with:
(defn my-filter
[pred coll]
(loop [pred pred
coll coll
new-coll []]
(if (empty? coll)
(seq new-coll)
(if (pred (first coll))
(recur pred (rest coll) (conj new-coll (first coll)))
(recur pred (rest coll) new-coll)))))
Is it bad form to have an if
statement nested as the else
branch of another if
statement? I'm wondering how else I could have terminated this because without that empty?
check I was getting some errors when executing. I feel like I should be using reduce
somehow to do all this but haven't figured it out yet.You could use cond
in place of the nested if
(cond
(empty? coll) (seq new-coll)
(pred (first coll)) (recur pred (rest coll) (conj new-coll (first coll)))
:else (recur pred (rest coll) new-coll))
But when I think about it for me reduce
means I'm taking a collection and taking it down to one value so maybe it's not appropriate since here I'm forming a whole new collection. Would you agree or am I thinking about that wrong?
If you think of the 'one value' as another collection then it works just fine.
So you could reduce one vector into another vector with fewer entries
that's what I was just concluding too. I just haven't trained my brain to see that pattern and approach yet with reduce. I'll need to track down more examples of that in usage.
having the (fn..)
's within another function starts being a little difficult for me to keep track in my head still
Actually most collection functions can be implemented using a reduce, since it gives you complete flexibility of the 'shape' of the thing you end up with after the iteration.
A reduce could yield a larger collection even
I would love to see a good example of this being the right approach if you can think of something.
(defn my-filter [pred coll]
(reduce
(fn [acc item]
(if (pred item)
(conj acc item)
acc))
(empty coll)
coll))
In this case (empty coll)
gives you an empty instance of whatever collection coll
is
The function to reduce takes an accumulator and each item
And if the item should be removed, just returns the current acc
Otherwise adds the item to acc
I think what tripped me up is that I could keep using pred
in that inner function without explicitly saying it's an argument to the inner function if that makes sense. that was tripping me up when I was trying to do this.
so the inner functions have access to all the parameters passed in to the original function
Yeah, you can rely on the lexical scope of the outer function so that you effectively 'close over' it's arguments and they remain accessible
This is a 'closure'
(Hence Clojure :))
haha, good stuff. and I'm definitely drinking the kool-aid because I was like hmmm, Hence
isn't a function
You can implement reduce
using loop/recur
- the reason the reduce
version is more succinct is because it's a higher level of abstraction than loop/recur
and so requires less work.
and with your reduce
version you don't have to explicitly check for an empty list right because reduce
knows to end at that point but in mine I have to explicitly check or it doesn't terminate? how would you put that in a clearer explanation?
Yes, you're right. reduce
already does the work of checking if coll
is empty and just returns it in that case.
Actually, it returns the initial value passed to reduce
but that's equivalent in this case.
So (reduce (fn [acc item] ...) "Wat!" []) => "Wat!"
No problem 🙂
so say you have an initial hunch to use loop/recur
like I often do in these situations. Is there some kind of rule of thumb where you are like "hmm, no this is a better use of reduce
"?
or do you always just default to reduce
and then think maybe it's a loop/recur
thing. yeah, I haven't thought this question through yet
and you don't have to even use first
and rest
and stuff because it's kind of built in to what reduce
is doing working through the collection. You just have (pred item)
(conj acc item)
. It's so damned elegant. I love it!
I think, after a certain amount of just using Clojure for stuff, you just start to reach for reduce
first and don't think of loop
/`recur`...
Well as I said, most of the other collection manipulation functions are built on top of something like reduce
but provide an even higher level of abstraction. So I personally don't use reduce
directly as much, instead I try and find another function that achieves my goal first.
But as @U04V70XH6 says, it's rare to use loop
/`recur` for me these days unless implementing new recursive algorithms. The other day, I used it for a custom graph traversal in loom
(https://github.com/aysylu/loom)
It's like transducers. At work we're pretty leading edge in terms of Clojure uptake -- we take alpha releases to production all the time so we can start to leverage new features earlier. But we didn't really start using transducers "naturally" until fairly recently (like, the last year or two) even tho' they've been available since 2015.
If you can't find any appropriate collection manipulation functions you can always rely on reduce
so for me the hierarchy is: specific function > reduce
> loop
/`recur`.
this is great. I feel like getting an intuitive understanding of these things can really take me to the next level. I haven't wrapped my head around transducers yet.
@U9J50BY4C nor have I 😄
Tim Baldridge has put together some nice videos on them though, when you want to learn more: https://tbaldridge.pivotshare.com/categories/transducers/2426/media
I might have to resubscribe to those. I had stepped away from clojure for a bit (to my regret) but now I'm back with a vengeance.
when exploring the clojure cheatsheet for inspiration I often times see "if not provided with a collection, this returns a transducer" so I've been thinking of them as lazy transformation functions if that makes any sense. hahaha
Yeah, that's how I'm seeing them too - they are composable transformations
It may help to think of them as separating the "processing" from the source and sink, especially when looking at into
: (into sink process source)
-- process
is some data transformation that can be applied in other contexts such as on a channel -- it's not tied to collections.
(and if you find yourself using ->>
to create pipelines of transformation, maybe using transducers would be more efficient)
interesting because I absolutely love ->>
but I am definitely looking forward to taking my understanding into these higher abstractions.
i don't seem to develop using ->>
as much as I like to refactor into it after "solving" the problem first using normal structural editing/repl development. I find it easier to understand when reading other people's code (and my old code)
So, the code base I'm working in has a bunch of defmacros that seem to be used identically to functions, what's everyones rule of thumb for when to create a macro instead of a function?
I use them only if: 1) the correctness of code requires evaluation while compiling and not later or 2) the explicit goal of the macro is to provide a new syntax
(= java.lang.String java.lang.String)
(case "a"
"a" "fruit"
)
(case java.lang.String
java.lang.String "fruit"
)
1. Unhandled java.lang.IllegalArgumentException
No matching clause: class java.lang.String
I saw this a few days ago, this is helpful in understanding https://stackoverflow.com/questions/12028944/clojure-case-statement-with-classes
I opted for multimethods when checking class, you can also use :default to make what is essentially a case
I dont feel enlightened, but condp for the win
user> (condp = java.lang.String
java.lang.String "fruit"
)
"fruit"
I'm getting a reflection warning about unresolved constructor from
(HashMap. {"foo" "bar"})
Adding a hint like (HashMap. ^Map {"foo" "bar"})
doesn't seem to address it. Is there anything instead that I should do?although, actually, even without the hint in that case you shouldn't get a reflection warning
I can't repro the reflection warning on that either. Maybe the real code has the map in a var @csd?
here's the actual snippet
(defn put-scalar-into-map [value]
(if (instance? Map value)
value
(HashMap. {"value" value})))
(defn put-scalar-into-map [value]
(if (instance? Map value)
value
(HashMap. ^Map (hash-map "value" value))))
I think @hiredman might be right about the type hint getting swallowed on the literal.Are there any place where we can practice the use of core.async? Some repository with exercises? I more or less understand the concept, but the library has a lot of functionality beyond the basics and it would be great if there was a place where to learn them.
@neo2551 this is a pretty helpful exercise to follow https://www.braveclojure.com/core-async/
@christian.gonzalez thanks a lot for the website I love it :). My issue is it does not go into all the pipelines of core.async
Yeah this is pretty introductory, I’m sure there are other resources out there depending on what you’re trying to achieve