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

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

yuhan04:03:56

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

yuhan04:03:57

contains? works on both types

yuhan04: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")

yuhan05: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

yuhan05:03:30

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

yuhan05:03:57

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

seancorfield05:03:18

Yes, that would be simpler. My bad.

yuhan05: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?

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.

Alex Miller (Clojure team)13:03:28

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

Alex Miller (Clojure team)13:03:52

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

Alex Miller (Clojure team)13:03:21

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

Alex Miller (Clojure team)13:03:03

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

Alex Miller (Clojure team)13:03:20

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

Alex Miller (Clojure team)13: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.

Alex Miller (Clojure team)13:03:51

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

Alex Miller (Clojure team)13:03:09

or wrap a doall around the map call

robertfw17: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 ...

robertfw17:03:59

I suppose so

joelsanchez17:03:21

I would thread that

robertfw17:03:23

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

robertfw17:03:04

I feel like the nonthreaded is a little easier to read

robertfw17: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

robertfw17:03:24

That's true, I like that. Thanks!

ghadi17:03:08

no that's false 😂

😛 4
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

robertfw18:03:50

it's the nils I need to avoid

robertfw18:03:56

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

robertfw18:03:07

I want that to come out as "a"

dpsutton18:03:14

then string? is not what you want

robertfw18:03:42

I see your point

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

robertfw18: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

robertfw18: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)

✔️ 4
Alex Miller (Clojure team)18:03:07

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

👍 20
Alex Miller (Clojure team)18:03:22

it's like literally the same words :)

3Jane22:03:31

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

Alex Miller (Clojure team)22:03:06

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

👍 4
Alex Miller (Clojure team)22:03:40

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

3Jane22:03:16

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

Alex Miller (Clojure team)22:03:51

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

Alex Miller (Clojure team)22:03:13

go forth and test thy private functions :)

Mario C.22: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 C.22:03:29

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

butterguns22:03:26

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

Mario C.22: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 C.22: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

Alex Miller (Clojure team)22:03:14

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

Alex Miller (Clojure team)22: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?

Alex Miller (Clojure team)22:03:41

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

Alex Miller (Clojure team)22: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

Alex Miller (Clojure team)22:03:27

yeah, that would be my question too

Lennart Buit22:03:13

yeah, toInstant does this indeed

Alex Miller (Clojure team)22: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

Alex Miller (Clojure team)22: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

Alex Miller (Clojure team)22: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…

3Jane22: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)

3Jane22: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

3Jane23:03:22

Yeah it’s … people are not tidy 🙂

3Jane23: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

3Jane23:03:22

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

3Jane23:03:25

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

3Jane23: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 🙂

hipster coder15:03:07

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

3Jane15:03:58

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

3Jane15:03:06

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

3Jane15:03:49

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