Re: Method overloading proxy method
Well the solution in my case was to create a map from visited types to visited members (http://tinyurl.com/poq5e2) the visitation logic uses this map in order to invoke the next visit (http://tinyurl.com/ pkugra). This pattern enables visitors to be implemented in Clojure for pure Java based frameworks (like AST visitors). On May 5, 6:00 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: On May 4, 11:52 pm, Alex Osborne a...@meshy.org wrote: Thankfully, Mark managed to figure out a way of doing it with with gen- class by using an undocumented (?) feature where you can put types into the method names so as to pick the exact one you want to override: (ns org.example.FancyInputStream (:gen-class :extends java.io.InputStream)) (defn -read-void [this] (int \a)) Related: You can also use the :exposes-methods argument to gen-class to access superclass methods. -Stuart Sierra --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Method overloading proxy method
On Mar 23, 9:55 am, ronen nark...@gmail.com wrote: [... what] I actually need is a way of overriding specific methods (like the visit (MethodDeclaration n, A arg) and not all of them. I keep running into this problem again and again myself, so I thought I might post some notes. The short of it: doing anything fancy with proxy gets hard fast but there is a way to do it with gen-class. In my case I'd like to subclass java.io.InputStream and implement the abstract read() method but NOT override the non-abstract read(byte[] b) and read(byte[] b, int off, int len). So what I really want to do is something like this: (def is (proxy [java.io.InputStream] [] (read [] (int \a Which works okay for this: (.read is) = 97 But if anything calls the other overloaded methods like this: (.read is (make-array (. Byte TYPE) 10)) We get a: java.lang.IllegalArgumentException: Wrong number of args passed to: user$fn--1844$fn So it seems as Stuart explained, proxy overrdes all the read methods, not just the zero-arity one. So my next attempt was to use proxy-super. This was also the suggestion from my friendly neighbourhood Clojure guru, Mark Triggs: (def is (proxy [java.io.InputStream] [] (read [ args] (println args) (cond (= (count args) 0) (int \a) (= (count args) 1) (proxy-super read (first args)) (= (count args) 3) (proxy-super read (first args) (second args) (nth args 3)) (.read is) = 97 (.read is (make-array (. Byte TYPE) 10)) = java.lang.AbstractMethodError: java.io.InputStream.read()I 0: clojure.proxy.java.io.InputStream.read(Unknown Source) 1: java.io.InputStream.read(InputStream.java:154) 2: clojure.proxy.java.io.InputStream.read(Unknown Source) 3: java.io.InputStream.read(InputStream.java:85) 4: clojure.proxy.java.io.InputStream.read(Unknown Source) So what's going on here? Well, my (.read is bytes) is doing (proxy- super read bytes) okay. The java code then does a this.read(bytes, 0, bytes.size). So my code passes this through to the super-class again which finally does a this.read(). Unfortunately, as Mark explains [proxy-super] works by temporarily hiding your overriding implementation of a method. For abstract classes that freaks out the JVM because it looks like you haven't implemented everything. So since read has been hidden, the java code attempting to call it just sees it's own abstract method which it obviously can't execute. In this case I can obviously resort to just reimplementing the other two methods, but it's a bit frustrating. This is a fairly common pattern in Java code, needing to subclass something and define one method foo() where there's a bunch of other overloaded convenience versions of it in the superclass which call the one you've overriden. Thankfully, Mark managed to figure out a way of doing it with with gen- class by using an undocumented (?) feature where you can put types into the method names so as to pick the exact one you want to override: (ns org.example.FancyInputStream (:gen-class :extends java.io.InputStream)) (defn -read-void [this] (int \a)) This now works as expected. Mark's notes on this are here: http://dishevelled.net/Tricky-uses-of-Clojure-gen-class-and-AOT-compilation.html --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Method overloading proxy method
On May 4, 11:52 pm, Alex Osborne a...@meshy.org wrote: Thankfully, Mark managed to figure out a way of doing it with with gen- class by using an undocumented (?) feature where you can put types into the method names so as to pick the exact one you want to override: (ns org.example.FancyInputStream (:gen-class :extends java.io.InputStream)) (defn -read-void [this] (int \a)) Related: You can also use the :exposes-methods argument to gen-class to access superclass methods. -Stuart Sierra --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Method overloading proxy method
On Mar 21, 6:13 pm, ronen nark...@gmail.com wrote: Hello there, Iv been trying to implement a proxy on a class (http://code.google.com/p/javaparser/source/browse/trunk/JavaParser/sr...) that has multiple overloaded methods (same arity different types), trying (defn create-visitor [] (proxy [VoidVisitorAdapter] [] (visit [method, arg] (println method)) (visit [exp, arg] (println type This results with compilation error Caused by: java.lang.IllegalArgumentException: Method 'visit' redefined. Type hints didn't help either: Proxy doesn't care about argument types. You need one method with a conditional: (defn create-visitor [] (proxy [VoidVisitorAdapter] [] (visit [arg1 arg2] (if (instance? MethodDeclaration arg1) ... You could also define a multimethod and call it from the proxy. -Stuart Sierra --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Method overloading proxy method
Hello there, Iv been trying to implement a proxy on a class ( http://code.google.com/p/javaparser/source/browse/trunk/JavaParser/src/japa/parser/ast/visitor/VoidVisitorAdapter.java?spec=svn77r=77) that has multiple overloaded methods (same arity different types), trying (defn create-visitor [] (proxy [VoidVisitorAdapter] [] (visit [method, arg] (println method)) (visit [exp, arg] (println type This results with compilation error Caused by: java.lang.IllegalArgumentException: Method 'visit' redefined. Type hints didn't help either: (defn create-visitor [] (proxy [VoidVisitorAdapter] [] (visit [#^MethodDeclaration method, arg] (println method)) (visit [#^AssignExpr exp, arg] (println type Any ideas? Thanx --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---