From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from MTA-11-3.privateemail.com (mta-11-3.privateemail.com [198.54.122.105]) by sourceware.org (Postfix) with ESMTPS id 21BBF3858001 for ; Tue, 7 Sep 2021 19:35:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 21BBF3858001 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=eatonphil.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eatonphil.com Received: from mta-11.privateemail.com (localhost [127.0.0.1]) by mta-11.privateemail.com (Postfix) with ESMTP id C785818001FD for ; Tue, 7 Sep 2021 15:35:43 -0400 (EDT) Received: from mail-ua1-f44.google.com (unknown [10.20.151.209]) by mta-11.privateemail.com (Postfix) with ESMTPA id 94CFB18000B2 for ; Tue, 7 Sep 2021 15:35:43 -0400 (EDT) Received: by mail-ua1-f44.google.com with SMTP id j31so6166530uad.10 for ; Tue, 07 Sep 2021 12:35:43 -0700 (PDT) X-Gm-Message-State: AOAM5333B4mGnjL/aEanNb/AlA1FaKnjiaLqWhN+Q2oUEq4GzVZQ0Rr4 2DV90zTNiFngbvBOD8cwBDliAhrgFqh9MI/O/Vw= X-Google-Smtp-Source: ABdhPJwJFU9ydbsxC3LGNw4n/3IKbsEEr8JrKYmK9IoOAeoQKoXWUAIHihZ8vJJ/eqhEAl8Q3t4DofKGLeSw6GoVnVM= X-Received: by 2002:ab0:3a85:: with SMTP id r5mr10308508uaw.103.1631043342082; Tue, 07 Sep 2021 12:35:42 -0700 (PDT) MIME-Version: 1.0 References: <5hzGa_Y5K9Av5y0olKFg4Qb_A8LuHAwRZiCNDB2oN17IDMHkgCxAhIGYUV0ttSsfsL82Krtjbc2I1AteZ5wQWGRBTMYf-dV1PHINjmezWa4=@protonmail.com> In-Reply-To: <5hzGa_Y5K9Av5y0olKFg4Qb_A8LuHAwRZiCNDB2oN17IDMHkgCxAhIGYUV0ttSsfsL82Krtjbc2I1AteZ5wQWGRBTMYf-dV1PHINjmezWa4=@protonmail.com> From: Phil Eaton Date: Tue, 7 Sep 2021 15:35:31 -0400 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: Receiver class does not define or inherit an implementation of the resolved method To: spellcard199 Cc: Per Bothner , kawa mailing list X-Virus-Scanned: ClamAV using ClamSMTP X-Spam-Status: No, score=-0.2 required=5.0 tests=BAYES_00, BODY_8BITS, HTML_MESSAGE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: kawa@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Kawa mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Sep 2021 19:35:48 -0000 > Since it is a Java library and, as I supposed, Java does not allow to have 2 methods with the same name and parameter types [1][2], if I were in you I would first try to translate your example to plain Java without Jooby's annotations (I don't know how to do it). Maybe asking the people working on Jooby may be an option? The problem is that Jooby does _Java_ source code analysis (not reflection). It literally parses your handler source code to figure out what the return type actually is (since the Object return type masks it). It only does this though if there's not a method it can introspect without source code analysis. I spent a while digging around Jooby's APIs and this was the only way I could shoehorn non-Java code into it. Since I put decent amount of effort into the ABCL code (needed to submit a patch to the ABCL team) I am reluctant to give up now in Kawa without finding a way to hack this up. Furthermore the problem is that almost every hip Java API is designed like this. They are very unfriendly to function-oriented paradigms. Now that I think of it though maybe using Kawa's class annotation support will help me fight less with Jooby since it does want you to annotate classes (which I was ignoring because I was trying to use classes as little as possible). On Tue, Sep 7, 2021 at 1:58 PM spellcard199 wrote: > I cloned your repo, cd'ed into abcl, run mvn install and then make. I > still had to copy-paste your main.lisp in the repl but it > worked. After commenting out each of the 2 apply methods I could see > what problem you have. > > If I understand correctly, basically what you are trying to do is > replicate at a language level what Jooby already does in pure > Java. > > My opinion as a not-experienced programmer that has never used Jooby > is that there may be some other way to use the Jooby api. Why > re-solving with a language-specific solution a problem that somewhere > in Jooby has already been implemented? Since it is a Java library and, > as I supposed, Java does not allow to have 2 methods with the same > name and parameter types [1][2], if I were in you I would first try to > translate your example to plain Java without Jooby's annotations (I > don't know how to do it). Maybe asking the people working on Jooby may > be an option? > > > I guess that's not the place where the method name is generated for > > bytecode compilation. If anyone could point me at where that happens > > that would help. > > Just out of curiosity... I've not tested it, but I think it happens in > gnu.expr.LambdaExp.addMethodFor, around line 1144. > > > Thanks! > > np, but I wasn't very helpful =3D/. > > [1] > https://stackoverflow.com/questions/2439782/overload-with-different-retur= n-type-in-java > [2] > https://stackoverflow.com/questions/5561436/can-two-java-methods-have-sam= e-name-with-different-return-types > > =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 Original = Message =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 > On Tuesday, September 7th, 2021 at 3:02 PM, Phil Eaton > wrote: > > Good question! I don't know how to get the ABCL-emitted bytecode otherwis= e > I would have just posted that. > > But I can describe to you the behavior that makes me say it emits two > functions with the same name. > > Here is my ABCL code: > https://github.com/eatonphil/jvm-lisp-examples/blob/main/abcl/main.lisp#L= 22 > . > > In this code I define two methods of the same name. The "fake" method > comes first. This is found when the jooby library does reflection! But it > is not the one called by Jooby. The second method that returns an Object > (the one that actually implements the interface) is the one that is calle= d. > > Separately, I was messing around in Kawa trying to understand where this > $X suffix is generated on duplicate methods. I did find fixParamNames in > gnu/bytecode/Scope.java:110. It has a note saying that $X suffix was > required because of _Android_/dex. I commented this method out and > recompiled and ran my example but it still generated the $X suffix. So I > guess that's not the place where the method name is generated for bytecod= e > compilation. If anyone could point me at where that happens that would he= lp. > > Thanks! > > On Tue, Sep 7, 2021 at 6:59 AM spellcard199 > wrote: > >> Hello. >> >> > For what it's worth this kind of redefinition of the same method >> worked for me in ABCL lisp. So I know it's definitely possible to >> express in Java. >> >> I know nothing about ABCL so I trust you on the fact ABCL handles >> this differently from Kawa, but I don't think in Java you do it. >> >> If I try to write the following class in plain Java... >> >> public class Main { >> public static void main(String[] args) { >> Main main =3D new Main(); >> System.out.println(main.apply("x")); >> } >> public java.lang.CharSequence apply(String s) { >> return s.concat(s); >> } >> public java.lang.Object apply(String s) { >> return s.concat(s).concat(s); >> } >> } >> >> ... it gives a compile time error: >> >> apply(String) is already defined in 'Main' >> >> And the same thing happens when the methods are static. >> >> I suppose in plain Java you can't have more than one method with both >> the same: >> - name >> - input types >> >> I remember being confused by this the first time I saw it, but in >> hindsight it makes sense: if there were 2 methods with the same name >> and input types, how could Java know which one should be called when >> applied to arguments? >> >> So my question is: does ABCL really let you have both methods at the >> same time or just the lastly defined one? >> >> >> =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 Original= Message =E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90=E2=80=90 >> >> On Tuesday, August 31st, 2021 at 1:18 AM, Phil Eaton >> wrote: >> >> > I spoke too soon. The issue is that I truly do need both of these >> methods >> > >> > to be called `apply` not `apply` and `apply$1`. >> > >> > For what it's worth this kind of redefinition of the same method worke= d >> for >> > >> > me in ABCL lisp. So I know it's definitely possible to express in Java= . >> > >> > On Mon, Aug 30, 2021 at 7:09 PM Phil Eaton phil@eatonphil.com wrote: >> > >> > > Aha! It gave my second apply method a different suffix. By reorderin= g >> > > >> > > these two methods the whole thing somehow works. >> > > >> > > $ javap main\$0.class >> > > >> > > Compiled from "main.scm" >> > > >> > > public class main$0 implements io.jooby.Route$Handler { >> > > >> > > main$frame this$0; >> > > >> > > public java.lang.CharSequence apply(io.jooby.Context); >> > > >> > > public java.lang.Object apply$1(io.jooby.Context); >> > > >> > > public main$0(main$frame); >> > > >> > > } >> > > >> > > It's weird but I'll take it. >> > > >> > > On Mon, Aug 30, 2021 at 12:40 PM Per Bothner per@bothner.com wrote: >> > > >> > > > On 8/29/21 12:03 PM, Phil Eaton wrote:> Still new to Kawa. I'm >> trying to >> > > > >> > > > implement an interface ( >> > > > >> > > > > io.jooby.Route$Handler >> > > > > >> > > > > < >> > > > > >> > > > > >> https://github.com/jooby-project/jooby/blob/2.x/jooby/src/main/java/io/j= ooby/Route.java#L247 >> > > > > >> > > > > ). >> > > > > >> > > > > It only has a single non-default method, apply. >> > > > > >> > > > > Here's what I've got >> > > > > >> > > > > (define (route app method path handler) >> > > > > >> > > > > (let ((handler (object (io.jooby.Route$Handler) >> > > > > >> > > > > #| This method exists just to stop Jooby from >> > > > > >> > > > > trying to introspect Java code that doesn't exist because this >> isn't >> > > > > >> > > > > written in Java. |# >> > > > > >> > > > > ((apply (ctx ::io.jooby.Context)) ::string >> > > > > >> > > > > #!null) >> > > > > >> > > > > ((apply (ctx ::io.jooby.Context)) >> > > > > >> > > > > ::java.lang.Object >> > > > > >> > > > > (handler ctx))))) >> > > > > >> > > > > (app:route method path handler))) >> > > > > >> > > > > But when this gets exercised, I get: >> > > > > >> > > > > [worker-1-3] ERROR io.jooby.Jooby - GET /hello-world 500 Server >> Error >> > > > > >> > > > > java.lang.AbstractMethodError: Receiver class main$0 does not >> define or >> > > > > >> > > > > inherit an implementation of the resolved method 'abstract >> > > > > >> > > > > java.lang.Object >> > > > > >> > > > > apply(io.jooby.Context)' of interface io.jooby.Route$Handler. >> > > > >> > > > I don't see anything obviously wrong. One thing to try is instead >> of an >> > > > >> > > > anonymous class (with object) use a named class (with >> > > > >> > > > define-simple-class). >> > > > >> > > > The anonymous class is more convenient of course there is some ext= ra >> > > > >> > > > "magic" >> > > > >> > > > (such as invisible fields) that might complicate things. >> > > > >> > > > > Also on a tangent, I was excited about the lambda shorthand for >> single >> > > > > >> > > > > method objects. Like I said this interface only has a single >> non-default >> > > > > >> > > > > method: apply. But I tried just calling `(app:route method >> handler)` >> > > > > >> > > > > without wrapping it in the io.jooby.Route$Handler object but it >> still >> > > > > >> > > > > failed. I guess it couldn't figure out this one method. >> > > > >> > > > Kawa has to be able to figure out at compile time that a specific >> > > > >> > > > class/interface >> > > > >> > > > is required before it can convert the lambda to an object. (As far >> as I >> > > > >> > > > can >> > > > >> > > > remember, doing this conversion at run-time isn't implemented, and >> would >> > > > >> > > > be >> > > > >> > > > fairly complicated.) So you may need to add some more >> type-specifiers. >> > > > >> > > > I suggest using javap to look at the generated classes, to see wha= t >> is >> > > > >> > > > going on. >> > > > >> ------------------------------------------------------------------------= --------- >> > > > >> > > > --Per Bothner >> > > > >> > > > >> > > > per@bothner.com http://per.bothner.com/ >> >