Fork me on GitHub
#clojure-dev
<
2018-04-23
>
schmee16:04:12

is there a technical reason why Clojure doesn’t automatically handle Java varargs, so you could avoid (into-array Object your-thing)?

seancorfield17:04:27

Isn't that more because Java doesn't really support varargs, and just translates the function to one that accepts an array under the hood? That's an interop detail that affects every language calling into Java.

ghadi17:04:43

I think I wrote a varargs macro sometime that was sugary (varargs methodName target a b c ^HintTheArray ... x y z)

ghadi17:04:05

yes the type hint is on the ... symbol

ghadi17:04:05

in the case of an empty varargs: (varargs methodName target a b c ^HintTheArray ...)

ghadi17:04:46

The analyzer could be compatibly extended to understand this syntax when doing a non-reflective call to a known varargs method: (.methodName target a b c ^HintTheArray ... x y z)

Alex Miller (Clojure team)17:04:56

I think there is 0 chance we are going to do that

ghadi17:04:37

That's why I wrote the macro

ghadi17:04:13

It is really annoying to have to type hint the output of make-array

schmee18:04:55

thanks for linking the issue!

schmee18:04:38

so if my interpretation is correct, the problem isn’t really that it’s unclear how it should work, it’s more that noone has actually implemented it, made sure all the corner cases are covered etc?

ghadi19:04:38

I think it's really unclear how/if it should work

ghadi19:04:04

low bang for the buck on CLJ-440

Alex Miller (Clojure team)19:04:06

I think this is one of those things where the goal is obvious but there are a lot of non-obvious and potentially ambiguous cases to be covered

schmee19:04:21

you’re both right probably, but it’s also in that tantalising region of small enough to be understandable and big enough to be interesting 😉

Alex Miller (Clojure team)19:04:05

this is certainly an annoying part of Java interop and one that would be nice to improve

dominicm19:04:58

I've tripped over it a number of times, I'd love to see it fixed.

Alex Miller (Clojure team)19:04:36

will probably also complicate the Reflector method selection code, which already has some pending trauma due to the Java 9 changes

bronsa20:04:58

I think the code in the Reflector has ptsd at this point, not just java 9 trauma

cfleming22:04:00

@ghadi Do you have that macro around for the terminally lazy?

cfleming22:04:14

Hehe, I’ll roll my sleeves up then.

ghadi22:04:23

(ns varargs
  (:require [clojure.spec.alpha :as s]
            [clojure.string :as str]))

(s/def ::method
  (s/or :static qualified-symbol?
        :instance (s/and simple-symbol? #(str/starts-with? (name %) "."))))

(s/def ::separator
  (s/and #{'...} (comp :tag meta)))

(s/def ::varargs-invoke
  (s/cat :call ::method
         :anything (s/* any?)
         :sep ::separator
         :varargs (s/* any?)))

(s/fdef varargs :args ::varargs-invoke)

(defmacro varargs [& args]
  (let [[call [sep] args] (partition-by #{'...} args)
        tag (-> sep meta :tag)]
    `(~@call ~(with-meta `(into-array ~tag ~(vec args))
               {:tag tag}))))

ghadi22:04:02

@cfleming it was something like that. Note that it only takes Class type hints, not #{bytes ints chars longs} sugar

ghadi22:04:33

nice thing about speccing the macro is that it's automatically checked simple_smile

ghadi22:04:07

I'm sure there is a better way to express the last couple lines, but I just crapped that out

gfredericks22:04:14

it's fundamentally ambiguous, I think. so it requires user input somehow to say whether you're passing one arg or an array of them

ghadi22:04:31

that's exactly right.

ghadi22:04:37

hence the ...

gfredericks22:04:41

I typed that after seeing the first three messages

gfredericks22:04:46

slack showed me the other dozen after I sent it

gfredericks22:04:00

which I haven't read yet so I don't know how redundant I was being 🙂

ghadi22:04:49

adding the ... as a separator acts as user input to tell it how to splat