Hash maps are great for carrying around named information, so that seems reasonable to me.
I'm playing around with the "orc names" code from the Brave & True book: https://www.braveclojure.com/zombie-metaphysics/ but instead of 3000-length names, let's have 10-letter names and instead of a few thousand names, I'd have billions. Can I do that with a lazy sequence?
(defn random-string
"Returns a random string of specified length"
[length]
(apply str (take length (repeatedly #(rand-nth letters)))))
(defn random-string-list
[list-length string-length]
(doall (take list-length (repeatedly (partial random-string string-length)))))
(def orc-names (lazy-seq (random-string-list 10 60000000000)))
It was my understanding that the whole idea of a lazy-seq was it only processed what I need. So, (in my mind) I should be able to get the (first orc-names)
without computing the whole sequence, right? But when I do that, I'm getting a java.lang.OutOfMemoryError (Java heap space).
Am I missing something about the nature of a lazy-seq?just a small thing - take
is redundant on repeatedly
- you can replace (take n (repeatedly f))
with (repeatedly n f)
with those changes:
(defn random-string-list
[list-length string-length]
(repeatedly list-length
(fn []
(apply str (repeatedly string-length
#(rand-nth letters))))))
You have a doall, which realizes the whole list
Also, I think the arguments are in the wrong order (list len & string len)
ahh, yes. Thanks.
@yekrats take
in random-string-list already returns lazy-seq, second call in def orc-names
is redundant
Hello, I was wondering if there was any way of differentiating these two expressions ? (= (first [nil]) (second [1]))
(nth [nil] 1 ::not-found)
. will return your value for value not present versus the value there
@dpsutton aren't you off by one in nth?
The question was how to distinguish nil from a collection that didn’t have an element there versus one that had an element there but the value was nil
So I combined both into that. Changing to 0 will return the nil in the collection. Asking for the next element will return the sentinel value
ty
is it preferred to use {:foo/bar some-val :foo/baz some-other-val}
or #:foo{:bar some-val :baz some-other-val}
- putting namespace in front of each keyword of a map or putting namespace in front of map when all keywords of a map use same namespace? which is more readable/understandable?
totally personal opinion. do what looks nicer to you or what your team has settled on
I think I'll put the namespace in front of each keyword, since it's more explicit and I can't confuse myself when destructuring or using get/assoc/etc...
you can read (doc *print-namespace-maps*)
and (set! *print-namespace-maps* true|false)
to adjust how the repl's printer prints maps as well
thanks! it even adjusts the output of pr-str 🙂
I am confused as to what the idiomatic way of working with date and times is. I have a long
representing milliseconds as a Unix timestamp and I want to get a nicely formatted date.
Use interop with Java time
would that be java.time
or java.util.Date
?
Java time
<https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html>
Definitely worth the time to read these javadocs for 15 minutes. Stay with interop only (no wrapper libs) while you learn the basic types and ways to manipulate them. Once comfortable, feel free to use a wrapper if you like but understanding the core concepts of the package will benefit you immensely
thank you for the advice
hi, I'm a newbie and trying to use ring coercion to transform the type of a path parameter to int. I've written this code https://pastebin.com/J7LGiqgs following an example from https://cljdoc.org/d/metosin/reitit-ring/0.2.13/doc/ring/pluggable-coercion#full-example but I still can't see the value as int.
I think you got the handler function wrong. Following the docs, it should look like this:
:handler (fn [{:keys [parameters]}]
(let [id (-> parameters :path :id)]
{:status 200 ... etc ...
btw, your link is for the docs of a relatively old version
Hello, why do some operations that are mostly meant to be applied on lists take the list as the last argument (e.g. cons, take, drop..) while most other operations take a collection as the first argument (e.g. conj, nthnext, select-keys, subvec..)?
Thanks Sean and Rakyi, I read Rich’s explanation and couldn’t quite follow the train of thought. How does “sequences being read from left and being fed from right” along with the "sequence functions like map, filter and having variadic args" influence the choice of having the sequence as the last arg?
Particularly why does “sequences being read from left and being fed from right” influence (map f sequence)
, (filter pred sequence)
not being (map sequence f)
, (filter sequence pred)
. We could still chain them the same way we do it for other collections (-> sequence (map f) (filter f))
.
Oh okay maybe it is this bit "partial allows for direct parameterization as above" that majorly affected this decision. But I rarely do something like this ((partial map inc) '(1 2))
. Can't think of many sequence functions that have more than one arg before the source.
@kslvsunil A lot of those sequence functions have transducer-producing arities: (map f)
, (filter pred)
etc.
As you get more familiar with Clojure, this argument ordering will start to make more sense and you’ll come to understand what Rich means.
Okay Sean. But transducers were introduced much later. Will probably have to reread the motive a few times.
Those transducer arities were only possible because of the argument ordering conventions.
Yeah, very interesting. Can’t imagine transducers composing easily without this arg ordering of sequence functions. Not sure if it was extreme foresight or if we just got lucky. :)
Or more like a good design decision allowing the easy evolution and birth of transducers
my hunch (or vague recollection of the actual explanation) is that things that act like entities coming as first arg works with message passing / OO conventions from smalltalk (as later adapted by java, c++ and friends) (message thing arg)
and things that act like collections coming last (action parameter things)
works with data processing idioms coming from lisp (map, filter, etc. etc.) - for me personally the flip in order helps me categorize them as they are different idioms of programming
as the RH quote above describes, both idioms existed in common lisp with the introduction of CLOS (the OO system for common lisp), and clojure just follows along
fun trivia, many don't realize that common lisp was one of the first few languages with a full featured object system
Is it some kind of idiom that for functions that return lazy seqs, the coll be the last arg?
Good question. I think your intuition is good, likely lazyness.
@julian608 thanks !
Hey, is it possible to bind a value in an or
clause with core.match?
e.g. something like this
(let [x 1 y 2]
(match [x y]
[1 (:or 1 2 :bind-as b)] b
:else nil))
you could use something like this:
(let [x 1 y 2]
(match [x y]
[1 (b :guard #{1 2})] b
:else nil))