Fork me on GitHub
#beginners
<
2018-05-27
>
andy.fingerhut00:05:54

There is an RRB-vector library that I haven't checked the performance of myself, but intends to have good big-Oh performance on concatenating arbitrary pairs of vectors, or splitting vectors at selected points. It has a catvec function for concatenating vectors, but only works on its own vectors, not Clojure's built-in ones: https://github.com/clojure/core.rrb-vector

andy.fingerhut00:05:26

That is definitely a bit off the Clojure beaten path.

seancorfield00:05:31

It says it works on regular Clojure vectors... I benchmarked it too

user=> (require '[clojure.core.rrb-vector :as fv])
nil
user=> (def big-vec (vec (range 1000)))
#'user/big-vec
user=> (def big-fvec (fv/vec (range 1000)))
#'user/big-fvec
user=> (bench (fv/catvec ['foo] big-vec))
Evaluation count : 5483040 in 60 samples of 91384 calls.
             Execution time mean : 10.801576 µs
    Execution time std-deviation : 303.262627 ns
...
user=> (bench (fv/catvec ['foo] big-fvec))
Evaluation count : 5678460 in 60 samples of 94641 calls.
             Execution time mean : 10.603606 µs
    Execution time std-deviation : 123.580560 ns
...

andy.fingerhut00:05:22

OK, I did not realize that lib supported concatenation on normal Clojure vectors, too.

seancorfield00:05:12

(me neither, until just now -- I'd never actually looked at it before, but clj -Sdeps ... makes it so easy to play with a library that I couldn't resist 🙂 )

Chris10:05:17

Can anyone advise how to compare Java objects nested in maps please? I’ve used clojure.java-time to parse two strings into (equal) Durations, but my tests fail presumably because object identity is being compared. I understand that I could use interop to call the equals method of the Duration to get a value comparison, but I don’t understand how to do this when the Duration is nested in a map.

Chris10:05:57

The test code is (is (= a b)) where a is {:q1 (jt/duration “PT1M23.456S”)}

Chris10:05:26

Oh... never mind. Typo’d a duration! Sorry

cvic12:05:51

So... I have an array of maps that looks like this

[ {:tz_label "Pacific Daylight Time", :deleted false, :is_bot false, :color "757575", :real_name "slackbot", :updated 0, :name "slackbot", :presence "active" } 
{:tz_label "Pacific Daylight Time", :deleted false, :is_bot false, :color "757575", :real_name "Some User", :updated 0, :name "some_user", :presence "away" } ]  
I want to get only the maps that contain :presence "active"

cvic12:05:34

Stuff like

(into {} (filter #(-> % val (= "active")) 
  (zipmap (map :real_name (get (clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members)) (map :presence (get (clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members)))
))
is ugly...

cvic12:05:40

Also

(map (juxt :real_name :presence) (get (clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members))
Close, but not really.

cvic12:05:11

And one more thing, I want to add one more condition (= true (:is_bot user))

cvic12:05:36

and should work...

cvic12:05:47

hm, nope...

curlyfry13:05:51

It should work! You can even skip the = true part since the result will be truthy anyway

cvic13:05:47

Doing something wrong...

(count (filter (fn [user] (= "active" (:presence user)) (not (:is_bot user)) ) ((clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members))

cvic13:05:02

And, yes, I need the non_bot users

cvic13:05:47

This works

(matching-entries ((clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members) :presence "active" :is_bot false)

curlyfry13:05:56

I don't see any and in the first example

cvic13:05:00

Doesn't work

cvic13:05:18

CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(/tmp/form-init6285822146552374847.clj:1:16

cvic13:05:37

(count (filter (fn [user] (= "active" (:presence user)) and (not (:is_bot user)) ) ((clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members)))

cvic13:05:12

Damn

user=> (filter (fn [user] (and (= "active" (:presence user))  (not (:is_bot user)) ) ((clj-slack.core/slack-request connection "users.list" {"presence" "1"}) :members)))
#object[clojure.core$filter$fn__5610 0x5aa6cbba "clojure.core$filter$fn__5610@5aa6cbba"]

cvic13:05:57

¯\(ツ)

oVerde17:05:48

Am passing these arguments:

(-> c :name)
(prn "Success"))

seancorfield17:05:51

@overde You don't seem to have a quote for your macro body...?

seancorfield17:05:27

Macros don't evaluate their arguments -- so b is literally the unevaluated form (-> c :name).

seancorfield17:05:52

I think you want

(defmacro branch?
  "Validate if the branch is actionable"
  [b & body]
  `(cond (= ~b "develop")           ~@body
         (= ~b "master")            ~@body
         (s/includes? ~b "release") ~@body
         :else false))

seancorfield17:05:02

Note the backtick around the macro body and the ~ in front of b each time to expand its value.

seancorfield17:05:10

A caution here is that will evaluate b each time it is mentioned -- because the expression is substituted into each place. It's usually safer in macros to introduce a local bound name for the argument to ensure it is only evaluated once:

(defmacro branch?
  "Validate if the branch is actionable"
  [b & body]
  `(let [b# ~b]
     (cond (= b# "develop")           ~@body
           (= b# "master")            ~@body
           (s/includes? b# "release") ~@body
           :else false)))
@overde Like this...

noisesmith17:05:47

~@body isn't appropriate there

noisesmith17:05:21

perhaps (do ~@body)

seancorfield17:05:52

@noisesmith Ooh, good catch! I'd only tested it with single form arguments!

😀 4
seancorfield17:05:19

I'd probably write it with a when and an or so there's only one copy of ~@body

(defmacro branch?
  "Validate if the branch is actionable"
  [b & body]
  `(let [b# ~b]
     (when (or (= b# "develop")
               (= b# "master")
               (s/includes? b# "release"))
       ~@body)))

😮 4
oVerde19:05:13

Thanks so much!

johnj22:05:49

on a vector does get and nth behave the same?

noisesmith22:05:03

the difference is the behavior if the index is not found

johnj22:05:50

ah one (nth) throws, thanks

johnj22:05:28

vector as a function too

noisesmith22:05:32

+user=> (nth [] 1)
IndexOutOfBoundsException   clojure.lang.PersistentVector.arrayFor (PersistentVector.java:158)
+user=> (get [] 1)
nil
+user=> (nth [] 1 :not-found)
:not-found
+user=> (get [] 1 :not-found)
:not-found

👍 4
noisesmith22:05:46

why not contains? for that?

johnj22:05:37

forgot than one

johnj22:05:42

yes, much better thanks

johnj22:05:22

specifies the intent better and looks nicer