This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-05
Channels
- # aleph (6)
- # announcements (2)
- # babashka (8)
- # beginners (121)
- # calva (7)
- # cider (7)
- # clj-kondo (25)
- # clojure (167)
- # clojure-android (1)
- # clojure-italy (1)
- # clojure-sweden (1)
- # clojuredesign-podcast (2)
- # clojurescript (11)
- # community-development (33)
- # cursive (23)
- # data-science (1)
- # datascript (11)
- # datomic (7)
- # emacs (12)
- # events (1)
- # fulcro (15)
- # graalvm (3)
- # hoplon (1)
- # instaparse (1)
- # malli (12)
- # off-topic (1)
- # planck (3)
- # re-frame (5)
- # shadow-cljs (61)
- # test-check (2)
How do you use recur with the second version of a function? Ignore the logic behind this and whether or not it works, as I'm fighting with it at the moment, but currently getting a syntax issue:
(defn determine-digits
([remaining-digits]
(if (= (quot remaining-digits 10) 0)
1
(recur (quot remaining-digits 10) 1)))
([remaining-digits digits-so-far]
(if (= (quot remaining-digits 10) 0)
digits-so-far
(recur (quot remaining-digits 10) (inc digits-so-far)))))
Syntax error (IllegalArgumentException) compiling recur at (form-init4233438687175101551.clj:5:6).
Mismatched argument count to recur, expected: 1 args, got: 2
I'm guessing because on line 5 recur somehow only recurs to that particular arity instance of the function? What's a better approach for what I'm trying to do syntactically, again, glossing over other logic issuesYou're trying to recur into another function, even though it looks like the same function, you're creating two functions that differ by arity
You need to merge both of them into the two arity one, and then make the one-arity a call to the two-arity
Ended up with
(defn digits
([remaining-digits]
(digits remaining-digits 1))
([remaining-digits digits-so-far]
(if (= (quot remaining-digits 10) 0)
digits-so-far
(recur (quot remaining-digits 10) (inc digits-so-far)))))
You can alternatively use the loop/recur syntax. Typically, calls to the two arity function will be internal so you can avoid exposing it.
If you don't particularly care about performance, you could just define it like this π:
(defn digit-count [n]
(count (str (Math/abs n))))
@U883WCP5Z That's how I did it initially. This is for exercism. My mentor said to do it arithmetically. I wonder, truly though, how much more/less performant each version is
Well, here they are:
user=> (defn digits2 [n]
#_=> (loop [num (long n)
#_=> d 1]
#_=> (let [q (quot num 10)]
#_=> (if (zero? q)
#_=> d
#_=> (recur q (inc d))))))
#'user/digits2
user=> (defn digits1 [n]
#_=> (count (str (Math/abs (long n)))))
#'user/digits1
user=> (crit/quick-bench (digits1 1234567890123456789))
Evaluation count : 7296390 in 6 samples of 1216065 calls.
nil
Execution time mean : 75.719094 ns
Execution time std-deviation : 2.568614 ns
Execution time lower quantile : 72.614107 ns ( 2.5%)
Execution time upper quantile : 78.657657 ns (97.5%)
Overhead used : 9.051454 ns
user=> (crit/quick-bench (digits2 1234567890123456789))
Evaluation count : 15884838 in 6 samples of 2647473 calls.
nil
Execution time mean : 28.911209 ns
Execution time std-deviation : 0.276928 ns
Execution time lower quantile : 28.680677 ns ( 2.5%)
Execution time upper quantile : 29.357405 ns (97.5%)
Overhead used : 9.051454 ns
Found 1 outliers in 6 samples (16.6667 %)
low-severe 1 (16.6667 %)
Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
The long
is to avoid reflective calls.Wow, thank you for that. Super interesting, ok so now we know it's definitely slower the way I was doing it
any problem by changing this recur on line 5 to a call with the name of the function?
Hmm I somehow thought you shouldn't do that for reasons that escape me, no TCO I think it was
(defn determine-digits
([remaining-digits]
(if (= (quot remaining-digits 10) 0)
1
(determine-digits (quot remaining-digits 10) 1)))
([remaining-digits digits-so-far]
(if (= (quot remaining-digits 10) 0)
digits-so-far
(recur (quot remaining-digits 10) (inc digits-so-far)))))
quick query through a code base that I am using and I hit an example
(defn now
([]
(now 0))
([delay]
(let [now (java.time.Instant/now)]
(java-time/plus now (java-time/days delay)))))
In my case though, I'm going to need the original call to look like (determine-digits 1123)
, so there is indeed a requirement for a single arity rather than a 0-arity
It's common to have several arities that all end up calling one specific arity with default values filled in for the other arguments.
@kamuela I think in your case you don't need to the if
in the 1-arity. Just call the function passing 1
as the second arg.
And just pass remaining-digits
, without calling quot
on it.
(defn determine-digits
([remaining-digits]
(determine-digits remaining-digits 1))
([remaining-digits digits-so-far]
(if ...)))
Well since we've dove straight to the logic, here's a brain-teaser: is 0 a single-digit number?
Thanks @iagwanderson you've solved the syntax issue with that pattern
as we like in clojure, the definition from Merriam-Webster says that 0 is a single-digit number.
single-digit adjective
Definition of single-digit
: having a number or percentage that is 9 or less
well are -9 .. -1
single digit or not?
Any real integer between -9 and 9 excluding 0 would be a precise definition, but I actually don't know what the real definition is
hehe, you are right, depends on your definition
Iβd say that counting the digits in 0
yields 1 digit, so should also be included
Is there something like Spring Data JPA for Clojure? There I can declare a repository (an interface) for a component (a POJO) and I get all the CRUD operations 'for free' (no code needed). It also makes it really easy to add custom queries.
maybe https://github.com/metabase/toucan is the closest thing to that.
I'm going through this tutorial btw: http://clojure-doc.org/articles/tutorials/basic_web_development.html
I am not from Java-land, but I did a small research on Data JPA and until now I haven't found a framework web that does that in clojure. In fact, I never used any clojure "framework" to build my web apps
I had asked why there were three ways to create a record. Clojure Applied starts off explaining it. Also I created a channel for #clojure-applied.
Renamed to #books-clojure-applied
Hey! I'm very new to Clojure, I'm attempting to read some data from an API, but it's being returned as a clojure.lang.PersistentVector
, is there some special way to access the values in that data type? I can't seem to figure it out?
A snapshot of the data looks like this when I print it out:
[{away_l 4, home_gp 13, stage_id 12051081, away_w 5, recent_form WWLWD, country England, season 2019/2020, away_ga 18, overall_l 9, home_ga 16, overall_d 6, away_gs 19, overall_w 11, overall_ga 34, points 39, team_id 9221, home_gs 21, position 9, comp_group nil, home_w 6, home_l 5, team_name Hull, status same, comp_id 1205, away_d 4, overall_gp 26, overall_gs 40, home_d 2, away_gp 13, round 26, gd +6, description }]
I'm attempting to access it like:
(defn fetch-teams [id]
(doseq [p (api->fetch-teams id)] (println (:team_name p))))
But :team_name
is nilOh my god, that was absolutely correct!
if you need to transform these keys into keywords
you can use the function clojure.walk/keywordize-keys
Thank you so much, it never occurred to me!
Ahaa that's really useful
Yes that's the one, I was using :as :json
for the others, but because this was returning an array, it didn't work the same, I had to do :as json-string
then had to use json/read-str
Thanks again!
Hi all π, I have a question I am struggling with let's say printing ranges, however including negative integers, where I know I could technically do (range 2 -3 -1)
but it seems clunky, I am looking for a function that would return numbers within a range [2 -5] including range boundries
Ok, so I have decided to reimplement range
(defn irange [start end]
(let [direction-positive (if (< start end) true false)
end-operator (if direction-positive > <)
jump-operator (if direction-positive inc dec)]
(loop [x start
l []]
(if (end-operator x end)
l
(recur (jump-operator x) (conj l x))))))
That is a reasonable-looking implementation. I only wanted to point out that if you call range
with the appropriate parameters inside of irange
you can take advantage of performance optimizations of range
, e.g. it is lazy, and I believe more efficient in its memory and CPU usage than your implementation above.
something like that maybe:
(defn irange-2 [start end]
(let [direction-positive? (< start end)]
(if direction-positive?
(range start (+ end 1))
(range start (- end 1) -1))))
Iβd also point out that you can call range
with 0-3 arguments, maybe you want to also implement the 3 argument version (`start` end
step
)
@UDF11HLKC I was just tailoring it for one of the advent of code excersises, so I consider this "one-off". Plus step seems unintuitive considering negative numbers. I would much rather change the implementation to accepting a partially applied function as step - seems more natural to me, but I am noob so :)
Right, if its a one off then sure ^^
I spent a couple months implementing the current version of range in core. I felt somewhat insane after a while just doing nothing but counting numbers more efficiently but there are a surprising number of weird edges and perf optimizations
now I am intrigued, the implementation is in the runtime?
Well thatβs all the most optimized one for all longs
You can use range with any kind of number - rationals, doubles, bigintegers, and even mix them
Consider long steps that are a high percentage of the long range etc - lots of overflow cases
The long range has to support 3 different iteration styles - self reduce (highly optimized), chunked seqs, and unchunked seqs
Balancing all that was a challenge
And we were really trying to improve the existing common case, and add the optimized reduce behavior, and not break anything that worked in the much simpler prior impl
what made you tackle performance of range? Youβd say that is not the most βhotβ code to be found
And it has to be thread safe (which I broke in one very subtle case and had to fix)
range is used in lots of places for very small ranges, and people use for a huge set of examples
But really it was part of a broader effort when we introduced transducers to make some of the key seq generator functions self reducible (range, iterate, cycle)
https://clojure.atlassian.net/browse/CLJ-1515 for the gory details
fascinating!
a class of problems I hope to be dealing with some day
I think it is more accurate to say "they preferred a different API that matched the way they wanted to pass parameters, versus what range provides"
as Andy said, (range 2 -3 -1) returns (2 1 0 -1 -2), so now i need to append one more value by extending the range, again I have to do yet another if for which parameter i have to dec/inc and so and so
Oh, okay, but still, why re-implement range and not just wrap it behind the interface you want say:
(defn rng
[s e]
(if (<= s e)
(range s (inc e))
(range s (dec e) -1)))
Which is one of my earlier suggestions in this thread
not the code, but the suggestion of calling range
I think the default bounds are designed for zero based index iteration over collections.
yes, i noticed range is mostly for iterating zero-index things, as for your solution it seems fine and better π #beginners but you have more conditions, you will be (dec end) or (inc end) based on wether its negative or positive, so it still different code I think.
Haha, ya sorry. I sounded a bit surprised, but it was mostly that I thought no one else had suggested to just leverage the existing range instead of re-implementing it, which I was wrong since others had I just overlooked it.
(rng 5 1)
;; => (5 4 3 2 1)
(rng 2 -3)
;; => (2 1 0 -1 -2 -3)
(rng 1 4)
;; => (1 2 3 4)
(rng 0 -3)
;; => (0 -1 -2 -3)
(rng 2 2);; => (2)
Looking for a Cron library. I found Quartzite, but doesn't seem to be maintained anymore. Anybody here use it?
There's also https://github.com/aphyr/tea-time
I used https://github.com/overtone/at-at at some point
is this idiomatic for java IO interop?
(let [raf (RandomAccessFile. "/tmp/longfile" "r")
_ (.seek raf (* 1000 1000 1000))
result (.readInt raf)]
(.close raf)
result)
I initially tried doto but that returns the final form - how do you return result
from the above code?
i think something like this
(with-open [raf (doto (RandomAccessFile. "/tmp/longfile" "r")
(.seek (* 1000 1000 1000)))]
(.readInt raf))
I remember a scheduling library that just took a sequence of times, but I can't find it anymore, anyone knows?
https://www.clojure-toolbox.com/ has a few options
Guys i'm studying with a excellent book called "clojure for the brave and true"

Not yet