Fork me on GitHub

I'm getting a Cannot disambiguate overloads of ProcessBuilder warning from Cursive in the (defn build-process [cmd] ... (java.lang.ProcessBuilder. cmd) ...) expression. It also manifests at runtime as this message:

Reflection warning, /Users/onetom/.../src/testbed.cljc:92:9 - call to java.lang.ProcessBuilder ctor can't be resolved.
I tried to add ^List in front of cmd and that made the issue go away, but List is not defined in Babashka...


what is the most generic type I should use in these situations? the constructor is defined to accept "var-args" and I read somewhere, to call such functions, Clojure should provide them with some array-ish thing.


(require '[clojure.reflect :as r])
(import '[clojure.reflect Constructor])
(->> (r/type-reflect ProcessBuilder)
     (filter (comp #{Constructor} type)))

(#clojure.reflect.Constructor{:name java.lang.ProcessBuilder,
                              :declaring-class java.lang.ProcessBuilder,
                              :parameter-types [java.util.List],
                              :exception-types [],
                              :flags #{:public}}
 #clojure.reflect.Constructor{:name java.lang.ProcessBuilder,
                              :declaring-class java.lang.ProcessBuilder,
                              :parameter-types [java.lang.String<>],
                              :exception-types [],
                              :flags #{:varargs :public}})


I'm wondering if there is a literal form for java.lang.String<> to use it as a type hint 😕


^Ljava.lang.String or ^java.lang.String<> doesn't work..


@U086D6TBN This works with both bb and clj:

$ bb -e '(set! *warn-on-reflection* true) ((fn [& args] (ProcessBuilder. ^java.util.List args)) "ls")'


So you get your reflection avoided and also compatible with bb


List is not a thing both in bb and clj without importing it or fully qualifying it


bb -e '(import (quote [java.util List])) ((fn [& args] (ProcessBuilder. ^List args)) "ls")'
java.lang.Exception: Unable to resolve classname: java.util.List [at line 1, column 1]


i was importing it in Clojure and as i mentioned it made Cursive happy, but not bb


Cursive recommends using the short form of fully qualified class references; that's how I cornered my self 🙂


Ah right, bb allows you to use type hints without actually needing those classes to be in bb


just for compatibility


i can't remember reading about this in the bb docs so far. might worth mentioning it


it will try to use the type hint if it can resolve the class


i feel like to make bb a good alternative to bash, using any kind of external process related functionality should be really friendly


I think it might be better to just add the java.util.List class to bb (I was kind of surprised it wasn't already in there)


If vec would have a return type tag on it, one could do this with (ProcessBuilder (vec args)) right?


are you asking me? i don't know. i didn't have to deal with type metadata much on my clojure journey so far 🙂 im not even sure where should the return type tag go. on the var or the arg vector...


which is i think a testament to how practical clojure is 🙂 i've trained a few people clojure over the past ~5 years. wrote a bunch of useful programs, even in clojurescript with hoplon, yet there was hardly any need to deal with type tags.


If you use this function:

(defn vec2 ^clojure.lang.PersistentVector [x]
  (vec x))
around your arguments to ProcessBuilder, the reflection warning goes away, because PersistentVector implements List. Maybe there's a reason why clojure.core doesn't have the type tag on vec as of now. @U064X3EF3?

Alex Miller (Clojure team)15:08:50

Generally, collections are never hinted with the concrete type - it just relies on polymorphism are the call site

Alex Miller (Clojure team)15:08:53

The return here is not necessarily that type either

Alex Miller (Clojure team)15:08:34

If you make your own concrete vector collection, and call vec on it, you’d get that type


ok, makes sense