Fork me on GitHub
#clojure
<
2022-07-19
>
Martynas Maciulevičius10:07:37

Hey. I'm trying to find how to specify type hint for my Object array and I can't find it here: https://clojure.org/reference/java_interop#typehints https://clojure.org/reference/metadata#_metadata_reader_macros Are there better places to look in?

p-himik11:07:44

Try ^"[Ljava.lang.Object;".

Martynas Maciulevičius11:07:52

I used ^java.util.ArrayList. I'll try that too.

p-himik11:07:58

An array list and an array are two very different things - make sure you to use the right one.

Martynas Maciulevičius11:07:33

I know. I only wanted something that I wouldn't need to use atom . I have a dependency injection framework and it returns less data that I want so I'll make a hack to mutably get something I want from initialization. ArrayList and array are very different things and I wanted it to spend little time on initialization. Obviously I was trying to create already pre-allocated ArrayList (even though it's only one item). But anyway. It wasn't a big gain. I lost too much performance by being forced to use DI framework as it's hardcoded into the initialization of a third-party lib.

Martynas Maciulevičius11:07:43

I gained more performance by removing logging than doing this hack :rolling_on_the_floor_laughing: (20ms per call)

roklenarcic13:07:53

What’s the opposite operation of not-any?? This one comes up many times, I want true if any object in coll fits predicate.

rolt13:07:51

(boolean (some ...)) ?

roklenarcic13:07:36

(not-any? #(= (:id %) 1) coll)
vs (some #(when (= (:id %) 1) true) coll) is way more wordy and redundant, also first one returns true/false, second one returns true/nil

borkdude13:07:37

yes, it's more verbose 🤷

rolt13:07:05

that's a poor example because = will return true so the when is unnecessary

roklenarcic13:07:34

some always kinda stood out to me…

rolt13:07:43

(def any? (comp boolean some))

roklenarcic13:07:57

any? is already defined in clojure.core

rolt13:07:21

call it as you want

roklenarcic13:07:43

also putting boolean around it doesn’t work really… you need to also change predicate to return nil

roklenarcic13:07:00

if you return false in some predicate it will keep going

roklenarcic13:07:16

that’s why it’s so clunky and you have to use when

rolt13:07:17

hmm no you don't ? am I missing someting ? do you have a counter example ?

roklenarcic13:07:06

some returns first non-nil result of the predicate given

roklenarcic13:07:32

oh wait… I am wrong, other *-some operations do that… my bad

roklenarcic13:07:10

sorry about that I thought it used the same rules as if-some when-some etc

rolt13:07:38

yeah it's a bit confusing, that's the behaviour of some?

afleck14:07:52

is there a good way to reuse core.match patterns to do different things on the same match in different places? I’m wishing I could do something like

(def match-pattern '[a b])
(defn subtract [x]
  (clojure.core/match x
    match-pattern
    (- a b)
    _ x))
(defn add [x]
  (clojure.core/match x
    match-pattern
    (+ a b)
    _ x))

Joshua Suskalo15:07:02

This is part of why Rich doesn't like pattern matching, it's brittle and doesn't handle code reuse. If you want to do this it must be done with your own wrapper macro.

afleck15:07:06

yeah. currently i’m resorting to producing data from the match, like

(defn match-ab [x]
  (clojure.core.match/match x
    [a b] {:a a :b b}
    _ nil))
and then operating upon that. it works fine, just wondering if perhaps there’s a better way. what’s the alternative approach that is not based on pattern matching at all?

Joshua Suskalo15:07:43

could just make a predicate that returns if it's a two-tuple and nil otherwise and do

(defn match-ab [x]
  (when (two-tuple? x)
    (zip-with [:a :b] x)))

afleck15:07:22

yeah, the actual case is with nontrivial nested vectors, so the pattern match is very convenient for extracting the data

Joshua Suskalo15:07:11

sure, then make your validation also extract the data into a more convenient format.

Joshua Suskalo15:07:00

it doesn't just have to return a boolean

Joshua Suskalo15:07:17

when-some is your friend

afleck15:07:05

right, and I do. I was just saying that it’s nice to be able to use clojure.match for that validation, and return the data as opposed to operating upon the data. it’s my way of attempting to get the best of both worlds: convenience of pattern matching, but with some resusability

Joshua Suskalo16:07:39

sure, that makes sense, but unfortunately core.match doesn't really support this, and I think for good reason, as the example you posted breaks hygeine in an unpredictable way that can cause issues.

👍 1
shaunlebron20:07:31

Is there a cool way for map to refer to the previous item in a sequence, or should I just reduce it

shaunlebron20:07:22

(I’m adding a running balance to a sequence of transactions)

p-himik20:07:19

map cannot do that without an extra step where you create an extra shifted sequence and combine it into a sequence of pairs with the original sequence. But reduce or loop can do that.

☝️ 1
pavlosmelissinos20:07:39

Chances are you can also use partition and then map over its result

isak20:07:57

Or if it is something like a vector, you could map over the indexes instead of the elements

jakemcc20:07:30

map can operate over multiple sequences at once, so something like below might also work.

user> (let [values (range 10)]
        (map (fn [prev curr] [prev curr])
             values
             (rest values)))
([0 1] [1 2] [2 3] [3 4] [4 5] [5 6] [6 7] [7 8] [8 9])

phronmophobic20:07:02

A common idiom is:

(map (fn [prev next]
        (my-combine prev next)
     coll
     (rest coll))
I think it's pretty cool 😎 .

shaunlebron20:07:30

Thanks guys! I like the different methods. Since I needed a running sum, I found reductions and went with this:

(def txns [{:amount 10}
           {:amount 20}
           {:amount 30}])

(def bals (reductions + (map :amount txns)))
;; => (10 30 60)

(mapv #(assoc %1 :balance %2) txns bals)
;; =>
;; [{:amount 10, :balance 10}
;;  {:amount 20, :balance 30}
;;  {:amount 30, :balance 60}]

Joshua Suskalo20:07:42

Like was mentioned about partition before, you could use (map your-fn (partition 2 1 coll))

Joshua Suskalo20:07:45

but yeah, reductions is like scan in other functional languages and does this well, yeah

shaunlebron20:07:35

yeah I realized I actually need more than the previous item, needed an accumulated sum as of the previous item