[Cuis-dev] [Ann] Serialization of BlockClosures

Juan Vuletich juan at jvuletich.org
Wed Oct 2 17:14:52 PDT 2019


Additionally, in the Collection hierarchy, #species is used for #select: 
and #collect: as I said before. In the base image, all the classes that 
redefine #species are Collections. And they redefine it essentially to 
make #select: and #collect: answer a reasonable result, for example for

'Hello' collect: [ :a | a numericValue ].

(1 to: 20) select: [ :a | a isPrime ].

In those cases (the only ones where #species and #class differ in the 
base image), the objective is _not_ to recreate the receiver.

Speaking of "original intent", the comment at Object>>species (no 
timestamp, I guess that comes from Squeak 1.1, or maybe Smalltalk-80, 
definitely not written by me) talks about collections, and literally 
says "Species and class are not always the same. For example, the 
species of Interval is Array.". So it seems that #species tries to be 
too many different things at once...

On 10/2/2019 8:14 PM, Phil B wrote:
> I've been doing a bit of poking around the image and perhaps a more 
> succinct way of making the point is that in general, the pattern of 
> '<an object reference> class <an instance creation selector>' usually 
> works but is often incorrect.  For example, cases of:
>
> self class new
>
> are often incorrect and should generally, but not always[1], be:
>
> self species new
>
> I suspect the reason this isn't a problem for most people, most of the 
> time is that:
>
> 1) most of the time #species and #class return the same class
>
> 2) people are usually directly using instances of relatively 
> straightforward class hierarchies
>
> [1] While I'm sure there are cases, they would be the exception rather 
> than the rule.
>
>
> On Wed, Oct 2, 2019 at 4:13 PM Phil B <pbpublist at gmail.com 
> <mailto:pbpublist at gmail.com>> wrote:
>
>     Juan,
>
>     On Wed, Oct 2, 2019, 11:21 AM Juan Vuletich <juan at jvuletich.org
>     <mailto:juan at jvuletich.org>> wrote:
>
>         On 10/1/2019 2:39 AM, Phil B wrote:
>>         The first example I ran into was in Vector3>cross: (you can
>>         see an implementation of it here:
>>         https://github.com/pbella/Cuis-OpenGL/blob/master/3DTransform.pck.st#L2247)
>>         though pretty much any sender of #species (I have over 200 in
>>         my image) potentially applies: what you're returning changes
>>         the definition of #species and therefore may[3] break
>>         existing code.  What's most problematic about this change is
>>         that because it's relatively subtle, it may not be
>>         immediately obvious in all cases what the breakage is because
>>         existing code will kinda-sorta work: you'll get back a class
>>         which may mostly work right up until the point that it
>>         doesn't which might be pretty far from the sender of #species
>>         that resulted in the now problematic instance.
>         I took a look at your code, and it seems to assume that
>         #species is a synonym for #class. I'd rather call #class, but
>         that's not the main issue here.
>
>
>     No, this actually *is* one of the main issues.  The 'not a
>     collection' argument was about *what* you wanted to do.  The
>     #species argument was about *how* you were trying to do it.  So
>     even though the *what* went away, we still have the *how* which I
>     think is important we come to agreement on. (mainly for future
>     reference should anyone want to override #species)
>
>     As I understand it, #species is what one should send *instead* of
>     #class to find the 'correct' class to use when one wants to create
>     a new instance based on the type of an existing object.  Sure,
>     usually it will return the same thing as #class... but not
>     always.  The 'but not always' is key as they are similar, not the
>     same.  There are two main use cases off the top of my head where
>     this is critical: 1) proxy objects 2) polymorphic hierarchies.  In
>     both cases, #species and #class will often return different
>     classes with the difference being that #class returns the class
>     that the existing instance *is* and #species returns the class
>     that you should use (which may decide to instantiate a different,
>     usually sub-, class) to create a new instance.  Probably the more
>     common use case is not sending #species to self but rather to a
>     parameter passed in to a method but both scenarios seem equally
>     valid to me.
>
>     An extreme, but not pathological example is that you might have
>     someObject that you want to create a new instance of.  However,
>     someObject is a profiling proxy (class P) wrapped around a
>     debugging proxy (class D) wrapped around an instance of class
>     SomeSubtype which is a subclass of SomeType.  The proxy instances
>     P and D are runtime instrumentation and irrelevant to the object
>     that should be created and SomeSubtype is what was determined to
>     be the appropriate subclass to instantiate based on
>     conditions/parameters at its instantiation time which might be
>     different the next time an instance is created.  When I send
>     someObject #class it will return P but what I really need it to do
>     is send #species which should return SomeType.  That is my
>     understanding of what #species should do and why it's important.
>
>     So I would argue that the example I provided, while trivial, was
>     the more 'correct' way to use it.  The way most people write and
>     use Smalltalk code, it doesn't matter as #class will get you what
>     you need.  That's fine, but please don't mess with #species
>     because for some code the distinction is vital and you will break
>     code.
>
>
>         The changes I did to #species are not useful, because we need
>         a better solution that treats #select: (same class of
>         elements, possibly different number of them) and #collect:
>         (possibly different kind of elements, but same number of them)
>         in a distinct way.
>
>
>     The problem I had with your #species changes is that they were
>     *wrong* per the intent of the #species method.  If you had decided
>     'nah, I don't care... I want to treat a Color as a collection
>     anyway', I could live with that because I would not be forced to
>     use/treat it as one. (that said, I like that we're agreeing not to
>     do that.)  However, your #species change broke code by using a new
>     definition inconsistent with its original intent.
>
>
>         Besides, I made Color (the motivation for that change) no
>         longer be a Collection, as you, Nicolas and Hernán have
>         suggested, and just told in a separate email.
>
>         So, I removed ArrayedCollection>>#species.
>
>         Thanks for caring.
>
>         Cheers,
>
>         -- 
>         Juan Vuletich
>         www.cuis-smalltalk.org  <http://www.cuis-smalltalk.org>
>         https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
>         https://github.com/jvuletich
>         https://www.linkedin.com/in/juan-vuletich-75611b3
>         @JuanVuletich
>
>
>     Thanks,
>     Phil
>


-- 
Juan Vuletich
www.cuis-smalltalk.org
https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
https://github.com/jvuletich
https://www.linkedin.com/in/juan-vuletich-75611b3
@JuanVuletich

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20191002/c12c6b1f/attachment-0001.htm>


More information about the Cuis-dev mailing list