Fork me on GitHub
#clojure-europe
<
2020-09-18
>
slipset05:09:36

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.

😂 3
synthomat06:09:52

good morning

plexus07:09:54

Good morning!

jmayaalv09:09:48

Buenos Dias!

otfrom09:09:03

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

otfrom09:09:37

tho peek/pop/conj might work too. And I think they are all O(1) on a vector

otfrom09:09:18

I wonder if I should do that rather than a (count my-vec) and an (update...)

otfrom09:09:17

and going back to other classics. Did we ever come to a conclusion wrt:

(filter (seq seqy-thing))

vs

(remove (empty? seqy-thing))

ordnungswidrig09:09:12

I like the latter.

plexus10:09:24

@otfrom

(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]

borkdude10:09:13

last is O(n)

plexus10:09:31

not saying it's performant code

plexus10:09:03

butlast is probably also O(n)

plexus10:09:47

replacing butlast with subvec and last with get is left as an exercise to the reader

plexus10:09:55

(defn update-last [v f & args]
  (let [cnt (dec (count v))]
    (conj (subvec v 0 cnt)
          (apply f (get v cnt) args))))

plexus10:09:32

peek it is!

(defn update-last [v f & args]
  (let [cnt (dec (count v))]
    (conj (subvec v 0 cnt)
          (apply f (peek v) args))))

plexus10:09:36

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

otfrom10:09:44

ooh, I hand't thought of that

otfrom10:09:56

@plexus I think I might go w/this

(defn update-last [v f & args]
    (conj (pop v)
          (apply f (peek v) args)))

otfrom10:09:04

I think the only risk here is that you can't pop an empty vector

plexus10:09:20

a true koan, what is a empty vector with its last element updated

🤯 6
otfrom10:09:36

conj/peek/pop all work on the cheap end of the data structure, which is what I want really

plexus10:09:54

seems pop creates a SubVector too

plexus10:09:14

public IPersistentStack pop(){
		if(end - 1 == start)
			{
			return PersistentVector.EMPTY;
			}
		return new SubVector(_meta, v, start, end - 1);
	}

plexus10:09:32

so the result of those last two versions will be the same

plexus10:09:47

but the pop version should be a tiny bit faster I presume

otfrom10:09:26

skips a count, I suppose

otfrom10:09:23

(real live honest to goodness working code rather than a minimal example)

otfrom10:09:37

I wish I could learn how to spell superseded

otfrom10:09:25

basically I have a yearly report, where the latest year might alter records in previous years

otfrom10:09:03

when I'm done, I should have a vector of records with no overlapping intervals (tho they don't have to meet each other)

otfrom12:09:09

which end do I pop/peek/conj?!?!?! I'm so confused

borkdude13:09:56

I guess a coffee / tea break would be nice. Who's with me? 🍵

👍 3
genRaiy13:09:35

(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]

otfrom14:09:04

@raymcdermott ooh, I like (and (seq v) (pop v))

otfrom14:09:32

and I've been a fan of that or style since I started configuring emacs 😄

😂 3
otfrom15:09:07

as an update-last tho:

(defn update-last [v f & args]
    (if (seq v)
      (conj
       (pop v)
       (apply f (peek v) args))
      v))

otfrom15:09:56

so to answer @plexus's koan, updating the last element of an empty vector returns the empty vector?

otfrom15:09:02

is that the least surprising thing?

otfrom15:09:02

@raymcdermott I couldn't figure out how to do the or pun

borkdude15:09:53

I like that you say: the empty vector. It seems there is indeed only one.

user=> (identical? [] (subvec [1 2 3] 0 0))
true

genRaiy15:09:09

It’s looking good @otfrom

otfrom15:09:00

I can't believe we've spent so much time on this. Surely this should be in core somewhere

Ben Hammond15:09:35

there is an update-in

Ben Hammond15:09:09

this sort of thing is sometimes a smell that you should be using a map rather than a vector

otfrom15:09:33

yeah, but a map doesn't tell you what went in last

otfrom15:09:35

I'm using update in atm along these lines:

(update v (dec (count v)) f foo bar)

Ben Hammond15:09:02

ah, I must have missed the starting point

otfrom15:09:11

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)

ordnungswidrig16:09:12

Would transients help?

otfrom16:09:59

I've not used them much. In what way? Just speed?

otfrom16:09:42

or avoiding memory leaks?

ordnungswidrig16:09:01

Not sure if tansients and subvec would work together nicely.

ordnungswidrig16:09:50

but maybe (let [t (transient v)] (update t (dec (count v)) inc) (persistent! t)) would be faster?!

ordnungswidrig16:09:44

Ok it’s actually (let [t (transient v) i (dec (count v))] (assoc! t i (inc (get v i))) (persistent! t))

🥨 3
mpenet00:09:32

persistent! should be called on the return value of assoc! not on t.

genRaiy20:09:32

no, not nice

genRaiy20:09:50

impressive, sure

otfrom22:09:42

That transient version isn't too different from what I have now