SequenceableCollection>>#allButFirst: inconsistence across subclasses
Hello, I opened that issue: https://github.com/pharo-project/pharo/issues/4442 <https://github.com/pharo-project/pharo/issues/4442> And I think to fix it we need to actually discuss about what we want. #allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size. For instance: #(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() » The question is then, who is right? Should #allButFirst: with an argument greater than the collection size raise an error Or Should #allButFirst: with an argument greater than the collection size returns an empty collection ? I asked a few people about it @ ESUG and it appears that the expected behaviour from #allButFirst: is not the same to all people. We need to decide so we improve consistence of collections. And then, we need to document that with a test :-). Cheers. Julien --- Julien Delplanque Doctorant à lâUniversité de Lille http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, Avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
On Fri, 30 Aug 2019 at 15:34, Julien <julien.delplanque@inria.fr> wrote:
Hello,
I opened that issue: https://github.com/pharo-project/pharo/issues/4442
And I think to fix it we need to actually discuss about what we want.
#allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size.
For instance:
#(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() »
The question is then, who is right?
Its worthwhile to at least survey other Smalltalks. For Visualworks... #(1 2) allButFirst: 3. "==> #()" (OrderedCollection with: 1 with: 2) allButFirst: 3. "==> OrderedCollection ()" (LinkedList with: Link new with: Link new ) allButFirst: 3. "raises an error Subscription out of bounds error" and also... (LinkedList with: Link new with: Link new ) allButFirst: 2. "raises an error Subscription out of bounds error" I feel that proceeding-without-iterating is nicer than showing-an-application-error. It provides the opportunity to not-check the number elements or wrapping error handling around it - i.e. less code if its not important. If its important not to exceed the number of elements, then that check can be explicitly coded. cheers -ben
over breakfast Santiago was suggesting that we have allButFirst:ifOutOfBounds: and he said that having an exception is important because you want to know if we get data data or not. And in that case the client will have to check all the time. Stef
On 30 Aug 2019, at 11:56, Ben Coman <btc@openinworld.com> wrote:
On Fri, 30 Aug 2019 at 15:34, Julien <julien.delplanque@inria.fr <mailto:julien.delplanque@inria.fr>> wrote: Hello,
I opened that issue: https://github.com/pharo-project/pharo/issues/4442 <https://github.com/pharo-project/pharo/issues/4442>
And I think to fix it we need to actually discuss about what we want.
#allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size.
For instance:
#(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() »
The question is then, who is right?
Its worthwhile to at least survey other Smalltalks. For Visualworks... #(1 2) allButFirst: 3. "==> #()" (OrderedCollection with: 1 with: 2) allButFirst: 3. "==> OrderedCollection ()" (LinkedList with: Link new with: Link new ) allButFirst: 3. "raises an error Subscription out of bounds error" and also... (LinkedList with: Link new with: Link new ) allButFirst: 2. "raises an error Subscription out of bounds error"
I feel that proceeding-without-iterating is nicer than showing-an-application-error. It provides the opportunity to not-check the number elements or wrapping error handling around it - i.e. less code if its not important. If its important not to exceed the number of elements, then that check can be explicitly coded.
cheers -ben
-------------------------------------------- Stéphane Ducasse http://stephane.ducasse.free.fr http://www.synectique.eu / http://www.pharo.org 03 59 35 87 52 Assistant: Julie Jonas FAX 03 59 57 78 50 TEL 03 59 35 86 16 S. Ducasse - Inria 40, avenue Halley, Parc Scientifique de la Haute Borne, Bât.A, Park Plaza Villeneuve d'Ascq 59650 France
Is this not the classic problem solved by design by contract (as in Eiffel)? Deciding who must check for errors (sender or receiver) and specifying it formally (the contract) is more important rather than who SHOULD check. I found http://forum.world.st/Run-time-checking-with-design-by-contract-assertions-t... that mentions a Pharo implementation of the principle. On Fri, 30 Aug 2019 at 07:19, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
over breakfast Santiago was suggesting that we have allButFirst:ifOutOfBounds:
and he said that having an exception is important because you want to know if we get data data or not. And in that case the client will have to check all the time.
Stef
On 30 Aug 2019, at 11:56, Ben Coman <btc@openinworld.com> wrote:
On Fri, 30 Aug 2019 at 15:34, Julien <julien.delplanque@inria.fr> wrote:
Hello,
I opened that issue: https://github.com/pharo-project/pharo/issues/4442
And I think to fix it we need to actually discuss about what we want.
#allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size.
For instance:
#(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() »
The question is then, who is right?
Its worthwhile to at least survey other Smalltalks. For Visualworks... #(1 2) allButFirst: 3. "==> #()" (OrderedCollection with: 1 with: 2) allButFirst: 3. "==> OrderedCollection ()" (LinkedList with: Link new with: Link new ) allButFirst: 3. "raises an error Subscription out of bounds error" and also... (LinkedList with: Link new with: Link new ) allButFirst: 2. "raises an error Subscription out of bounds error"
I feel that proceeding-without-iterating is nicer than showing-an-application-error. It provides the opportunity to not-check the number elements or wrapping error handling around it - i.e. less code if its not important. If its important not to exceed the number of elements, then that check can be explicitly coded.
cheers -ben
-------------------------------------------- Stéphane Ducasse http://stephane.ducasse.free.fr http://www.synectique.eu / http://www.pharo.org 03 59 35 87 52 Assistant: Julie Jonas FAX 03 59 57 78 50 TEL 03 59 35 86 16 S. Ducasse - Inria 40, avenue Halley, Parc Scientifique de la Haute Borne, Bât.A, Park Plaza Villeneuve d'Ascq 59650 France
-- Christopher Fuhrman, P.Eng., PhD *Professeur au Département de génie logiciel et des technologies de l'informationÃTS (Ãcole de technologie supérieure)* http://profs.etsmtl.ca/cfuhrman +1 514 396 8638 *L'ÃTS est une constituante de l'Université du Québec*
Personnally I sometimes want to break the contracts because I know that I don't need them and can optimize some performance-critical operations. A good example is Fraction. The invariants are: numerator isInteger and: [denominator isInteger and: [ denominator strictlyPositive and: [numerator isZero not and: [(numerator gcd: denominator) = 1]]]] Remark: we can see that there is an order in the invariants, we would not want to test (numerator gcd: denominator) = 1 before knowing they are integer... Normal usage is (Fraction numerator: n denominator: d) reduced, unless sender has the last two invariants in preconditions, in which case it can omit sending reduced. But when parsing Float, we write (Fraction numerator: n denominator: d) asFloat, even if the last invariant does not apply, because asFloat will perform some form of reduction either directly in floating point arithmetic, or via a quo: operation to keep only significand part, and because the last but one invariant is already in pre condition of sender. So a correct specification would be to apply the last two invariant to every Fraction method, but two exceptions: reduced (obviously) and asFloat. That would be a great way to specify the subtle arrangement. Also I was thinking that reduced could be entirely omitted when the contract is known to be fullfilled... That's a great deal of the optimizations that we are performing manually (like Fraction>>#squared etc...) but if a system could find that by induction (given the declarative pre/post contracts) it could probably find many more (I imagine when having type information like in Sista inlining phase). Le ven. 30 août 2019 à 15:18, Christopher Fuhrman < christopher.fuhrman@etsmtl.ca> a écrit :
Is this not the classic problem solved by design by contract (as in Eiffel)? Deciding who must check for errors (sender or receiver) and specifying it formally (the contract) is more important rather than who SHOULD check.
I found http://forum.world.st/Run-time-checking-with-design-by-contract-assertions-t... that mentions a Pharo implementation of the principle.
On Fri, 30 Aug 2019 at 07:19, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
over breakfast Santiago was suggesting that we have allButFirst:ifOutOfBounds:
and he said that having an exception is important because you want to know if we get data data or not. And in that case the client will have to check all the time.
Stef
On 30 Aug 2019, at 11:56, Ben Coman <btc@openinworld.com> wrote:
On Fri, 30 Aug 2019 at 15:34, Julien <julien.delplanque@inria.fr> wrote:
Hello,
I opened that issue: https://github.com/pharo-project/pharo/issues/4442
And I think to fix it we need to actually discuss about what we want.
#allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size.
For instance:
#(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() »
The question is then, who is right?
Its worthwhile to at least survey other Smalltalks. For Visualworks... #(1 2) allButFirst: 3. "==> #()" (OrderedCollection with: 1 with: 2) allButFirst: 3. "==> OrderedCollection ()" (LinkedList with: Link new with: Link new ) allButFirst: 3. "raises an error Subscription out of bounds error" and also... (LinkedList with: Link new with: Link new ) allButFirst: 2. "raises an error Subscription out of bounds error"
I feel that proceeding-without-iterating is nicer than showing-an-application-error. It provides the opportunity to not-check the number elements or wrapping error handling around it - i.e. less code if its not important. If its important not to exceed the number of elements, then that check can be explicitly coded.
cheers -ben
-------------------------------------------- Stéphane Ducasse http://stephane.ducasse.free.fr http://www.synectique.eu / http://www.pharo.org 03 59 35 87 52 Assistant: Julie Jonas FAX 03 59 57 78 50 TEL 03 59 35 86 16 S. Ducasse - Inria 40, avenue Halley, Parc Scientifique de la Haute Borne, Bât.A, Park Plaza Villeneuve d'Ascq 59650 France
-- Christopher Fuhrman, P.Eng., PhD
*Professeur au Département de génie logiciel et des technologies de l'informationÃTS (Ãcole de technologie supérieure)*
http://profs.etsmtl.ca/cfuhrman +1 514 396 8638 *L'ÃTS est une constituante de l'Université du Québec*
On Fri 30 Aug 2019 at 09:34, Julien <julien.delplanque@inria.fr> wrote:
Hello,
I opened that issue: https://github.com/pharo-project/pharo/issues/4442
And I think to fix it we need to actually discuss about what we want.
#allButFirst: behaves differently depending on the actual type of sequenceable collection when argument is greater than collection size.
For instance:
#(1 2) allButFirst: 3. "PrimitiveFailed signaled" (LinkedList with: 1 with: 2) allButFirst: 3. "PrimitiveFailed signaled" (OrderedCollection with: 1 with: 2) allButFirst: 3. "an OrderedCollection() »
The question is then, who is right?
Should #allButFirst: with an argument greater than the collection size raise an error
Or
Should #allButFirst: with an argument greater than the collection size returns an empty collection ?
I asked a few people about it @ ESUG and it appears that the expected behaviour from #allButFirst: is not the same to all people.
We need to decide so we improve consistence of collections.
And then, we need to document that with a test :-).
Hi, I was one of the person who discussed this with Julien at ESUG and IMO it should launch an error. While working on complexe models, errors in such cases are really really really helpful to find bugs. Errors such as SubscriptOutOfBound or NotFound help me a lot to find bugs and sometimes without this kind of methods it could have take me days to find the problem (and itâs only in the case I know there is a bug).
Cheers.
Julien
--- Julien Delplanque Doctorant à lâUniversité de Lille http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, Avenue Halley 59650 <https://www.google.com/maps/search/40,+Avenue+Halley+59650+Villeneuve+d'Ascq?entry=gmail&source=g> Villeneuve <https://www.google.com/maps/search/40,+Avenue+Halley+59650+Villeneuve+d'Ascq?entry=gmail&source=g> d'Ascq <https://www.google.com/maps/search/40,+Avenue+Halley+59650+Villeneuve+d'Ascq?entry=gmail&source=g> Numéro de téléphone: +333 59 35 86 40
-- Cyril Ferlicot https://ferlicot.fr
participants (6)
-
Ben Coman -
Christopher Fuhrman -
Cyril Ferlicot -
Julien -
Nicolas Cellier -
Stéphane Ducasse