USe of isKindOf: is a crime against humanity

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

USe of isKindOf: is a crime against humanity

timrowledge
There are 623 senders of isKindOf: in the 4.5 image I'm using right now - which may be more than the general because I have some extra stuff loaded - and I'd bet that there are no more than a dozen places where it is actually a sensible way of doing what is needed.

It's slow - it scans up a class tree.
It's ugly.
It isn't actually testing what a lot of people seem to think - if you want to find out is some object can handle a certain capability try actually asking with something like  #isAGraphicThing rather than (isKindOf: Morph) or:[ foo isKindOf: DisplayObject] blahblahblah.

We can do better.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Paralyzed from the neck up.



Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Casey Ransberger-2
Totally. Also, one might argue that switching on type isn't terribly object-oriented. Or rather, it sort of re-implements dispatch. Sometimes it's hard to avoid, but some hard things are worth doing. Of course I'm a big fat hypocrite once in a long while (DNU hacks, #isKindOf:, etc.)

#respondsTo: is nicer in some spots. Protocol isn't class. Etc.

+1


On Sat, Aug 31, 2013 at 7:39 PM, tim Rowledge <[hidden email]> wrote:
There are 623 senders of isKindOf: in the 4.5 image I'm using right now - which may be more than the general because I have some extra stuff loaded - and I'd bet that there are no more than a dozen places where it is actually a sensible way of doing what is needed.

It's slow - it scans up a class tree.
It's ugly.
It isn't actually testing what a lot of people seem to think - if you want to find out is some object can handle a certain capability try actually asking with something like  #isAGraphicThing rather than (isKindOf: Morph) or:[ foo isKindOf: DisplayObject] blahblahblah.

We can do better.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Paralyzed from the neck up.






--
Casey Ransberger


Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Casey Ransberger-2
Only tangentially related but I can't resist. Here's my least-favorite hack... pure evil. What was that thing uncle Ben said about power?

someObject perform: ('foo' , 'Bar') asSymbol. "There are no senders of #fooBar! Oh wait..."


On Sat, Aug 31, 2013 at 8:30 PM, Casey Ransberger <[hidden email]> wrote:
Totally. Also, one might argue that switching on type isn't terribly object-oriented. Or rather, it sort of re-implements dispatch. Sometimes it's hard to avoid, but some hard things are worth doing. Of course I'm a big fat hypocrite once in a long while (DNU hacks, #isKindOf:, etc.)

#respondsTo: is nicer in some spots. Protocol isn't class. Etc.

+1


On Sat, Aug 31, 2013 at 7:39 PM, tim Rowledge <[hidden email]> wrote:
There are 623 senders of isKindOf: in the 4.5 image I'm using right now - which may be more than the general because I have some extra stuff loaded - and I'd bet that there are no more than a dozen places where it is actually a sensible way of doing what is needed.

It's slow - it scans up a class tree.
It's ugly.
It isn't actually testing what a lot of people seem to think - if you want to find out is some object can handle a certain capability try actually asking with something like  #isAGraphicThing rather than (isKindOf: Morph) or:[ foo isKindOf: DisplayObject] blahblahblah.

We can do better.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- Paralyzed from the neck up.






--
Casey Ransberger



--
Casey Ransberger


Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Andres Valloud-4
In reply to this post by timrowledge
> It's slow - it scans up a class tree.

... my favorite part of the slowness is that isKindOf: causes an
unending sequence of megamorphic message sends which routinely need
expensive lookups or large, much more complicated caches than "simple"
PICs so the process is not overly slow.  And of course, since the
isKindOf: code tends to be well refactored, there is effectively one
send site for every one of those megamorphic messages in the whole
image, which _ensures_ those send sites will be slow... ;).

Andres.

Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Andres Valloud-4
Hey, let's use isKindOf: for exception handling!

... oh, wait...

On 8/31/13 23:35 , Andres Valloud wrote:

>> It's slow - it scans up a class tree.
>
> ... my favorite part of the slowness is that isKindOf: causes an
> unending sequence of megamorphic message sends which routinely need
> expensive lookups or large, much more complicated caches than "simple"
> PICs so the process is not overly slow.  And of course, since the
> isKindOf: code tends to be well refactored, there is effectively one
> send site for every one of those megamorphic messages in the whole
> image, which _ensures_ those send sites will be slow... ;).
>
> Andres.
>
>

Reply | Threaded
Open this post in threaded view
|

No senders of #fooBar (was: USe of isKindOf: is a crime against humanity)

Stéphane Rollandin
In reply to this post by Casey Ransberger-2
> someObject perform: ('foo' , 'Bar') asSymbol. "There are no senders of
> #fooBar! Oh wait..."

(SimpleButtonMorph new
        label: 'Test';
        target: (MessageSend receiver: World selector: #fooBar);
        actionSelector: #value) openInHand

... no senders of #fooBar are found either.

Of course the above example is silly, but my point is that the look-up
for senders is not comprehensive anyway.

Stef

Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Frank Shearar-3
In reply to this post by Casey Ransberger-2
It's not terribly OO, I agree. It's useful in a kind've pattern
matching-y way (albeit pattern matching lite). I used it deliberately
when playing around with derivative parsing. Take a look at
#isNullableBlock here:
https://github.com/frankshearar/Parsing-Derivatives/blob/master/Derivatives/DerivingParser.st

isNullableBlock
    | n |
    n := nil.
    n := [:p |
        p class caseOf: {
            [Empty] -> [false].
            [EmptyString] -> [true].
            [EpsStar] -> [true].
            [Literal] -> [false].
            [LiteralSet] -> [false].
            [Union] -> [(n value: p left) or: [n value: p right]].
            [Cat] -> [(n value: p first) and: [n value: p second]].
            [Red] -> [n value: p parser].
            [StarParser] -> [(n value: p parser) or: [p parser isEmpty]].
            [DelayedParser] -> [n value: p force].
            [DelegateParser] -> [n value: p parser]}
        otherwise: [Error signal: 'isNullable not defined for ', p
className]] lfpWithBottom: false.
    ^ n.

(We're _effectively_ using #isMemberOf: (I think? I can never remember
which is "is this class" and which is "is this class or subclass") by
switching on `p class`.)

I switch on type here because I'm much more interested here in the
algorithm, and I can concentrate the whole thing into one place,
rather than use implementors-of to view and a Browser to extend.

But if you could mark methods as belonging to the same "conceptually
same method split into multiple parts like a type-switching pattern
match" you could have a special Browser assemble all the parts to
display them together, as well as make it easily to extend the
"partial method". When you use Traits the Browser +
SystemChangeNotification stuff lets you do all sorts of nifty things
that feel like you're working with (lisp) macros while also letting it
look like everything's flattened. We need more of that.

frank

On 1 September 2013 04:30, Casey Ransberger <[hidden email]> wrote:

> Totally. Also, one might argue that switching on type isn't terribly
> object-oriented. Or rather, it sort of re-implements dispatch. Sometimes
> it's hard to avoid, but some hard things are worth doing. Of course I'm a
> big fat hypocrite once in a long while (DNU hacks, #isKindOf:, etc.)
>
> #respondsTo: is nicer in some spots. Protocol isn't class. Etc.
>
> +1
>
>
> On Sat, Aug 31, 2013 at 7:39 PM, tim Rowledge <[hidden email]> wrote:
>>
>> There are 623 senders of isKindOf: in the 4.5 image I'm using right now -
>> which may be more than the general because I have some extra stuff loaded -
>> and I'd bet that there are no more than a dozen places where it is actually
>> a sensible way of doing what is needed.
>>
>> It's slow - it scans up a class tree.
>> It's ugly.
>> It isn't actually testing what a lot of people seem to think - if you want
>> to find out is some object can handle a certain capability try actually
>> asking with something like  #isAGraphicThing rather than (isKindOf: Morph)
>> or:[ foo isKindOf: DisplayObject] blahblahblah.
>>
>> We can do better.
>>
>> tim
>> --
>> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
>> Useful random insult:- Paralyzed from the neck up.
>>
>>
>>
>
>
>
> --
> Casey Ransberger
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: USe of isKindOf: is a crime against humanity

Levente Uzonyi-2
On Sun, 1 Sep 2013, Frank Shearar wrote:

> It's not terribly OO, I agree. It's useful in a kind've pattern
> matching-y way (albeit pattern matching lite). I used it deliberately
> when playing around with derivative parsing. Take a look at
> #isNullableBlock here:
> https://github.com/frankshearar/Parsing-Derivatives/blob/master/Derivatives/DerivingParser.st
>
> isNullableBlock
>    | n |
>    n := nil.
>    n := [:p |
>        p class caseOf: {
>            [Empty] -> [false].
>            [EmptyString] -> [true].
>            [EpsStar] -> [true].
>            [Literal] -> [false].
>            [LiteralSet] -> [false].
>            [Union] -> [(n value: p left) or: [n value: p right]].
>            [Cat] -> [(n value: p first) and: [n value: p second]].
>            [Red] -> [n value: p parser].
>            [StarParser] -> [(n value: p parser) or: [p parser isEmpty]].
>            [DelayedParser] -> [n value: p force].
>            [DelegateParser] -> [n value: p parser]}
>        otherwise: [Error signal: 'isNullable not defined for ', p
> className]] lfpWithBottom: false.
>    ^ n.
>
> (We're _effectively_ using #isMemberOf: (I think? I can never remember
> which is "is this class" and which is "is this class or subclass") by
> switching on `p class`.)

Yes, it's something like #isMemberOf:, but not exactly, due to the hidden
#= sends of #caseOf:otherwise:. #isMemberOf: doesn't do any message sends
in Squeak.

>
> I switch on type here because I'm much more interested here in the
> algorithm, and I can concentrate the whole thing into one place,
> rather than use implementors-of to view and a Browser to extend.
>
> But if you could mark methods as belonging to the same "conceptually
> same method split into multiple parts like a type-switching pattern
> match" you could have a special Browser assemble all the parts to
> display them together, as well as make it easily to extend the
> "partial method". When you use Traits the Browser +
> SystemChangeNotification stuff lets you do all sorts of nifty things
> that feel like you're working with (lisp) macros while also letting it
> look like everything's flattened. We need more of that.

If you come up with a unique selector, then you can let the VM do the
dispatching, which is a lot more efficient. The unique selector will
ensure that you can use the Implementors Browser to see just these
methods at the same place.


Levente

>
> frank
>
> On 1 September 2013 04:30, Casey Ransberger <[hidden email]> wrote:
>> Totally. Also, one might argue that switching on type isn't terribly
>> object-oriented. Or rather, it sort of re-implements dispatch. Sometimes
>> it's hard to avoid, but some hard things are worth doing. Of course I'm a
>> big fat hypocrite once in a long while (DNU hacks, #isKindOf:, etc.)
>>
>> #respondsTo: is nicer in some spots. Protocol isn't class. Etc.
>>
>> +1
>>
>>
>> On Sat, Aug 31, 2013 at 7:39 PM, tim Rowledge <[hidden email]> wrote:
>>>
>>> There are 623 senders of isKindOf: in the 4.5 image I'm using right now -
>>> which may be more than the general because I have some extra stuff loaded -
>>> and I'd bet that there are no more than a dozen places where it is actually
>>> a sensible way of doing what is needed.
>>>
>>> It's slow - it scans up a class tree.
>>> It's ugly.
>>> It isn't actually testing what a lot of people seem to think - if you want
>>> to find out is some object can handle a certain capability try actually
>>> asking with something like  #isAGraphicThing rather than (isKindOf: Morph)
>>> or:[ foo isKindOf: DisplayObject] blahblahblah.
>>>
>>> We can do better.
>>>
>>> tim
>>> --
>>> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
>>> Useful random insult:- Paralyzed from the neck up.
>>>
>>>
>>>
>>
>>
>>
>> --
>> Casey Ransberger
>>
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: No senders of #fooBar (was: USe of isKindOf: is a crime against humanity)

Bert Freudenberg
In reply to this post by Stéphane Rollandin
On 2013-09-01, at 11:32, Stéphane Rollandin <[hidden email]> wrote:

>> someObject perform: ('foo' , 'Bar') asSymbol. "There are no senders of
>> #fooBar! Oh wait..."
>
> (SimpleButtonMorph new
> label: 'Test';
> target: (MessageSend receiver: World selector: #fooBar);
> actionSelector: #value) openInHand
>
> ... no senders of #fooBar are found either.
>
> Of course the above example is silly, but my point is that the look-up for senders is not comprehensive anyway.
>
> Stef

I have occasionally put a literal array of all the constructed selectors at the sending site, just to facilitate senders browsing:

        #(fooBar fooBaz fooFum). "for senders browsing"
        someObject perform: ('foo' , thing) asSymbol.

It even helps to do that if the selector is not constructed but simply performed after being passed into the method.

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: No senders of #fooBar (was: USe of isKindOf: is a crime against humanity)

Casey Ransberger-2
I've done stuff like this too. What I was pointing out was mostly composing selectors from strings. One great way to tell e.g. ME that a message actually is sent somewhere when doing these kinds of shenanigans is to write an SUnit test which includes the composed selector. Then it will still show up as being sent, and I'll know not to remove the method from my image as useless.

Make sense, gents? :)


On Mon, Sep 2, 2013 at 4:04 AM, Bert Freudenberg <[hidden email]> wrote:
On 2013-09-01, at 11:32, Stéphane Rollandin <[hidden email]> wrote:

>> someObject perform: ('foo' , 'Bar') asSymbol. "There are no senders of
>> #fooBar! Oh wait..."
>
> (SimpleButtonMorph new
>       label: 'Test';
>       target: (MessageSend receiver: World selector: #fooBar);
>       actionSelector: #value) openInHand
>
> ... no senders of #fooBar are found either.
>
> Of course the above example is silly, but my point is that the look-up for senders is not comprehensive anyway.
>
> Stef

I have occasionally put a literal array of all the constructed selectors at the sending site, just to facilitate senders browsing:

        #(fooBar fooBaz fooFum). "for senders browsing"
        someObject perform: ('foo' , thing) asSymbol.

It even helps to do that if the selector is not constructed but simply performed after being passed into the method.

- Bert -






--
Casey Ransberger