clojure-europe

For people in Europe... or elsewhere... UGT https://indieweb.org/Universal_Greeting_Time
slipset 2020-09-18T05:33:36.005Z

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.

๐Ÿ˜‚ 1
2020-09-18T06:21:15.005300Z

Morning

synthomat 2020-09-18T06:37:52.005500Z

good morning

2020-09-18T07:07:03.005700Z

Morning

jasonbell 2020-09-18T07:21:16.005900Z

Morning

plexus 2020-09-18T07:24:54.006100Z

Good morning!

2020-09-18T09:10:48.006400Z

Buenos Dias!

2020-09-18T09:23:03.007100Z

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

2020-09-18T09:23:37.007700Z

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

2020-09-18T09:24:18.008200Z

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

2020-09-18T09:25:17.009400Z

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

(filter (seq seqy-thing))

vs

(remove (empty? seqy-thing))

ordnungswidrig 2020-09-18T09:40:12.009600Z

I like the latter.

plexus 2020-09-18T10:11:24.009900Z

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

borkdude 2020-09-18T10:12:13.010200Z

last is O(n)

plexus 2020-09-18T10:12:31.010500Z

not saying it's performant code

plexus 2020-09-18T10:13:03.010800Z

butlast is probably also O(n)

plexus 2020-09-18T10:13:47.011300Z

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

plexus 2020-09-18T10:15:55.011700Z

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

borkdude 2020-09-18T10:15:57.011900Z

peek is indeed O(1) on a vector (https://clojurians.slack.com/archives/CBJ5CGE0G/p1600420983007100)

plexus 2020-09-18T10:16:32.012400Z

peek it is!

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

plexus 2020-09-18T10:26:36.013500Z

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

2020-09-18T10:32:44.013700Z

ooh, I hand't thought of that

2020-09-18T10:33:56.014Z

@plexus I think I might go w/this

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

2020-09-18T10:35:04.014300Z

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

plexus 2020-09-18T10:37:20.015300Z

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

๐Ÿคฏ 2
2020-09-18T10:37:36.015700Z

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

plexus 2020-09-18T10:38:54.016300Z

seems pop creates a SubVector too

plexus 2020-09-18T10:39:14.016600Z

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

plexus 2020-09-18T10:39:32.017Z

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

plexus 2020-09-18T10:39:47.017400Z

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

2020-09-18T10:40:26.017600Z

skips a count, I suppose

plexus 2020-09-18T10:41:11.018200Z

it does

2020-09-18T10:43:23.019Z

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

2020-09-18T10:43:37.019300Z

I wish I could learn how to spell superseded

2020-09-18T10:44:25.019800Z

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

2020-09-18T10:45:03.020400Z

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

slipset 2020-09-18T10:50:08.020700Z

This will probably break evertything https://github.com/pjstadig/deque-clojure

2020-09-18T12:46:09.021300Z

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

borkdude 2020-09-18T13:20:56.022400Z

I guess a coffee / tea break would be nice. Who's with me? ๐Ÿต

๐Ÿ‘ 1
raymcdermott 2020-09-18T13:23:35.023100Z

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

2020-09-18T14:20:04.023600Z

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

2020-09-18T14:20:32.024200Z

and I've been a fan of that or style since I started configuring emacs ๐Ÿ˜„

๐Ÿ˜‚ 1
2020-09-18T15:06:07.024800Z

as an update-last tho:

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

2020-09-18T15:06:56.025500Z

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

2020-09-18T15:07:02.025700Z

is that the least surprising thing?

2020-09-18T15:09:02.026100Z

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

borkdude 2020-09-18T15:17:53.026600Z

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

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

raymcdermott 2020-09-18T15:29:09.027200Z

Itโ€™s looking good @otfrom

2020-09-18T15:37:00.027700Z

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

2020-09-18T15:37:35.028Z

there is an update-in

2020-09-18T15:39:09.029Z

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

2020-09-18T15:40:33.029400Z

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

2020-09-18T15:41:35.030400Z

I'm using update in atm along these lines:

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

2020-09-18T15:42:02.030900Z

ah, I must have missed the starting point

2020-09-18T15:43:11.031800Z

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)

ordnungswidrig 2020-09-18T16:27:12.032400Z

Would transients help?

2020-09-18T16:31:59.032700Z

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

2020-09-18T16:32:42.033100Z

or avoiding memory leaks?

ordnungswidrig 2020-09-18T16:32:45.033300Z

both.

ordnungswidrig 2020-09-18T16:33:01.033700Z

Not sure if tansients and subvec would work together nicely.

ordnungswidrig 2020-09-18T16:33:50.034600Z

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

ordnungswidrig 2020-09-18T16:37:44.034800Z

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

๐Ÿฅจ 1
2020-09-18T16:39:07.035100Z

nice

raymcdermott 2020-09-18T20:45:32.035500Z

no, not nice

raymcdermott 2020-09-18T20:45:50.035800Z

impressive, sure

2020-09-18T22:11:42.036300Z

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