Hello!
Is there, in Pharo, builders for equals (=) and hash messages similar to: https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/builder/EqualsBuilder.html and Thanks in advance, Vitor |
Not that I know. Because it can be a little project. Now what is the key point to encapsulate this computation? On Mon, Oct 2, 2017 at 12:51 AM, Vitor Medina Cruz <[hidden email]> wrote:
|
in java, because this is a pain to do it each time.
for us, maybe for the same… even if is a lot easier. Esteban
|
In reply to this post by Vitor Medina Cruz
Hi. I just use RBGenerateEqualHashRefactoring for this:
But it is a bit different. 2017-10-02 0:51 GMT+02:00 Vitor Medina Cruz <[hidden email]>:
|
In reply to this post by EstebanLM
Hi, I wrote a generator for that. Probably it makes no sense to publish it as a standalone project. I tend to think code generation fits better in other languages. I can paste the relevant code here if needed. 2017-10-02 9:44 GMT+02:00 Esteban Lorenzano <[hidden email]>:
|
Publish it in a package and let us have a look. On Mon, Oct 2, 2017 at 9:53 AM, Jose San Leandro <[hidden email]> wrote:
|
in java, because this is a pain to do it each time. for us, maybe for the same… even if is a lot easier. Yeah, and it is boring to implement that every time, especially because it is tricky to get it right sometimes. Another interesting thing I use in Java to test my equals and hash implementation is the http://jqno.nl/equalsverifier/ I just use RBGenerateEqualHashRefactoring for this: Oh! That is nice, I will give a deeper look at it, I think this may do the job. Thanks! On Mon, Oct 2, 2017 at 10:09 AM, Stephane Ducasse <[hidden email]> wrote:
|
Administrator
|
In reply to this post by Denis Kudriashov
Denis Kudriashov wrote
> I just use RBGenerateEqualHashRefactoring for this: > > r := RBGenerateEqualHashRefactoring className: MyClass variables: #(vars > which should be used in equal and hash). > r execute That is sooooo cool! I shudder to think how many times I implemented just that by hand!! Two questions/comments about the generated code: 1. #= ... self class = anObject class "should compare #species instead?" ifFalse: [ ^ false ]. ... Typically, I've seen #species instead of #class in the guard statement. Should we change it to that? 2. #hash ^ var1 hash bitXor: (var2 hash bitXor: var3 hash) Is this implementation always safe? It's what I usually hand roll based on what I've seen, but Andres Valloud wrote a whole (large) book on hashing, so I've always wondered if I was missing something… ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Cheers,
Sean |
Administrator
|
In reply to this post by Denis Kudriashov
Denis Kudriashov wrote
> I just use RBGenerateEqualHashRefactoring for this: I added your answer to the Pharo wiki. Is this available through the UI? If not, maybe it should be! ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Cheers,
Sean |
In reply to this post by Sean P. DeNigris
Hi Sean. I did not know about quality of generated hash function. But if I remember correctly the same code is generated for java using Eclipse or Idea. So it should be good enough. Denis Kudriashov wrote |
In reply to this post by Sean P. DeNigris
2017-10-02 16:41 GMT+02:00 Sean P. DeNigris <[hidden email]>:
Denis Kudriashov wrote As I know it not exists |
I think it should have an option to generate with species (which I think should be the default). Also It would be nice if it could implement the solution for pitfall #4 described in http://www.artima.com/lejava/articles/equality.html On Mon, Oct 2, 2017 at 11:45 AM, Denis Kudriashov <[hidden email]> wrote:
|
In reply to this post by Sean P. DeNigris
2017-10-02 16:37 GMT+02:00 Sean P. DeNigris <[hidden email]>:
I doubt that it is important for domain classes. Because I never saw the user of #species which is not a kind of Collection. And for collections this refactoring is not valid anyway.
|
I am sorry, not species, but #isKindOf istead of #= to compare classes. On Mon, Oct 2, 2017 at 11:57 AM, Denis Kudriashov <[hidden email]> wrote:
|
2017-10-02 17:13 GMT+02:00 Vitor Medina Cruz <[hidden email]>:
It is bad idea. #= should be transitive. How you will generate it with isKindOf: logic? You need to know common parent. Also I not remember cases where I was needed two instances of different classes to be equal. And I can imaging the problems which it will lead to.
|
In reply to this post by Sean P. DeNigris
> On 2 Oct 2017, at 16:37 , Sean P. DeNigris <[hidden email]> wrote: > > 2. #hash > ^ var1 hash bitXor: (var2 hash bitXor: var3 hash) > Is this implementation always safe? It's what I usually hand roll based on > what I've seen, but Andres Valloud wrote a whole (large) book on hashing, so > I've always wondered if I was missing something… If you read Andres book (which is hard, because he won’t make it available online), you will learn that it’s better to take the order of the instance variables into account. #bitXor: is commutative, so it of course ignores order. In other words, if you have a Point with x and y fields, then 3@9 and 9@3 will have the same hash. For this reason, it’s better to multiply successive fields by a constant (e.g. shifting left by 2) before XORing them into the hash. But then, for objects with lots of fields, the later ones are lot completely, because they are multiplied by a number so large that they are out of the range of the hash. One can avoid this by using a circular shift to implement the multiply. All of this was, I thought, implemented in a #hashCombine: method, but I can’t find it in my image. Maybe some other Smalltalk ... |
Denis, That can be done with an canEqual implementation as described by http://www.artima.com/lejava/articles/equality.html.For this reason, it’s better to multiply successive fields by a constant (e.g. shifting left by 2) before XORing them into the hash. But then, for objects with lots of fields, the later ones are lot completely, because they are multiplied by a number so large that they are out of the range of the hash. I think this exactly what HasCodeBuidler does, however I saw no special treatment for hashes made of many fields.... On Mon, Oct 2, 2017 at 12:38 PM, Prof. Andrew P. Black <[hidden email]> wrote:
|
In reply to this post by Denis Kudriashov
2017-10-02 17:30 GMT+02:00 Denis Kudriashov <[hidden email]>:
Oh, I used wrong word, shame on me :). I tried to say commutative.
|
Yes, canEqual implementation also make #= be commutative. On Tue, Oct 3, 2017 at 11:11 AM, Denis Kudriashov <[hidden email]> wrote:
|
Noury also proposed a trait to avoid to systematically have to implement hash.
Vitor why don't you take it as a small project to propose a solution for Pharo. On Thu, Oct 5, 2017 at 6:34 PM, Vitor Medina Cruz <[hidden email]> wrote: > Yes, canEqual implementation also make #= be commutative. > > On Tue, Oct 3, 2017 at 11:11 AM, Denis Kudriashov <[hidden email]> > wrote: >> >> >> 2017-10-02 17:30 GMT+02:00 Denis Kudriashov <[hidden email]>: >>> >>> >>> 2017-10-02 17:13 GMT+02:00 Vitor Medina Cruz <[hidden email]>: >>>> >>>> I am sorry, not species, but #isKindOf istead of #= to compare classes. >>> >>> >>> It is bad idea. #= should be transitive. >> >> >> Oh, I used wrong word, shame on me :). I tried to say commutative. >> >>> >>> How you will generate it with isKindOf: logic? You need to know common >>> parent. >>> >>> Also I not remember cases where I was needed two instances of different >>> classes to be equal. >>> And I can imaging the problems which it will lead to. >>> >>>> >>>> >>>> On Mon, Oct 2, 2017 at 11:57 AM, Denis Kudriashov <[hidden email]> >>>> wrote: >>>>> >>>>> >>>>> 2017-10-02 16:37 GMT+02:00 Sean P. DeNigris <[hidden email]>: >>>>>> >>>>>> >>>>>> Two questions/comments about the generated code: >>>>>> 1. #= >>>>>> ... >>>>>> self class = anObject class "should compare #species instead?" >>>>>> ifFalse: [ ^ false ]. >>>>>> ... >>>>>> Typically, I've seen #species instead of #class in the guard >>>>>> statement. >>>>>> Should we change it to that? >>>>> >>>>> >>>>> I doubt that it is important for domain classes. Because I never saw >>>>> the user of #species which is not a kind of Collection. And for collections >>>>> this refactoring is not valid anyway. >>>>> >>>>>> >>>>>> >>>>>> >>>>>> 2. #hash >>>>>> ^ var1 hash bitXor: (var2 hash bitXor: var3 hash) >>>>>> Is this implementation always safe? It's what I usually hand roll >>>>>> based on >>>>>> what I've seen, but Andres Valloud wrote a whole (large) book on >>>>>> hashing, so >>>>>> I've always wondered if I was missing something… >>>>>> >>>>>> >>>>>> >>>>>> ----- >>>>>> Cheers, >>>>>> Sean >>>>>> -- >>>>>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html >>>>>> >>>>> >>>> >>> >> > |
Free forum by Nabble | Edit this page |