asArray method in Sets (please ignore previous draft if you receive it)

Jason Rogers jacaetevha at gmail.com
Mon Oct 17 13:51:50 UTC 2005


What about this:

========
Set>#asArray

^self class = Set
    ifTrue: [self alternativeAsArray]
    ifFalse: [super asArray]
========

You should also write a test (the following is just a sketch, there
are most likely other things to cover):

========
SetTest>testAsArray
    Set allSubclasses do: [:theClass |
        | instance |
        instance := theClass new.
        self stuff: (self itemsFor: theClass) into: instance.
        self assert: (self flattendItems = instance asArray).
    ]
========

On 10/17/05, Ralph Boland <rpboland at gmail.com> wrote:
> I use Sets (and its subclasses like Dictionary) a lot and desire that
> they be efficient. (I am currently using Squeak 3.6)
>
> I discovered that Set inherits the 'asArray' method from Collection
> which is written as follows:
>
> "
>        | anArray index |
>        anArray := Array new: self size.
>        index := 0.
>        self associationsDo: [:each | anArray at: (index := index + 1)
> put: each].
>        ^ anArray
> "
>
> Since Set does not have an 'associationsDo:' method  the corresponding
> method in Collection is used which just invokes the 'do:' method which
> is implemented in Set.
>
> I felt that this was too inefficient so I implemented 'asArray' in Set
> as follows:
>
> "
>                        | anArray newIndex |
>
>        anArray := Array new: self size.
>        newIndex := 1.
>        1 to: array size do:  [:index |
>                     | elem |
>              (elem := array at: index)   ifNotNil: [
>                    anArray at: newIndex put: elem.
>                    newIndex := newIndex + 1].
>              ].
>
>        ^ anArray
> "
>
> This causes 'asArray' in class Dictionary to fail because it now
> inherits the asArray method from Set instead of Collection
> so I copied verbatum the asArray method from Collection to Dictionary.
> So far everything appears to work.
> I have the following questions:
>
> 1)  For me the cost of the extra code was worth the gain in efficientcy
>     (I believe;  I didn't actually do any measurements).
>     Given the importance of Sets and its subclasses (like Dictionary) is this
>     modification not worth being in Squeak itself?
>     Note that I find there are many places in Squeak where I would have
>     reimplemented  a method rather then use inheritance so I am
>     probably at variance with the Squeak community.
>     Even so, the above case seems to me to be especially bad.
>     Comments?
>
>  2)  I was forced to reimplement the asArray method in Dictionary
>       even though I used the exact same code as in Dictionary's
>       super super class (Collection).
>      I could have avoided this by implementing a method
>      'skipSetAsArray' in Set  written:   "^super asArray"
>      and implemented 'asArray' in Dictionary as
>      "^self skipSetAsArray".  This is ugly but what I would have used
>       had 'asArray' been a method containing a lot of code.
>      Comments on this solution?
>
> 3)   An alternative to 2) would be if there was some way to control from which
>      class a method is inherited.  Say, for example we could write 'asArray' in
>      Dictionary as  "^super(Collection) asArray"  implying that
>      the version of 'asArray' in the super class of Dictionary
>      called Collection is to be used.
>      This seems to me to be a simple and efficient solution.
>      Comments?
>
> 4)  When I finally release my code, anybody who loads it will have my
>      implementations of 'asArray' in Set and Dictionary added to their
>      images.  If my code is not implemented properly it could break their
>      images and even if it is implemented properly it could still break their
>      images (if for example they created a subclass of Set which relies
>      on inheritance to invoke the version of 'asArray' in Collection.
>      i.e.  they could get burned the same way Dictionary was).
>      How am I expected to deal with these issues?
>         a) Undo my changes?
>         b) Work to have my changes made a permanent part of Squeak?
>         c) Document the possible effects of this change so the user
>             will be aware of it (if s(he) reads the documentation that is).
>         d) Let the users figure it out for themselves (probably faster than
>             reading the documentation especially since only a small portion
>             of users are likely to be affected).
>      Perhaps there thould be a standard special section in
>      documentation where this kind of change is noted.
>
> Thanks in advance for  any comments received.
>
> Ralph Boland
>
>


--
Jason Rogers

"I am crucified with Christ: nevertheless I live; yet not I,
but Christ liveth in me: and the life which I now live in
the flesh I live by the faith of the Son of God, who loved
me, and gave himself for me."
    Galatians 2:20



More information about the Squeak-dev mailing list