0

I am new to Clojure and I am trying to implement a Java interface to Clojure. Specifically this code

import javax.print.*;

class Test {

    public static void main (String [] args)
    {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        System.out.println("Number of print services: " + printServices.length);

        for (PrintService printer : printServices)
            System.out.println("Printer: " + printer.getName()); 
    }
}

The PrintService is an interface and the PrintServiceLookup a constaructor class. I am confused on how to use reify and proxy. My goal is to get the installed printers on my system. Can anyone explain with an example on how to use reify or proxy? From the documendation I understand that I must load the interface and then the methods I want to use, but I can't make it work. From Java perspective as I understand it, I must get an object from PrintServiceLookup.lookupPrintServices() and apply to it the getName function from PrintService interface and then to print it. My try till now

(defn print-serv []
  (let [printS (proxy [PrintService PrintServiceLookup] []
       (getName [])
                 (lookupPrintServices [])
    )]
    (.println (System/out) (.getName printSe))
    )

    )

I am pretty sure is all the way wrong but I can't understand how really reify and proxy work, if anyone could expain it to me better I would be grateful!

1 Answer 1

2

The Java code you posted doesn't implement an interface. It looks like you're just trying to call a static method and iterate over the result:

(let [printers (PrintServiceLookup/lookupPrintServices nil nil)]
  (println "Number of print services:" (count printers))

  (doseq [^PrintService p, printers]
    (println (.getName p)))

The doseq loop can also be written simply as:

(doseq [p printers]
  ...)

I just included the ^PrintService type hint for completeness.

Also note, you don't have to write the full (.println (System/out) ...). Clojure has the println shortcut.

Sign up to request clarification or add additional context in comments.

4 Comments

You were right, that worked!!! Thank you!! But in the (doseq [^PrintService p, printers] you actually tell coljure that p it belongs to PrintService interface?What actually happens there?
@narocath Np. Glad to help. And the ^PrintService type hint is optional. It's just telling the compiler that p is a PrintService. I usually include type hints when using interop though, even though they're optional. It lets your IDE give you better autocomplete guesses, and allows you to avoid reflection, which generally leads to faster code. If you skip the hint, your IDE might give warnings about not being able to resolve .getName, which will require reflection at runtime.
I see, one more question, when I should load an interface, I mean in this specific case would it be correct to load the interface. I can't understand when I need to implement a whole interface and when I need just call static methods?
@narocath That's more of a broad programming question specific to certain scenarios than anything having to do with Clojure specifically. It's the same answer in Clojure as it is in Java. And I'm not sure what you mean by "load an interface". In this case, there's no need to implement an interface since you aren't trying to supply code that does something specific to be used elsewhere. Just like in the Java code, you just needed to call the static lookupPrintServices method to get some results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.