Fork me on GitHub
#clojure
<
2023-05-25
>
simongray10:05:02

I have a sequential Clojure collection. I can call (.iterator coll) on it to get an iterator, but how do I get a parameterized Java iterator, e.g. Iterator<Triple> in this case?

simongray10:05:54

The coll already contains only Triple objects, but I think the parameterized type of any Clojure collection is Object . This doesn’t work when I need to call a Java method that takes Iterator<Triple> as one arg.

Alex Miller (Clojure team)10:05:16

Clojure collections are raw but you can cast them to the needed type. Or reify a Java interface that returns the generic type

simongray10:05:18

> Clojure collections are raw but you can cast them to the needed type. How though…? Google is not helping… :S

p-himik11:05:42

Add ^Iterator in front of the argument to that Java method. You can't add <Triple> but you also don't need to.

simongray11:05:09

@U2FRKM4TW How exactly would Java know which method to delegate to…? This is an overloaded method.

p-himik11:05:57

What are the overloads?

simongray11:05:18

Ahhhhh, my bad, it actually isn’t, the method name is slightly different for the different parameterised types. I will try adding the type hint and see if it makes a diffeence.

p-himik11:05:53

Yeah, you can't have a method be overloaded on, say, Iterator<Triple> and Iterator<T> - you'll get a "name clash: methods have the same erasure" error from Java compiler.

2
genmeblog11:05:06

Generics in Java are used only at compile time, after compilation information about generics is removed. https://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure

genmeblog11:05:49

So Iterator<Triple> and Iterator<T> are the same classes

Alex Miller (Clojure team)12:05:30

sorry, I assumed from the question that you were working in Java....

simongray12:05:41

np @U064X3EF3, I was confused too!

Brian Beckman13:05:03

SOLVED Hello — macro puzzle of the day, here. I am processing vectors of naked int-symbol pairs to produce hashmaps, like this: input: [1 nym1, 2 nym2] desired output: ({:stid 1, :nym nym1} {:stid 2, :nym nym2}) If I manually quote the symbols, I get the desired output:

(pprint (for [[stid nym]
              ;; MANUALLY QUOTED:
              (partition 2 [1 'nym1, 2 'nym2])]
          {:stid stid, :nym nym)))
;; => ({:stid 1, :nym nym1} {:stid 2, :nym nym2})
Manual quoting is not feasible for my big data sets, and preprocessing with, say, awk, is odious. So I try a macro! Results are inexplicably nil:
(defmacro maps-of-pairs [naked-pairs]
  (let [pairs (partition 2 naked-pairs)
        fpairs (for [[stid nym] pairs]
                 `{:stid ~stid, :nym '~nym})]
    `~fpairs))
                       ;; NOT MANUALLY QUOTED:
(pprint (maps-of-pairs [1 nym1, 2 nym2]))
;; => nil
Where did I go wrong, please & thanks?

🏁 2
igrishaev13:05:51

Why would you write a macro? Just create a function and pass a quoted vector like this:

(defn by-chunks [n coll]
  (partition n n [] coll))

(def data
  '[1 foo 2 bar 3 baz])

(for [[int sym] (by-chunks 2 data)]
  {:stid int :nym sym})

🏁 4
Brian Beckman13:05:07

yes, that works better than trying to distribute the quotes to the symbols. Thanks. I have some more complications in my actual application context, but this is a good start at a solution.

Brian Beckman13:05:27

Thad did it! SOLVED. Thanks again.

kennytilton14:05:46

For future macrology reference:

(defmacro maps-of-pairs [naked-pairs]
    (let [pairs (partition 2 naked-pairs)
          fpairs (for [[stid nym] pairs]
                   `{:stid ~stid, :nym '~nym})]
      `[~@fpairs])) ;; <==== remember, we are outputting code
  ;; NOT MANUALLY QUOTED:
  (pprint (maps-of-pairs [1 nym1, 2 nym2]))

output:
[{:stid 1, :nym nym1} {:stid 2, :nym nym2}]
hth!

👍 4
ajones02:05:14

another option for future readers, depending on the constraints of the larger picture, zipmap can be used instead of for here to simplify down to:

(def data '[1 nym1 2 nym2])

(map #(zipmap [:stid :nym] %)
     (partition 2 data))
have used it a lot in the past for running similar transforms on csv data.

Can13:05:46

(def !type (atom ["String"]) )
(get @!type 0)

;this is working if I give manually "String" instead of this method (get @!type 0). 
(defn f [text]
  (count (re-seq #(get @!type 0) text)))

(reduce + (into [] (map f (map :content vec))))         <--------- Why this is not working? 

genmeblog13:05:56

re-seq accepts regular expression as the first argument. #(get ...) is a function not regex. Use re-pattern instead.

4
Can13:05:43

Thanks I understand and worked.

👍 2