-
Notifications
You must be signed in to change notification settings - Fork 50
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
More compact code for equals methods #99
Comments
The main constraint is that everything that is generated must be type-safe. Given that constraint there is two code reduction strategies we could implement:
class m1 extends C1 {
@Override
public boolean equals(Object other) {
return (other instanceof C1) && caseOf((C1) other).m1(p1 -> this.p1.equals(p1)).otherwise(false);
}
}
interface DefaultCases<R> extends Cases {
R defaultValue();
default R m1 (Integer p1) { retrun defaultValue(); }
default R m2 (Integer p1, String p2) { retrun defaultValue(); }
default R m3 (Integer p1, String p2, Object p3) { retrun defaultValue(); }
}
class DefaultCasesToFalse extends DefaultCases<Boolean> {
Boolean defaultValue() { return false; };
}
class m1 extends C1 {
@Override
public boolean equals(Object other) {
return (other instanceof C1) && ((C1) other).match(new DefaultCasesToFalse() {
@override
R m1 (Integer p1) { return C1.this.p1.equals(p1); }
});
}
} The second strategy is move involve (actually comes with a whole new feature: "default visitor") and only works with case class defined via a visitor interface (ie. not available when match method takes multiple function arguments). But its execution should be slightly more efficient. My feeling is that since |
Hi @jbgi! I just noticed I had a mistake in the final code snippet in my post above. I edited it to fix it. What I meant was to check if |
The issue is that all sound instances of C1 should be comparable, be it generated by derive4j or manually crafted. boolean testEqualsWithManuallyDefined() {
return C1s.m1(1).equals(new C1() {
public <R> R match (Cases<R> cases) { return cases.m1(1); };
public boolean equals(Object other) {
return (other instanceof C1) && caseOf((C1) other).m1(p1 -> p1.equals(1)).otherwise(false);
}
})
}; should return true. But if we use your proposed definition of |
Consider a class with a few cases, like this:
This causes derive4j to generate an equals method in every subclass M1, M2, M3. Each one looks like this:
More generally, for N cases, there will be N equals methods, each with N lines most of which are just mapping to
false
. When N gets moderately large, this generates a lot of code. For example, with N = 100, we get 10k lines of code just for these simple equals methods.How about generating more compact code, something like this for each equals:
That would cause the number of lines of code to scale linearly, rather than quadratically, since each equals just implements equals on its attributes.
The text was updated successfully, but these errors were encountered: