Re: Method overloading proxy method

2009-05-09 Thread ronen

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

2009-05-05 Thread Alex Osborne

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

2009-05-05 Thread Stuart Sierra

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

2009-03-22 Thread Stuart Sierra

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

2009-03-21 Thread ronen

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
-~--~~~~--~~--~--~---