Allow reified classes to store instance variables in raw fields#7012
Allow reified classes to store instance variables in raw fields#7012headius merged 1 commit intojruby:jruby-9.3from
Conversation
|
A couple general comments...
Nicely done reusing the plumbing for FieldVariableAccessor! I can give this a run through JVM assembly dumping to confirm it is inlining the access to the field directly. |
|
Some thoughts from chat: java_field, "java.lang.String => testfield", variable: :@testfield |
|
My current configuration thought is |
does it make sense to |
A similar question to @kares: why would you declare the variable as |
I've updated it to be:
I've also added some more tests for concrete vs ruby and unwrap vs no unwrap As part of the concrete testing I had to expand the methodhandle stuff much more, but I think I'm ready for review now |
|
A few general comments/questions as I start reviewing...
So this is like current behavior on a Java proxy type, where the field will be presented as a
Something about this naming doesn't work for me. If we want to be explicit about it being an instance variable, why not "instance_variable" instead of "bind_variable"? This keyword is really about adjusting the behavior of the instance variable accesses, right? If this is a more general purpose |
Correct, and those methods are always present (the configuration doesn't change that) |
headius
left a comment
There was a problem hiding this comment.
Approved but we should chat through my very minor naming/encapsulation concerns.
core/src/main/java/org/jruby/javasupport/util/JavaClassConfiguration.java
Outdated
Show resolved
Hide resolved
I think we should get the naming right on the first go, so here is my reasoning:
A few I thought of:
|
|
I am leaning toward I'm also having a bit of trouble with the nested hash for the instance variable options. It makes sense semantically but it feels cumbersome. Using your examples:
Those two forms feel pretty good. With the additional options, it feels cleaner to just have them as additional keywords. "to_java" is pretty good, but "convert" might be more obvious? One problem with "to_java" to me is that it's really bi-directional, so it's both "to_java" and "to_ruby" depending on whether you set or get.
|
|
I do like the parity with Because this is rather advanced usage and does weird things to semantics, I'd definitely like something a) easily understandable without googling in case a someone runs into it and hasn't seen this form before, and b) easily googleable. Due to the infrequency of use by end users expected, I think we should optimize understanding for the novice reader over the expert writer here. That's one reason (in addition to those listed above) why I have preferred "verb-y" names thus far. Taking this into account, I definitely would prefer something like I notice you are preferring verbless names so far, what's the reasoning behind that preference? As for the other options, |
|
I think adding a verb will become harder to remember than the word 'instance_variable'. java_field is a declarative set of statements about the field. One adjective here is it is also an instance_variable (or so it will appear so). I cannot think of a better name that convert. I would like to see a concrete example of why convert needs to be anything other than true or false. I believe there is one but it would be nice to see a good example (all I am coming up with is field is a base type yet we decide to say it is a specific type with convert). We need this example if for no other reason then we need to document the feature. |
The need for a specific type comes from toJava requiring an argument, and me not knowing any better way to say "make this a java thing, whatever it is". Under the hood, convert is only used as self.my_field = value.to_java(convert_argument_here) Examples: java_field "java.lang.Object myfield", ..., convert: false # default for object, stores the IRubyObject in myfield
java_field "my.Class myfield", ..., convert: my.Class # default for non-Object, stores the raw java instance in myfield
java_field "java.lang.Object myfield", ..., convert: my.Class # stores the raw java instance in myfield
java_field "java.lang.Numeric myfield", ..., convert: j.l.Float # store a float in the number, not an integer, long, or shortWithout convert, any type of Object either a) won't be able to store a java instance or b) won't be able to store a ruby instance. by adding convert, it's configurable. Another important note: the A summary of when
I think that is all the reasons you would use As for the primary name, I'm not clear on which name you prefer? |
|
I guess I see this as three possible forms: No conversion (you are just passing around the natural Java type of the field: java_field "my.Address address", instance_variable: true, convert: falseConversion [default and can be omitted] (we are passing a Ruby type around which knows how to convert to the Java type [rubyToJava]): java_field "java.lang.String address", instance_variable: true, convert: trueConversion but we want to specify what type we want to convert too (this seems like it could only be useful for a Ruby type which can be multiple Java classes/interfaces): java_field "java.swing.JComponent component", instance_variable: true, convert: java.swing.JButtonThis last example is what I don't understand. It is also possible I am missing something in the original proposal. I largely just see a specified type to convert but I do not really understand why convert would ever be different than the type declaration. If they are different then I am wondering what the behavior is if the Java access of this same type puts the base type but it will not match our convert type. |
This is principally for making Java integration produce more idomatic Ruby. This allows users to configure a class to store specific ivars in a field of a reified class.
167f282 to
ebc6a6e
Compare
|
I have updated the syntax to "intance_variable:" and "to_java", as per the recent matrix chat. I have also squashed and rebased this to 9.3 as per the same matrix chat. (original commits on orig_field_ivar_storage on byteit101 fork) That's all I have. |
|
Merged! |
This is principally for making Java integration produce more idomatic Ruby. This allows users to configure a class to store specific ivars in a field of a reified class. This is principally for JRubyFX at this point in time, as that framwork sets java fields on a provided class.
Still a WIP. Notable things that need to be done:
@foo.equals?(@foo)being false for some types (ex: j.l.String)@foo=being frozen, butself.foo=notQuick working demo:
Now outputs: