[Cuis-dev] Poll: ? instead of is: ?
Andres Valloud
ten at smallinteger.com
Tue Aug 6 21:16:08 PDT 2019
On 8/6/19 19:03, Phil B wrote:
> I'm assuming you're referring to my first example use case (if not,
> you've lost me): It's not a case of undesirable forms of polymorphism,
> it's a case of invalid forms of polymorphism. Just because the
> image/VM uses polymorphism to (usually) nicely get you to the debugger
> doesn't mean polymorphism is always the answer.
I agree, just because something is there is not valid grounds to use it.
> Sometimes, discontinuities in control flow (and hijacking those
> discontinuities) are your only way out of / around a problem and it is
> desirable/necessary to control when and how they occur to allow for more
> graceful recovery or by invoking the debugger/logging an error sooner
> rather than later to provide more meaningful feedback.
>
> If one is developing a relatively straightforward application
> interactively in the image, sure just wait for the debugger to pop and
> solve the problems as they occur. That approach falls apart rather
> quickly when you bring background processes, FFI and networking into the
> mix and is a non-starter for most server-based applications. If you add
> to the mix sourcing arbitrary code/data from the Internet, you are now
> living with a qualitatively different order of pain. That's when things
> like #is: start looking really good vs. the alternatives.
I can see some of that. In "normal" circumstances, like what I saw when
I reviewed those senders of #is:, I still think #is: is more a symptom
than a feature.
Andres.
>
> On Tue, Aug 6, 2019 at 7:28 PM Andres Valloud via Cuis-dev
> <cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>> wrote:
>
> The argument seems to be that undesirable forms of polymorphism can be
> avoided with #is: messages--- yet the #is: messages are polymorphic
> themselves. Why, exactly, is the polymorphic use of #is: better than
> other forms of polymorphism?
>
> To me, that kind of usage reimplements by hand what the VM is
> working so
> hard to provide. The result is code that is slower (the system has
> more
> to do), and bigger (my brain has more to think about). But don't
> repeat
> yourself, once and only once, and all that. So I'd rather not.
>
> On 8/6/19 15:39, Phil B wrote:
> > Two main use cases off the top of my head:
> >
> > 1) Sometimes I'm doing an assert: (x is #Foo) where I need to check
> > behavior, not type, in the assertion. (#respondsTo: is too granular)
> >
> > 2) Dynamic dispatch. A recent example that comes to mind is a
> clipboard
> > object handler where I had a dynamic dispatcher that is generated
> > dynamically at runtime based on what packages are loaded when it
> is called.
> >
> > Polymorphism is a great tool, but it's not always the right tool.
> >
> >
> > On Tue, Aug 6, 2019, 5:55 PM Andres Valloud via Cuis-dev
> > <cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>
> <mailto:cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>>> wrote:
> >
> > If one is willing to implement #is: and friends so that one
> can write
> >
> > (x is: #Blah) ifTrue: [x doSomething]
> >
> > then why not just write the following?
> >
> > x doSomethingIfBlah
> >
> > It's essentially the same number of methods, and if too many
> of those
> > start accumulating in Object then you know there's a design
> problem
> > that
> > should be fixed rather than accommodated.
> >
> > Also, it's way faster because now there are fewer message
> sends, and
> > the
> > code is delegating the class / protocol checks to the VM
> (which was
> > there to provide that functionality in the first place).
> >
> > On 8/6/19 14:08, Phil B wrote:
> > > I've always seen the value as being two-fold:
> > >
> > > 1) To avoid needing to implement N #is* methods on Object (and
> > there's a
> > > lot more of this out there than just what the base image
> > implements and
> > > uses)
> > >
> > > 2) As a mechanism to test for *protocol* compliance rather
> than
> > *class*
> > > membership of an object. One may or may not agree with this
> > > interpretation, but lacking a definition that said
> otherwise, I
> > decided
> > > it meant this as well 😀
> > >
> > > While implementations in the base image tend to have a 1:1
> > relationship
> > > with a particular class, it is not required. For example,
> I have a
> > > number of classes that return true for #is: which aren't
> actually
> > > subclasses of the thing they return true for but do behave
> as if
> > they
> > > were. I don't care so much if a given object isKindOf:
> Morph, but
> > > rather if it behaves as one.
> > >
> > > There was a time when I tried to make the second use case more
> > explicit
> > > but there didn't seem to be a interest from others. So I
> may be the
> > > only person who makes use of the second use case today.
> If so and 1
> > > isn't seen as a worthwhile reason to stick with this
> approach, I
> > can do
> > > this another way.
> > >
> > > On Tue, Aug 6, 2019, 3:21 PM Andres Valloud via Cuis-dev
> > > <cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>
> <mailto:cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>>
> > <mailto:cuis-dev at lists.cuis.st
> <mailto:cuis-dev at lists.cuis.st> <mailto:cuis-dev at lists.cuis.st
> <mailto:cuis-dev at lists.cuis.st>>>> wrote:
> > >
> > > So it looks like the #is: methods are there to
> implement the
> > > functionality of #isXYZ messages with half the
> methods, which
> > in turn
> > > are there presumably to avoid having to send class or
> > #isKindOf:. But
> > > one way or another, they are still class checks done
> in the
> > language,
> > > when the system already provides fast and invisible class
> > checking in
> > > every message send.
> > >
> > > In an old Cuis image that I have handy right now,
> there are 30
> > > implementors of #is:. There are 120 senders, but
> > (essentially) 30 of
> > > those are the implementors just mentioned. So, 90
> senders for 30
> > > methods, a use factor of 3. A brief look suggests a
> > histogram, which
> > > yields the following arguments for #is: (excluding the
> > implementors
> > > themselves).
> > >
> > > #(#Text #Color #Morph #Morph #Text #Morph #Form #Text
> #Morph
> > #Form
> > > #Text
> > > #Text #Text #Form #Morph #Text #PluggableButtonMorph
> > #CompiledMethod
> > > #Morph #Color #Color #ColorForm #CompiledMethod
> #Stream #Text
> > #Stream
> > > #Morph #DateAndTime #DateAndTime #DateAndTime #DateAndTime
> > #DateAndTime
> > > #Text #Array #HandMorph #InnerTextMorph #InnerTextMorph
> > #SystemWindow
> > > #SystemWindow #HandMorph #MessageSend #Color #Text
> #ScrollPane
> > > #CompiledMethod #Text #HandMorph #MenuItemMorph
> #MenuItemMorph
> > > #MenuItemMorph #MenuItemMorph #UpdatingMenuItemMorph
> > > #UpdatingMenuItemMorph #LayoutMorph #HandMorph
> > #CompiledMethod #Stream
> > > #Stream #Text #HandMorph #SystemWindow #HandMorph
> > #MorphicEvent #Morph
> > > #HaloMorph #Stream #Text #Text #HaloMorph
> #SystemWindow #Taskbar
> > > #SystemWindow #SystemWindow #MessageSend
> #refusingToAccept #Text
> > > #Rectangle #Rectangle #Rectangle #Rectangle #Rectangle
> #Text
> > > #hasTextProvider #hasTextProvider #Stream #Text #Text
> #Text
> > > #CompiledMethod #SystemWindow #SystemWindow
> #PluggableListMorph
> > > #SystemWindow #SystemWindow #Taskbar #Text #Morph
> #Text #Text
> > #Text
> > > #DateAndTime #DateAndTime #DateAndTime #DateAndTime
> #DateAndTime
> > > #UpdatingMenuItemMorph #ColorForm #MessageSend
> #MessageSend
> > #Morph
> > > #Morph)
> > >
> > > As a set, this collection has a size of 25 (so already
> this
> > suggests
> > > dead code is present). Further, as an actual
> histogram, we
> > see this:
> > >
> > > #Text -> 23
> > > #Morph -> 11
> > > #DateAndTime -> 10
> > > #SystemWindow -> 10
> > > #Stream -> 6
> > > #HandMorph -> 6
> > > #Rectangle -> 5
> > > #CompiledMethod -> 5
> > > #MessageSend -> 4
> > > #Color -> 4
> > > #MenuItemMorph -> 4
> > > #UpdatingMenuItemMorph -> 3
> > > #Form -> 3
> > > #hasTextProvider -> 2
> > > #HaloMorph -> 2
> > > #Taskbar -> 2
> > > #ColorForm -> 2
> > > #InnerTextMorph -> 2
> > > #PluggableButtonMorph -> 1
> > > #LayoutMorph -> 1
> > > #Array -> 1
> > > #refusingToAccept -> 1
> > > #PluggableListMorph -> 1
> > > #ScrollPane -> 1
> > > #MorphicEvent -> 1
> > >
> > > which suggests there is something going on,
> design-wise, with
> > the top
> > > 20% because together they account for much more than
> 50% of
> > the usage.
> > >
> > > So, even though as syntax I would find it just fine, I
> wonder
> > if this
> > > improvement is optimizing the highest priority problem.
> > >
> > > What has been the evolution / usage of this feature over
> > time? Where
> > > should it go from here?
> > >
> > > On 8/6/19 04:54, Juan Vuletich via Cuis-dev wrote:
> > > > Hi Folks,
> > > >
> > > > One thing I don't like about the #is: message is
> that being a
> > > keyword,
> > > > it usually requires parenthesis. Today I realized
> we can
> > use #?
> > > instead.
> > > > So, we could write:
> > > >
> > > > aForm ? #GrayForm ifTrue: [ self doSomething ].
> > > >
> > > > instead of
> > > >
> > > > (aForm is: #GrayForm) ifTrue: [ self doSomething ].
> > > >
> > > > Do you like it? What do you prefer, #is: or #? ?
> Reasons for
> > > adopting or
> > > > not adopting it?
> > > >
> > > > Thanks,
> > > >
> > > --
> > > Cuis-dev mailing list
> > > Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>
> <mailto:Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>>
> > <mailto:Cuis-dev at lists.cuis.st
> <mailto:Cuis-dev at lists.cuis.st> <mailto:Cuis-dev at lists.cuis.st
> <mailto:Cuis-dev at lists.cuis.st>>>
> > > https://lists.cuis.st/mailman/listinfo/cuis-dev
> > >
> > --
> > Cuis-dev mailing list
> > Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>
> <mailto:Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>>
> > https://lists.cuis.st/mailman/listinfo/cuis-dev
> >
> --
> Cuis-dev mailing list
> Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>
> https://lists.cuis.st/mailman/listinfo/cuis-dev
>
More information about the Cuis-dev
mailing list