Fork me on GitHub
#beginners
<
2019-03-28
>
qythium04:03:18

what's an idiomatic way of abstracting over a value that could be either a map or a set?

qythium04:03:56

i.e a hashed collection where I'm only interested in its keys

qythium04:03:57

contains? works on both types

qythium04:03:07

but removing items is awkward:

(if (associative? coll)
  (dissoc coll k)
  (disj coll k))

lilactown04:03:18

you could do something clever with remove

lilactown04:03:02

(into (empty coll) (remove (k coll) coll))

seancorfield05:03:33

@qythium Perhaps convert the set to a hash map (where you don't care about the values)?

seancorfield05:03:24

I would be suspicious of a function that could accept both a set and a hash map -- that suggests there's something wrong with the abstractions being used in the program perhaps?

seancorfield05:03:43

user=> (let [s #{:a :b :c :f :h}] (zipmap s s)) ; no need for this (into {} (map vector s s))
{:c :c, :h :h, :b :b, :f :f, :a :a}
Then contains? and dissoc do what you need and adding to the "set" becomes (assoc s v v)

seancorfield05:03:26

(and if you need to get a set back, (into #{} (keys s)) where s is your hash map "set")

qythium05:03:16

Thanks, I was actually "broadening" the type of an object from a set to a map, to account for cases where I would need an optional "label" for a key

qythium05:03:30

and wondering if there was a way to do so without having to go around and refactor all the function calls

qythium05:03:57

would (zipmap s s) be equivalent to the above?

seancorfield05:03:18

Yes, that would be simpler. My bad.

qythium05:03:08

thanks 🙂 I suppose the order of sequencing s is guaranteed to be the same for both arguments of zipmap, even though it's unordered

fabrao12:03:42

Hello all, I want to do something like this: - Having a big list/vector/something else ... with (it´s a list of ips) - Having like n 'consumers' that will "consume" the element of this list in thread, not more than n running at the same time Is that possible? How can I limit the n running thread function at the same time?

alexmiller13:03:48

Queue + worker pool

alexmiller13:03:16

= Java executor

cristibalan13:03:35

Hi. I was expecting to get "hola" everywhere. Is there something about map that ignores the binding?

cristibalan13:03:16

Interestingly enough, if I use pmap instead it works.

alexmiller13:03:28

map is lazy, so it returns a lazy seq of pending calls to f

alexmiller13:03:52

you are forcing those calls in printing the result returned from the binding (after the binding has been popped)

alexmiller13:03:21

pmap is sending those calls off in binding scope and then lazily looking at the results

alexmiller13:03:03

many ways to alter behavior here, but changing map to mapv would make it eager

alexmiller13:03:20

for a side-effecting thing like this, usually run! is preferred to map

alexmiller13:03:53

(defn hrm []
  (prn "M" *xxx*)
  (run! f [1 2 3]))

cristibalan13:03:44

Ah, thanks. Forgot about the laziness of map 🙂 I'll go with mapv as my actual code does other things.

alexmiller13:03:51

that's also sufficient to fix this. returns nil instead, rather than (nil nil nil)

alexmiller13:03:09

or wrap a doall around the map call

robertfrederickwarner17:03:36

Is there a simpler way to do the following?

dev=> (join "." (filter some? ["a" nil]))
"a"
dev=> (join "." (filter some? ["a" "b"]))
"a.b"

dpsutton17:03:36

that's pretty simple ...

joelsanchez17:03:21

I would thread that

robertfrederickwarner17:03:23

(->> ["a" "b"] (filter some?) (join "."))

robertfrederickwarner17:03:04

I feel like the nonthreaded is a little easier to read

robertfrederickwarner17:03:17

Thanks for the input 🙂

ghadi17:03:49

some? to me implies caring about false

user=> (some? false)
true

ghadi17:03:55

perhaps it could be clearer with (filter string?) @robertfrederickwarner

robertfrederickwarner17:03:24

That's true, I like that. Thanks!

ghadi17:03:08

no that's false 😂

dpsutton17:03:22

string.join can handle non-strings. it will attempt to coerce them

dpsutton17:03:40

(str/join "." [:a "b" 3]) so it depends on what is unacceptable to you

robertfrederickwarner18:03:50

it's the nils I need to avoid

robertfrederickwarner18:03:56

dev=> (join "." ["a" nil])
"a."

robertfrederickwarner18:03:07

I want that to come out as "a"

dpsutton18:03:14

then string? is not what you want

dpsutton18:03:58

unless you can keep nils out higher up or make sure only strings end up. then you can filter str/blank?

dpsutton18:03:22

(end up in your collection i mean)

noisesmith18:03:34

`(join "." (keep some? coll))` ? - incorrect

robertfrederickwarner18:03:42

The second value is coming out of an associative destructuring, so I could set a default for that to be ""

ghadi18:03:19

consider (remove nil?) or (filter identity)

ghadi18:03:41

I still think some? implies caring about false

robertfrederickwarner18:03:56

(remove nil?) is pretty explicit, I like that

zane18:03:47

See also keep.

noisesmith18:03:28

but keep is like map - it transforms the elements (often you can avoid needing a filter identity by using keep instead of map)

alexmiller18:03:07

nothing beats (remove nil?) when your goal is to remove nils imo

alexmiller18:03:22

it's like literally the same words :)

lady3janepl22:03:31

hey, any tips on testing of private functions? wrap them with with-test?

alexmiller22:03:06

use #'my/foo to invoke them via the var

alexmiller22:03:40

vars that refer to functions can be invoked and will invoke the function they refer to

lady3janepl22:03:16

Thanks 🙂 I was wondering if that was the more canonical options, b/c people have presented it as something of a hack

alexmiller22:03:51

I believe it's a fine thing to do :)

alexmiller22:03:13

go forth and test thy private functions :)

mario.cordova.86222:03:52

Is there anyway to select keys based off a regex?

lennart.buit22:03:33

you can just use filter and reject keys not matching your regex, right?

mario.cordova.86222:03:29

Yea, that does work... but I am starting to question the design of this function

mattmorten22:03:26

What is your function, and what concerns do you have?

mario.cordova.86222:03:05

I was using a vector of keys to pull out from a function response. The thing is that sometimes the keys are representations of many keys and I need to somehow distinguish from a regular key to multiple keys. All this complexity seems unnecessary to me but after asking its suppose to enforce that those keys get removed at another point in the system.

mario.cordova.86222:03:18

yea its kinda hard to explain

lennart.buit22:03:27

So re date-times, if you have an inst in clojure that is particularly long ago, like #inst "0001-01-01". If you convert that to an Instant, you get a particular strange representation of “0000-12-30T00:00:00Z”. I guess that sense because of shifts in calendar systems between now and thousands of years ago, but what is the inst actually representing, where is this difference in presentation coming from

hiredman22:03:15

#inst is not any particular type

alexmiller22:03:14

abstractly true, but if you literally type #inst ..., you'll get a java.util.Date and that's kind of baked in

alexmiller22:03:17

so you could rephrase as, if I have a java.util.Date representing some very old instant, and format it with "whatever inst uses", why does it present in this way?

alexmiller22:03:41

getting Clojure mostly out of the way to leave you with a Java question

alexmiller22:03:47

off the top of my head, I have no idea

hiredman22:03:03

when you say "convert that to an Instant" that is almost certainly where the difference is introduced

hiredman22:03:23

and you'll have to be more specific about how that is done

alexmiller22:03:27

yeah, that would be my question too

alexmiller22:03:48

.toInstant()?

lennart.buit22:03:13

yeah, toInstant does this indeed

alexmiller22:03:31

Date.toInstant() does Instant.ofEpochMilli(getTime()) where "getTime()" is just long millis since the beginning of 1970 (when all time began)

lennart.buit22:03:53

right, so they are both the same value so to say, but they are shown differently

lennart.buit22:03:08

they have the same number of milliseconds since epoch

lennart.buit22:03:49

I don’t feel like I am posing a coherent question, sorry!

dpsutton22:03:25

odd its 12-30 not 12-31

lennart.buit22:03:31

I did read something strange about switching of calendar systems

lennart.buit22:03:54

Try for example (.toInstant #inst "1500-01-01")

dpsutton22:03:36

do you get 1499-12-31?

lennart.buit22:03:48

no you get 1500-01-10

dpsutton22:03:17

user=> #inst "1500-01-01"
#inst "1500-01-01T00:00:00.000-00:00"

dpsutton22:03:24

are you sure its now where you are?

lennart.buit22:03:53

right, I ninja’edited: (.toInstant #inst "1500-01-01")

lennart.buit22:03:12

date and time is weird

lennart.buit22:03:21

and majorly confusing

dpsutton22:03:50

yes. i'm glad others have wrestled with it

lennart.buit22:03:14

right, but it gets extra confusing when the one API requires new style java.time.* objects, and the other old style java.util.* objects

lennart.buit22:03:38

In such a way that I can’t get my head around it anymore

andy.fingerhut03:03:21

There was about 200 years where Catholic European countries adopted the Gregorian calendar, which when adopted suddenly jumped the calendar 10 days forward, whereas Protestant countries resisted the change. Neighboring countries official calendars were off of each other by 10 days for all of that time.

lennart.buit07:03:25

right, so this date in 1500, which is pre the switch to Gregorian is printing correctly if you take into account the switch in calendar systems

alexmiller22:03:53

prob a leap day kind of thing somewhere I'd guess

dpsutton22:03:57

but i think this is a timezone thing maybe?

Clojure 1.10.0
user=> #inst "0001-01-01"
#inst "0001-01-01T00:00:00.000-00:00"
user=>

dpsutton22:03:04

but i'm guessing its a UTC and then local time thing

dpsutton22:03:09

and in a few hours i'll see it too

alexmiller22:03:15

I don't think I'd rely much on the Instant object toString() you're seeing in there

dpsutton22:03:46

the Z means UTC correct?

dpsutton22:03:21

this makes sense to me (modulo the 12-30 not 12-31).

lennart.buit22:03:02

Okay, not my most coherent question, thanks for thinking along…

lady3janepl22:03:44

You’re not going to get year 0 you shouldn’t be getting year 0, b/c year 0 does not exist (if you use the AD/BC aka CE/BCE)

lady3janepl22:03:20

…except in ISO when it is, turns out. https://en.wikipedia.org/wiki/Year_zero#ISO_8601 Calendars in the deep past are worse than handling summer/winter time and leap years 🙂

lennart.buit22:03:07

That’s quite interesting, thanks

lennart.buit22:03:55

I feel like I have this half grasp of what is happening with jumps in calendars

lennart.buit22:03:07

It’s just very confusing

lady3janepl23:03:22

Yeah it’s … people are not tidy 🙂

lady3janepl23:03:42

A number of days went missing when switching from Julian to Gregorian calendar for ex

lennart.buit23:03:19

Yes, and it seems that java.util.Date just ignores that fact

lennart.buit23:03:48

Or at least in its toString

lady3janepl23:03:22

some holidays look weird now, but they used to fall on solar dates, St Lucy used to be winter solstice

lady3janepl23:03:25

I think maybe going that far back you’ll need to use libraries

lady3janepl23:03:14

there’s a GregorianCalendar and more recently JulianFields in java itself… but it’s been long since I did something with the language so I’d advise checking for the current recommended method somewhere more official 🙂

nathantech200515:03:07

I was reading in wiki that any year divisible by 4 is the leap year on Gregorian Calendar?

lady3janepl15:03:58

any time you think you know something about dates, you don’t know something about dates

lady3janepl15:03:06

> These extra days occur in years which are multiples of four (with the exception of centennial years not divisible by 400).

lady3janepl15:03:49

also we have leap seconds which happen whenever people can be bothered to add them