Fork me on GitHub
#beginners
<
2018-02-02
>
Will00:02:07

I have a java project with some clojure interop, and I’m having trouble converting the maps passed back from my clojure code into java objects. The error I’m getting is clojure.lang.PersistentArrayMap cannot be cast to MyObject

Will00:02:24

Also is there a separate slack channel or community for this kind of thing? Or is this the correct place to ask questions on Java projects with Clojure interop

Alex Miller (Clojure team)02:02:42

It looks like you’re trying to pass a Clojure map where a MyObject is expected

Alex Miller (Clojure team)02:02:44

If you really need a MyObject, you’ll need to construct it and invoke setters using data from the map. Constructor looks like (MyObject.) and doto is pretty useful for calling a bunch of setters

Will02:02:10

Like this? (MyObject. my-map) @alexmiller

Alex Miller (Clojure team)03:02:11

Depends - does the MyObject constructor take a Map?

Will03:02:07

It takes a bunch of attributes

Will03:02:32

Could I do something like (List<MyObject>. (data :id my-map) (data :title my-map) (data :description my-map))?

noisesmith03:02:49

@Will almost like that - <MyObject> is something only the java compiler uses, it means nothing in clojure

noisesmith03:02:58

and List is an interface - you can use list to make something that implements List though - and so does `map

noisesmith03:02:31

eg. (map #(data % my-map) [:id :title :description]) returns a List containing the data you want in the right order

noisesmith03:02:24

I don't know what that data function is - you usually would use the keyword directly with the map to look it up

hawari03:02:15

Hi, how can I "extract a list" like (a b c) into a b c? I need it because i have an argument opts on a function, and I want to pass it to another function as is:

(defn function-b
    [& opts]
    (do-something))

(defn function-a
    [a b & opts]
    (function-b opts))

Michael Stokley03:02:33

(apply function-b opts) might work

hawari03:02:05

If function-b looks like something like this, then can I still use apply?

(defn function-b
    [b & opts]
    (do-something))

(defn function-a
    [a b & opts]
    (apply function-b b opts))

Michael Stokley03:02:23

or maybe unquote splicing? ~@

Michael Stokley03:02:45

@hawari.rahman17 in that case maybe you'd want to cons b and opts in the (apply function-b ...) expression?

noisesmith04:02:34

Apply is var arg and never needs cons, (apply f a [b c]) is the same as (apply f [a b c])

hawari03:02:48

Aha! yeah, unquote splicing might work, I'll try that

hawari03:02:33

Yeah, didn't think about cons for that purpose before,

hawari03:02:15

I'll try those solutions that you provided and look which one suits best. Thank you @michael740!

Michael Stokley03:02:42

i suspect there's a lot going on in syntax quoting. it might be overkill

hawari03:02:07

Yep, I think apply does it the best for me, less "alien" character to read, thanks again @michael740

noisesmith04:02:52

You don't need unquote splicing or cons, as I described in a thread above

hawari06:02:55

What is the most idiomatic way if there are two defmethod that has exactly the same implementation?

(defmulti multifn :type)

(defmethod multifn "type a"
  [item]
  (function-a item))

(defmethod multifn "type b"
  [item]
  (function-a item))

rauh06:02:32

@hawari.rahman17 What's "type a"/"type b"?

hawari06:02:34

just a string, the multifn will be called like this (multifn {:type "type a" :other-key "other value"})

hawari06:02:14

basically what I want to do is processing a list of items based on their :type, but some of this types shares identical characteristic

rauh06:02:36

@hawari.rahman17 So since they're strings you can't use derive, hence my question. You just have to call a fn like you do in your example, there is no build in way to bundle these

hawari06:02:25

I see, so in that case there's no way but to define it into different defmethod right?

hawari06:02:18

Ah so if it's a keyword, I can make some kind of parent-child relationship, is it? (Just got back from reading docs on derive)

rauh06:02:46

Yeah symbol, keywords, classes support derive

hawari06:02:22

Hmm... I might be able to tweak my data a little bit for this

hawari06:02:33

Thanks a lot @rauh for the pointers!

Will15:02:29

If my data looks like this

({:description Entry, :amount -730.74M, :date #inst "2018-01-26T07:00:00.000000000-00:00"}{:description food, :amount -30M, :date #inst "2018-01-27T07:00:00.000000000-00:00"})
How would I loop over each one and create a list from it? Or is there a different approach I should take?

joelsanchez15:02:23

a list of what?

Will15:02:43

A list java objects

Will15:02:01

To pass back to my java code

ghadi15:02:20

Clojure vectors and lists are already java Lists

ghadi15:02:36

likewise clojure persistent maps are java.util.Maps

ghadi16:02:06

(Doesn't mean their keys will be understood by the java code you're giving them to)

Will16:02:28

Is there a way to convert it to my java object in clojure and pass it back? Or should I try to convert the map on the java side

Will16:02:36

I can call my constructor like this (Transaction. (:description data) (:amount data) (:date data)) Which can convert to a single object but how do i loop over the list of clojure maps and convert it to a list of java Transaction objects?

sundarj16:02:44

(map (comp (partial apply #(Transaction. %1 %2 %3)) vals) data) should do the trick

sundarj16:02:09

ah wait, maps are unordered aren't they

sundarj16:02:52

@josmith2016 try (map (comp (partial apply #(Transaction. %1 %2 %3)) (juxt :description :amount :date)) data)

Will16:02:11

Thanks, I’ll try it

joelsanchez16:02:40

not sure why being so complicated

joelsanchez16:02:52

am i missing something

sundarj16:02:20

@joelsanchez no, i think i am the one who missed something. i blame fatigue 😁

Will17:02:01

If I have a BigDecimal I want to convert to a BigInteger, would I do something like this? (BigInteger. (BigDecimal/toBigIntegerExact (BigDecimal/scaleByPowerOfTen decimal 2)))

sundarj17:02:41

you should be able to use the bigint function

Will17:02:12

like this (bigint decimal)

Will17:02:53

What about if I need a java.math.BigInteger for my Java Object?

sundarj17:02:05

guess you have to use java interop for that one

sundarj17:02:07

actually there's a biginteger function @josmith2016

Will17:02:19

Ok that worked thanks @sundarj, my BigDecimal that is set to 730.34 turns into 730, Is there a way to retain the value on the right of the decimal point, and turn it into 73034?

noisesmith17:02:44

@josmith2016

+user=> 1.03M
1.03M
+user=> (BigDecimal. 1.03)
1.0300000000000000266453525910037569701671600341796875M

noisesmith17:02:00

both of those create BigDecimal rather than bigint / biginteger

noisesmith18:02:50

if you want exactly two digits to the right of the decimal point at all times, the simplest thing is to use x*100

Will18:02:40

You’re right @noisesmith I should have thought of that, thanks!

rcustodio23:02:31

What is more common to use, apache logs 2 or 1 version?

rcustodio23:02:35

Which is better?