God morgen! Since the defn-podcast people canโt get their act together and make podcasts at the rate which I consume them, Iโve been forced to search around for those ones. I found a couple of episodes with Michael Nugaard on The Idealcast that I really enjoyed. Also, most episodes of Corecursive are great too. But nothing beats defn.
Morning
good morning
Morning
Morning
Good morning!
Buenos Dias!
I still don't feel that we've found a good way to tweak the last element of a vector https://clojurians.slack.com/archives/CBJ5CGE0G/p1600273110363900
tho peek/pop/conj might work too. And I think they are all O(1) on a vector
I wonder if I should do that rather than a (count my-vec) and an (update...)
and going back to other classics. Did we ever come to a conclusion wrt:
(filter (seq seqy-thing))
vs
(remove (empty? seqy-thing))
I like the latter.
(defn update-last [v f & args]
(conj (vec (butlast v))
(apply f (last v) args)))
(def my-vec [1 2 2])
(update-last my-vec + 2)
;; => [1 2 4]
last
is O(n)
not saying it's performant code
butlast
is probably also O(n)
replacing butlast
with subvec
and last
with get
is left as an exercise to the reader
(defn update-last [v f & args]
(let [cnt (dec (count v))]
(conj (subvec v 0 cnt)
(apply f (get v cnt) args))))
peek
is indeed O(1) on a vector (https://clojurians.slack.com/archives/CBJ5CGE0G/p1600420983007100)
peek it is!
(defn update-last [v f & args]
(let [cnt (dec (count v))]
(conj (subvec v 0 cnt)
(apply f (peek v) args))))
subvec should make a big difference here as it is really just a window onto the existing vector, but it will also prevent the original vector (and thus the previous version of that last element) to be garbage collected, so that could become a memory leak
ooh, I hand't thought of that
@plexus I think I might go w/this
(defn update-last [v f & args]
(conj (pop v)
(apply f (peek v) args)))
I think the only risk here is that you can't pop an empty vector
a true koan, what is a empty vector with its last element updated
conj/peek/pop all work on the cheap end of the data structure, which is what I want really
seems pop creates a SubVector too
public IPersistentStack pop(){
if(end - 1 == start)
{
return PersistentVector.EMPTY;
}
return new SubVector(_meta, v, start, end - 1);
}
so the result of those last two versions will be the same
but the pop version should be a tiny bit faster I presume
skips a count, I suppose
it does
this is what I fumbled my way to previously: https://github.com/MastodonC/witan.cic.driver/blob/b8f5a6d4474b2d0bea23617b6cd9301e1e0fced0/src/witan/cic/episodes.clj#L322-L330
(real live honest to goodness working code rather than a minimal example)
I wish I could learn how to spell superseded
basically I have a yearly report, where the latest year might alter records in previous years
when I'm done, I should have a vector of records with no overlapping intervals (tho they don't have to meet each other)
This will probably break evertything https://github.com/pjstadig/deque-clojure
which end do I pop/peek/conj?!?!?! I'm so confused
I guess a coffee / tea break would be nice. Who's with me? ๐ต
(let [v []
new-item 1]
(conj (or (and (seq v) (pop v))
[])
new-item))
=> [1]
(let [v [0 0 0 2]
new-item 1]
(conj (or (and (seq v) (pop v))
[])
new-item))
=> [0 0 0 1]
@raymcdermott ooh, I like (and (seq v) (pop v))
and I've been a fan of that or style since I started configuring emacs ๐
as an update-last tho:
(defn update-last [v f & args]
(if (seq v)
(conj
(pop v)
(apply f (peek v) args))
v))
so to answer @plexus's koan, updating the last element of an empty vector returns the empty vector?
is that the least surprising thing?
@raymcdermott I couldn't figure out how to do the or
pun
I like that you say: the empty vector. It seems there is indeed only one.
user=> (identical? [] (subvec [1 2 3] 0 0))
true
Itโs looking good @otfrom
I can't believe we've spent so much time on this. Surely this should be in core somewhere
there is an update-in
this sort of thing is sometimes a smell that you should be using a map rather than a vector
yeah, but a map doesn't tell you what went in last
I'm using update in atm along these lines:
(update v (dec (count v)) f foo bar)
ah, I must have missed the starting point
@ben.hammond up here: https://clojurians.slack.com/archives/CBJ5CGE0G/p1600273110363900
like I said. I'm a bit stunned we've been talking about it so much. I was presuming that I was being a dunderhead (I usually am)
Would transients help?
I've not used them much. In what way? Just speed?
or avoiding memory leaks?
both.
Not sure if tansients and subvec would work together nicely.
but maybe (let [t (transient v)] (update t (dec (count v)) inc) (persistent! t))
would be faster?!
Ok itโs actually (let [t (transient v) i (dec (count v))] (assoc! t i (inc (get v i))) (persistent! t))
nice
no, not nice
impressive, sure
That transient version isn't too different from what I have now