-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java Integration conversions #3105
Comments
We have always wanted to eliminate these conversions, instead making java.lang.String and friends duck type to Ruby String (by defining equivalent versions of all String methods). The problem, however, is that changing this behavior globally would immediately break any code calling java.lang.String-based APIs if we don't coerce automatically. An alternative might be that we only coerce if we can't fit our RubyString object into the target type; so CharSequence, Object, Serializable argument types would go in as RubyString, but an argument type of java.lang.String would autocoerce. I worry this would be even more confusing, since it would only coerce sometimes. This is a tough question we've never found a suitable answer for. A high majority of users never notice that Ruby string and Java string are being converted automatically for them, because it makes the APIs work smoothly. But then you run into cases like this, where you have identity and information loss, and there's no good solution. |
We are planning an open-source rewrite of InfraRuby (a compiler and runtime for a statically-typed Ruby). This issue is one area we want to improve in the rewrite. The compiler presently applies those conversions (as InfraRuby is designed so InfraRuby code runs on Ruby interpreters without modification) except when compiling the runtime, because we can get away with that (we don't need the runtime to run on Ruby interpreters) and because those conversions would break a whole lot of stuff (for reasons given earlier). Unfortunately, outside the runtime, the compiler must apply conversions (because JRuby does) and, for example, we can't implement generic containers backed by As part of the rewrite, InfraRuby source files will use ".ir" as the file extension. JRuby could use file extensions and/or magic comments to select the behavior for Java Integration in each source file. A command-line option could enable warnings for conversions applied in source files using the default behavior. This approach would give JRuby developers a testing ground for alternative behaviors and a migration path if one alternative is preferred to the current behavior. |
@headius I'm closing this issue as another approach is possible, with a JRuby extension: the Thanks for JRuby; your work is excellent! |
@InfraRuby might be interested in seeing some of your work and maybe doing smt similar with a --flag (would be off by default) to get better JI as an experiment under JRuby. is there a public source repo? |
Another little bit of information... We have always had some concerns about doing this automatic translation, mostly on the Java-to-Ruby side of things, since often you really, really want the actual Java object. For Ruby-to-Java some of these conversions are necessary, like being able to pass a Ruby string for a Java string, but that's harder to avoid. One thought that @enebo and I had for years was to see how far we could get just making the Java types duck-type as the Ruby versions. So in that case, when you call a Java method and get back a java.lang.String, it's really, truly the actual Java string object, but we add on methods that Ruby code expects to see. If it walks like a String and quacks like a String... |
Also, I think we'd all agree that preserving identity on numeric objects is a very risky proposition, so JRuby passing Fixnum by converting to one of the primitive Java integer types is pretty benign. The conversions that have always bothered me are the Java-to-Ruby "normal" objects like Strings (and I guess String is really the primary one...we don't convert many other things). |
@kares now at https://github.com/InfraRuby/infraruby-java The extension also adds
Taking the examples in the issue, we now have no identity loss:
... no unwanted conversions:
... and no information loss:
|
@headius there are three options for Ruby-to-Java conversions:
InfraRuby takes the third option: |
@headius also this:
but, on the other hand:
|
Java Integration converts
java.lang.String
<->String
andjava.math.BigInteger
<->Integer
.These conversions violate Java and Ruby conventions for object identity:
These conversions break some methods:
These conversions lose information:
Would you consider a patch to disable these conversions on a per-source-file basis?
The text was updated successfully, but these errors were encountered: