[Pharo-users] a basic hash question
Hi, i guess i can subsume almost everything i know about hashes in one sentence: it is my understanding that two objects that are equal (obj1=obj2. -->true) have to have the same hash value (which is used for some collection types), whereas objects where obj1=obj2 returns false should have different hash values although it may happen that they have the same one. now here things don't turn out exactly like that: (1 to:4) = #(1 2 3 4). "true" (1 to:4)hash = #(1 2 3 4)hash. "false" well ok, actually these results make - pfffh, in a certain way - sense to me, but i wonder what arguments the people in the know would use to defend that result, if i would have another opinion? werner
Re: [Pharo-users] a basic hash question
Just a quick guess seeing the implementation hash for collections is about hash of its elements SequencableCollection>>hasEqualElements: otherCollection "Answer whether the receiver's size is the same as otherCollection's size, and each of the receiver's elements equal the corresponding element of otherCollection. This should probably replace the current definition of #= ." | size | (otherCollection isKindOf: SequenceableCollection) ifFalse: [^ false]. (size := self size) = otherCollection size ifFalse: [^ false]. 1 to: size do: [:index | (self at: index) = (otherCollection at: index) ifFalse: [^ false]]. ^ true Cheers, Cédrick > Le 30 juil. 2018 à 14:07, werner kassens a écrit : > > Hi, > i guess i can subsume almost everything i know about hashes in one sentence: > it is my understanding that two objects that are equal (obj1=obj2. > -->true) have to have the same hash value (which is used for some > collection types), whereas objects where obj1=obj2 returns false should > have different hash values although it may happen that they have the > same one. > > now here things don't turn out exactly like that: > (1 to:4) = #(1 2 3 4). "true" > (1 to:4)hash = #(1 2 3 4)hash. "false" > well ok, actually these results make - pfffh, in a certain way - sense > to me, but i wonder what arguments the people in the know would use to > defend that result, if i would have another opinion? > werner > >
Re: [Pharo-users] a basic hash question
But it raises the question if : (1 to:4)hash = #(1 2 3 4)hash should return true instead ?? Cedrick > Le 30 juil. 2018 à 14:51, Cédrick Béler a écrit : > > Just a quick guess seeing the implementation > > hash for collections is about hash of its elements > > SequencableCollection>>hasEqualElements: otherCollection > "Answer whether the receiver's size is the same as otherCollection's > size, and each of the receiver's elements equal the corresponding > element of otherCollection. > This should probably replace the current definition of #= ." > > | size | > (otherCollection isKindOf: SequenceableCollection) ifFalse: [^ false]. > (size := self size) = otherCollection size ifFalse: [^ false]. > 1 to: size do: > [:index | > (self at: index) = (otherCollection at: index) ifFalse: [^ > false]]. > ^ true > > Cheers, > > Cédrick > >> Le 30 juil. 2018 à 14:07, werner kassens a écrit : >> >> Hi, >> i guess i can subsume almost everything i know about hashes in one sentence: >> it is my understanding that two objects that are equal (obj1=obj2. >> -->true) have to have the same hash value (which is used for some >> collection types), whereas objects where obj1=obj2 returns false should >> have different hash values although it may happen that they have the >> same one. >> >> now here things don't turn out exactly like that: >> (1 to:4) = #(1 2 3 4). "true" >> (1 to:4)hash = #(1 2 3 4)hash. "false" >> well ok, actually these results make - pfffh, in a certain way - sense >> to me, but i wonder what arguments the people in the know would use to >> defend that result, if i would have another opinion? >> werner >> >> >
Re: [Pharo-users] a basic hash question
Werner, I would say that you are right, this is a problem. A (not un-common) source of subtle bugs in Smalltalk is missing this rule that equivalent objects must have the same hash. In GemStone the objects are not equivalent (I’m not arguing that this is right, just that it avoids the problem you identify). I wonder what would happen if the hash comparison were added to the equivalence operator (#’=‘)! James > On Jul 30, 2018, at 5:07 AM, werner kassens wrote: > > Hi, > i guess i can subsume almost everything i know about hashes in one sentence: > it is my understanding that two objects that are equal (obj1=obj2. > -->true) have to have the same hash value (which is used for some > collection types), whereas objects where obj1=obj2 returns false should > have different hash values although it may happen that they have the > same one. > > now here things don't turn out exactly like that: > (1 to:4) = #(1 2 3 4). "true" > (1 to:4)hash = #(1 2 3 4)hash. "false" > well ok, actually these results make - pfffh, in a certain way - sense > to me, but i wonder what arguments the people in the know would use to > defend that result, if i would have another opinion? > werner > > >
[Pharo-users] transactions on pharo objects
Hi, is there some library or approach how to do transactions in pharo? And I don't mean database transactions, but directly in memory on Pharo objects... e.g. p := Person new. transaction do: [ p name: 'Nobody'. p age: 70. ] on: Error do: [ transaction rollback. ]. self assert: p name equals: 'Nobody'. self assert: p age equals: 70. transaction do: [ p name: 'Somebody'. p age: 1 / 0. ] on: Error do: [ transaction rollback. ]. self assert: p name equals: 'Nobody'. self assert: p age equals: 70. Any pointers appreciated. Thanks, Peter
Re: [Pharo-users] transactions on pharo objects
I think it is a tricky thing to do "in memory transactions", even without thinking about databases. You have to define what to keep and where to place the "original" values (inst. vars.) of the object. As a general purpose solution if you can do that, you end up implementing a mini gemstone in Pharo :) But what's sure is that you should have a mini object-table of the "touched" objects or do "explicit" registration of these objects like GLORP allows you to do. e.g. | p | p := Person new. System transaction: [:tx | tx register: p. p name: 'Nobody'. p age: 70. ]. self assert: p name equals: 'Nobody'. self assert: p age equals: 70. I'm using System here, to make it compatible with GemStone. #transaction: could be implemented in terms of #beginTransaction, #commitTransaction and internally use #abortTransaction if an unhandled Error is signalled. Regards! Esteban A. Maringolo El lun., 30 jul. 2018 a las 10:17, Peter Uhnák () escribió: > > Hi, > > is there some library or approach how to do transactions in pharo? > And I don't mean database transactions, but directly in memory on Pharo > objects... e.g. > > p := Person new. > > transaction do: [ > p name: 'Nobody'. > p age: 70. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > transaction do: [ > p name: 'Somebody'. > p age: 1 / 0. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > Any pointers appreciated. > > Thanks, > Peter
Re: [Pharo-users] transactions on pharo objects
Maybe you can have a look to this paper : https://www.sciencedirect.com/science/article/pii/S1477842408000237 On Mon, Jul 30, 2018 at 2:17 PM Peter Uhnák wrote: > Hi, > > is there some library or approach how to do transactions in pharo? > And I don't mean database transactions, but directly in memory on Pharo > objects... e.g. > > p := Person new. > > transaction do: [ > p name: 'Nobody'. > p age: 70. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > transaction do: [ > p name: 'Somebody'. > p age: 1 / 0. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > Any pointers appreciated. > > Thanks, > Peter > -- Serge Stinckwich UMI UMMISCO 209 (SU/IRD/UY1) "Programs must be written for people to read, and only incidentally for machines to execute."http://www.doesnotunderstand.org/
Re: [Pharo-users] transactions on pharo objects
Peter Uhnák wrote > is there some library or approach how to do transactions… directly in > memory on Pharo > objects Magritte? It uses the Memento pattern to verify all changes before committing to real object. - Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Re: [Pharo-users] transactions on pharo objects
El lun., 30 jul. 2018 a las 11:03, Sean P. DeNigris () escribió: > > Peter Uhnák wrote > > is there some library or approach how to do transactions… directly in > > memory on Pharo > > objects > > Magritte? It uses the Memento pattern to verify all changes before > committing to real object. But you need Magritte, and define descriptions, and references, and access the objects via Magritte Accessors, etc. I think that works for an UI of a somehow limited form, but not as a general purpose (as I guess Peter is looking for). Also for forms, but without metadata, Dolphin used a "BufferedModel" object, which means that if you have an MVP/MVC, instead of using your original model, you work on this "buffer", which internally has the original and a copy, and all messages are sent to the copy and once you "apply" the changes they are applied back to the original model, and if you don't apply, the copy is discarded and the original model left unmodified. But again, I guess Peter is looking for something else. Regards!
Re: [Pharo-users] a basic hash question
jgfoster wrote > Werner, > > I would say that you are right, this is a problem. A (not un-common) > source of subtle bugs in Smalltalk is missing this rule that equivalent > objects must have the same hash. In GemStone the objects are not > equivalent (I’m not arguing that this is right, just that it avoids the > problem you identify). > > I wonder what would happen if the hash comparison were added to the > equivalence operator (#’=‘)! > > James > >> On Jul 30, 2018, at 5:07 AM, werner kassens < > wkassens@ > > wrote: >> >> Hi, >> i guess i can subsume almost everything i know about hashes in one >> sentence: >> it is my understanding that two objects that are equal (obj1=obj2. >> -->true) have to have the same hash value (which is used for some >> collection types), whereas objects where obj1=obj2 returns false should >> have different hash values although it may happen that they have the >> same one. >> >> now here things don't turn out exactly like that: >> (1 to:4) = #(1 2 3 4). "true" >> (1 to:4)hash = #(1 2 3 4)hash. "false" >> well ok, actually these results make - pfffh, in a certain way - sense >> to me, but i wonder what arguments the people in the know would use to >> defend that result, if i would have another opinion? >> werner >> >> >> +1, this is a bug. Either Interval >> #hash needs to change*, or the equivalency be broken**. Fun fact: #(1 2 3 4) = #[1 2 3 4] false You'd think they might be more similar than an Interval and an Array, or a LinkedList containing ValueLinks and an Interval, but no ;) Cheers, Henry *Interval >> hash "Hash is reimplemented because = is implemented. Since we are equivalent to other collections of our species, we must also hash equivalently" | hash | hash := self species hash. start to: stop by: step do: [:element | hash := (hash + element hash) hashMultiply]. ^hash **both ways, which is challenging, if one neither wants to: - change species of Interval (which has bad consequences) - add hash comparison to sequenceablecollection = (which slows it down even further) -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Re: [Pharo-users] a basic hash question
Hi, thank you all for your answers. Cédrick Béler wrote: > But it raises the question if : > (1 to:4)hash = #(1 2 3 4)hash should return true instead ?? principally yes, but it would slow down the Interval>>hash implementation considerably. id guess one would first make SequentialCollection>>hash a bit faster & shorter or one could very fast get a memory overflow. i mean the trick with Intervals is not so much (1to:4), but (-1000 to: 1000) which doesnt use any space and time. jgfoster wrote: > In GemStone the objects are not > equivalent (I’m not arguing that this is right, just that it avoids the > problem you identify). i see, yes, it can happen that hash has its own idea what equivalence _really means. > I wonder what would happen if the hash comparison were added to the > equivalence operator (#’=‘)! you probably mean something like this: #= ^(doWhatYouveDoneBefore)and:[self hash = object hash] of course that would eliminate the problem but it would need to be implemented everywhere. if not, #= could become not symmetric which produces the same problems (actually i stumbled upon this question because i implemented #= for a subobject of Array and gave it the species Array, problematic because with my implementation it opened the possibility of myObject~=anArray but anArray=myObject). actually #= in pharo is symmetric (and transitive, which also is necessary for hash to work) because it is more or less carefully designed , the symmetry is not somehow automatically incorporated in the language, and as i noticed its not too difficult to break that symmetry with ones own objects On 07/30/2018 05:27 PM, Henrik Sperre Johansen wrote: > +1, this is a bug. > Either Interval >> #hash needs to change*, or the equivalency be broken**. > > Fun fact: > #(1 2 3 4) = #[1 2 3 4] false > You'd think they might be more similar than an Interval and an Array, or a > LinkedList containing ValueLinks and an Interval, but no ;) i guess it is difficult to juggle & balance everything between all the different kinds of collections. thanks again folks werner
Re: [Pharo-users] a basic hash question
The interval 1 to: (10 raisedTo: 100) can be created just fine, yet hashing its elements won't compute. A generous interpretation of the intent of #=, where any wisp of equivalence is promoted to full fledged equality, is problematic in the long run. Here's another one: 17/20 = 0.85, therefore (17/20) hash = 0.85 hash Never mind there's no floating point value that is equal to 17/20 in the first place. It just snowballs from there. For instance, should collections like these be equal? (0.0 to: 1.0 by: 0.3) = #(0.0 0.3 0.6 0.9) Sometimes it's just better if different things stay different. Andres. On 7/30/18 8:27 , Henrik Sperre Johansen wrote: jgfoster wrote Werner, I would say that you are right, this is a problem. A (not un-common) source of subtle bugs in Smalltalk is missing this rule that equivalent objects must have the same hash. In GemStone the objects are not equivalent (I’m not arguing that this is right, just that it avoids the problem you identify). I wonder what would happen if the hash comparison were added to the equivalence operator (#’=‘)! James On Jul 30, 2018, at 5:07 AM, werner kassens < wkassens@ > wrote: Hi, i guess i can subsume almost everything i know about hashes in one sentence: it is my understanding that two objects that are equal (obj1=obj2. -->true) have to have the same hash value (which is used for some collection types), whereas objects where obj1=obj2 returns false should have different hash values although it may happen that they have the same one. now here things don't turn out exactly like that: (1 to:4) = #(1 2 3 4). "true" (1 to:4)hash = #(1 2 3 4)hash. "false" well ok, actually these results make - pfffh, in a certain way - sense to me, but i wonder what arguments the people in the know would use to defend that result, if i would have another opinion? werner +1, this is a bug. Either Interval >> #hash needs to change*, or the equivalency be broken**. Fun fact: #(1 2 3 4) = #[1 2 3 4] false You'd think they might be more similar than an Interval and an Array, or a LinkedList containing ValueLinks and an Interval, but no ;) Cheers, Henry *Interval >> hash "Hash is reimplemented because = is implemented. Since we are equivalent to other collections of our species, we must also hash equivalently" | hash | hash := self species hash. start to: stop by: step do: [:element | hash := (hash + element hash) hashMultiply]. ^hash **both ways, which is challenging, if one neither wants to: - change species of Interval (which has bad consequences) - add hash comparison to sequenceablecollection = (which slows it down even further) -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html .
Re: [Pharo-users] transactions on pharo objects
Basically, what you are talking about is Software Transactional Memory. According to https://en.wikipedia.org/wiki/Software_transactional_memory#Smalltalk there *is* STM support for Pharo at http://source.lukas-renggli.ch/transactional/ although the last version there is from 2012, and there have been major changes to Pharo since then, so it probably doesn't work any longer. You could probably make a TransactionalObject class with a 'lastTransaction' instance variable, and a noteChange method that checks if lastTransaction == Transaction current, and if not, pushes self -> self shallowCopy onto a stack inside Transaction and sets lastTransaction to Transaction current. Then to roll back a transaction, peel back original -> backup records from the stack and do original copyFrom: backup for each of them. Please don't ask me to think about combining this with concurrency. On 31 July 2018 at 01:16, Peter Uhnák wrote: > Hi, > > is there some library or approach how to do transactions in pharo? > And I don't mean database transactions, but directly in memory on Pharo > objects... e.g. > > p := Person new. > > transaction do: [ > p name: 'Nobody'. > p age: 70. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > transaction do: [ > p name: 'Somebody'. > p age: 1 / 0. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > Any pointers appreciated. > > Thanks, > Peter >
Re: [Pharo-users] a basic hash question
Hi Andres, that is the kind of argument i was looking for, as i thought i would have a similar situation as in my small example and wondered whether i could keep my slightly incongruent definition of #= and #hash, but in a way your examples show that my problem is different, iow i should change my implementation & i have changed it. werner On 07/31/2018 12:34 AM, Andres Valloud wrote: > The interval > > 1 to: (10 raisedTo: 100) > > can be created just fine, yet hashing its elements won't compute. > > A generous interpretation of the intent of #=, where any wisp of > equivalence is promoted to full fledged equality, is problematic in > the long run. Here's another one: > > 17/20 = 0.85, therefore (17/20) hash = 0.85 hash > > Never mind there's no floating point value that is equal to 17/20 in > the first place. It just snowballs from there. For instance, should > collections like these be equal? > > (0.0 to: 1.0 by: 0.3) = #(0.0 0.3 0.6 0.9) > > Sometimes it's just better if different things stay different. > > Andres.
Re: [Pharo-users] a basic hash question
I do not think that (1 to: 4) and #(1 2 3 4) should be equal. Let me put it a little more strongly: it's a bug. Taking a := 1 to: 4. b := Array withAll: a. c := OrderedCollection withAll: b. in the two other Smalltalk systems I just tried, no two of these are equal. This is what the ANSI Smalltalk standard requires. Ceteris paribus, two sequences are equivalent if and only if 1. they are instance of the same class 2. they have the same size 3. corresponding elements are equivalent. It is fairly common for Smalltalk systems to distinguish between "these sequences are equivalent" and "these sequences have the same elements in the same order", with no consensus on the name of the second method. One calls it #sameContentsAs:, Squeak #hasEqualElements:. On 31 July 2018 at 00:07, werner kassens wrote: > Hi, > i guess i can subsume almost everything i know about hashes in one > sentence: > it is my understanding that two objects that are equal (obj1=obj2. > -->true) have to have the same hash value (which is used for some > collection types), whereas objects where obj1=obj2 returns false should > have different hash values although it may happen that they have the > same one. > > now here things don't turn out exactly like that: > (1 to:4) = #(1 2 3 4). "true" > (1 to:4)hash = #(1 2 3 4)hash. "false" > well ok, actually these results make - pfffh, in a certain way - sense > to me, but i wonder what arguments the people in the know would use to > defend that result, if i would have another opinion? > werner > > >
Re: [Pharo-users] a basic hash question
+1 to what Andreas Valloud (Mr "how to hash in Smalltalk") said. On 31 July 2018 at 10:34, Andres Valloud wrote: > The interval > > 1 to: (10 raisedTo: 100) > > can be created just fine, yet hashing its elements won't compute. > > A generous interpretation of the intent of #=, where any wisp of > equivalence is promoted to full fledged equality, is problematic in the > long run. Here's another one: > > 17/20 = 0.85, therefore (17/20) hash = 0.85 hash > > Never mind there's no floating point value that is equal to 17/20 in the > first place. It just snowballs from there. For instance, should > collections like these be equal? > > (0.0 to: 1.0 by: 0.3) = #(0.0 0.3 0.6 0.9) > > Sometimes it's just better if different things stay different. > > Andres. > > > On 7/30/18 8:27 , Henrik Sperre Johansen wrote: > >> jgfoster wrote >> >>> Werner, >>> >>> I would say that you are right, this is a problem. A (not un-common) >>> source of subtle bugs in Smalltalk is missing this rule that equivalent >>> objects must have the same hash. In GemStone the objects are not >>> equivalent (I’m not arguing that this is right, just that it avoids the >>> problem you identify). >>> >>> I wonder what would happen if the hash comparison were added to the >>> equivalence operator (#’=‘)! >>> >>> James >>> >>> On Jul 30, 2018, at 5:07 AM, werner kassens < >>> >> wkassens@ >>> >> >> > wrote: >>> Hi, i guess i can subsume almost everything i know about hashes in one sentence: it is my understanding that two objects that are equal (obj1=obj2. -->true) have to have the same hash value (which is used for some collection types), whereas objects where obj1=obj2 returns false should have different hash values although it may happen that they have the same one. now here things don't turn out exactly like that: (1 to:4) = #(1 2 3 4). "true" (1 to:4)hash = #(1 2 3 4)hash. "false" well ok, actually these results make - pfffh, in a certain way - sense to me, but i wonder what arguments the people in the know would use to defend that result, if i would have another opinion? werner >> +1, this is a bug. >> Either Interval >> #hash needs to change*, or the equivalency be broken**. >> >> Fun fact: >> #(1 2 3 4) = #[1 2 3 4] false >> You'd think they might be more similar than an Interval and an Array, or a >> LinkedList containing ValueLinks and an Interval, but no ;) >> >> Cheers, >> Henry >> >> *Interval >> hash >> "Hash is reimplemented because = is implemented. >> Since we are equivalent to other collections of our species, we >> must also >> hash equivalently" >> | hash | >> >> hash := self species hash. >> start to: stop by: step do: [:element | hash := (hash + element >> hash) >> hashMultiply]. >> ^hash >> >> **both ways, which is challenging, if one neither wants to: >> - change species of Interval (which has bad consequences) >> - add hash comparison to sequenceablecollection = (which slows it down >> even >> further) >> >> >> >> >> -- >> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html >> >> . >> >> >
Re: [Pharo-users] transactions on pharo objects
> Am 30.07.2018 um 15:16 schrieb Peter Uhnák : > > Hi, > > is there some library or approach how to do transactions in pharo? > And I don't mean database transactions, but directly in memory on Pharo > objects... e.g. > > p := Person new. > > transaction do: [ > p name: 'Nobody'. > p age: 70. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > transaction do: [ > p name: 'Somebody'. > p age: 1 / 0. > ] on: Error do: [ > transaction rollback. > ]. > > self assert: p name equals: 'Nobody'. > self assert: p age equals: 70. > > Any pointers appreciated. > Should this work image wide or per process? Norbert
Re: [Pharo-users] transactions on pharo objects
> Am 30.07.2018 um 16:02 schrieb Sean P. DeNigris : > > Peter Uhnák wrote >> is there some library or approach how to do transactions… directly in >> memory on Pharo >> objects > > Magritte? It uses the Memento pattern to verify all changes before > committing to real object. > This only works for simple use cases where there is one flow that creates the memento and keeps it like in a web form. The problem with the memento is that it is hard to make all objects give a memento when they are aquired. Norbert > > - > Cheers, > Sean > -- > Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html >
Re: [Pharo-users] transactions on pharo objects
> Am 31.07.2018 um 06:57 schrieb Richard O'Keefe : > > Basically, what you are talking about is Software Transactional Memory. > According to > https://en.wikipedia.org/wiki/Software_transactional_memory#Smalltalk > there *is* STM support for Pharo at > http://source.lukas-renggli.ch/transactional/ > although the last version there is from 2012, and there have been major > changes to Pharo > since then, so it probably doesn't work any longer. > > You could probably make a TransactionalObject class with a 'lastTransaction' > instance variable, and a noteChange method that checks if lastTransaction == > Transaction current, and if not, pushes self -> self shallowCopy onto a stack > inside Transaction and sets lastTransaction to Transaction current. Then to > roll back a transaction, peel back original -> backup records from the stack > and do original copyFrom: backup for each of them. > > Please don't ask me to think about combining this with concurrency. > You could delegate the transaction list and other objects to a process specific variable. But the biggest problem with a copy approach is that all identity checks fail with the copied objects Norbert >> On 31 July 2018 at 01:16, Peter Uhnák wrote: >> Hi, >> >> is there some library or approach how to do transactions in pharo? >> And I don't mean database transactions, but directly in memory on Pharo >> objects... e.g. >> >> p := Person new. >> >> transaction do: [ >> p name: 'Nobody'. >> p age: 70. >> ] on: Error do: [ >> transaction rollback. >> ]. >> >> self assert: p name equals: 'Nobody'. >> self assert: p age equals: 70. >> >> transaction do: [ >> p name: 'Somebody'. >> p age: 1 / 0. >> ] on: Error do: [ >> transaction rollback. >> ]. >> >> self assert: p name equals: 'Nobody'. >> self assert: p age equals: 70. >> >> Any pointers appreciated. >> >> Thanks, >> Peter >