> De: "Steven Stewart-Gallus" <stevenselectronicm...@gmail.com>
> À: "mechanical-sympathy" <mechanical-sympathy@googlegroups.com>
> Envoyé: Samedi 27 Avril 2019 00:15:07
> Objet: Re: Exotic classes

> It seems to me you have to do a lot of hacky stuff to get around the "ugly" 
> API
> as you call it.

> Maybe it'd be better to separate out the ObjectSupport class into two separate
> classes, a HasherSupport class and an EqualsSupport class.

> interface HashSupport < T > {
> public static < T > HashSupport < T > of ( Lookup lookup , String ... fields 
> ) {
> var mh = createMh ( lookup , fields );
> return ( obj ) -> {
> mh . invokeExact ( obj );
> };
> }
> int hashCode ( T obj );
> }

> and similar for EqualsSupport.

One usual issue with people hand writing equals and hashCode is that they 
doesn't play well together because there are not using the same set of fields, 
grouping together the implementation of equals and hashCode alleviate this 
issue. 

> I feel like ObjectSupport is a bit nebulous and open ended and you'd 
> inevitably
> end up needing more support methods such as a toString method.

yes, toString and perhaps compare, but i want to get right equals and hashCode 
first. 

Rémi 

> On Friday, April 26, 2019 at 8:13:17 AM UTC-7, Remi Forax wrote:
>>> De: "Steven Stewart-Gallus" < [ javascript-blocked: | 
>>> stevensele...@gmail.com ]
>>> >
>>> À: "mechanical-sympathy" < [ javascript-blocked: | 
>>> mechanica...@googlegroups.com
>>> ] >
>>> Envoyé: Vendredi 26 Avril 2019 01:51:47
>>> Objet: Re: Exotic classes
>> Hi Steven,
>> thanks for spending some time on this,

>>> 1. Why
>>> public abstract class ObjectSupport {
>>> public abstract boolean equals ( Object self , Object other );
>>> public abstract int hashCode ();
>>> public static ObjectSupport of ( Lookup lookup , String ... fields ) {
>>> // impl details
>>> }
>>> // impl details
>>> }

>>> and not something like?
>>> interface ObjectSupport < T > {
>>> public boolean equals ( T self , T other );
>>> public int hashCode ( T obj );
>>> public static < T , U extends ObjectSupport < T >> T of ( Lookup lookup , 
>>> Class
>>> < U > iface , Class < T > obj ) {
>>> // impl details
>>> }
>>> }
>>> @Retention ( RetentionPolicy . RUNTIME )
>>> @Target ( ElementType . FIELD )
>>> @interface ObjectSupportField {
>>> }

>> There are three questions, why not use an interface, why not use generics to
>> make the API more typesafe and why not use an annotation to mark the fields,
>> (1), it should be an interface, yes :
>> (2), yes, the API can be more typesafe, i've implemented that. BTW, the 
>> correct
>> type of equals() if generified is (T, Object), because you can call
>> equals(Person, String), it should return false.
>> (3),the API you propose can be built on top of the existing one, that's why
>> there is an overload of ObjectSupport.of() that takes a function as third
>> parameter
>> see [
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
>> |
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
>> ]

>> so i've updated the code according to (1) and (2).

>>> 2. I don't understand why you can't use [
>>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
>>> |
>>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
>>> ] instead of unsafe. If you can use [
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
>>> |
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
>>> ] things might be easier to optimise because the VM doesn't trust nonstatic
>>> final fields but I don't think you'll need to rely on that.

>> I need a VM anonymous class otherwise the method handles used to implement
>> equals and hashCode are not considered as constant by the JIT. A previous
>> version of the API was using one lambdas for equals and one for hashCode,
>> but it makes the API ugly. see [
>> https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13
>> |
>> https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13
>> ]

>>> 3. The raw class file isn't always available at runtime so you can't 
>>> necessarily
>>> use ObjectSupportImpl as a template.

>> yes, i will inline it (storing it as an array of bytes inside the Java code)
>> once the API is stable enough.

>>> 4. [
>>> https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
>>> |
>>> https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
>>> ] Pretty sure you want a static final field here. You can do that if you're
>>> using ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't
>>> accept arguments so you have to use wonky garbage like a hashmap to pass
>>> runtime data that can't be embedded in a class file easily.

>> No need for static fields there because ObjectSupportImpl is loaded as a VM
>> anonymous class, so the instance fields are considered as constant if the
>> object itself is a constant (see the answer to your question 2).

>> There is a JMH test if you want to take a look to the generated assembly code
>> [
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java
>> |
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java
>> ]

>> regards,
>> Rémi

>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "mechanical-sympathy" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an 
>>> email
>>> to [ javascript-blocked: | mechanical-sympathy+unsubscr...@googlegroups.com 
>>> ] .
>>> For more options, visit [ https://groups.google.com/d/optout |
>>> https://groups.google.com/d/optout ] .

> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email
> to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com |
> mechanical-sympathy+unsubscr...@googlegroups.com ] .
> For more options, visit [ https://groups.google.com/d/optout |
> https://groups.google.com/d/optout ] .

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to