Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
March 2022
- 32 participants
- 104 messages
Re: Null Object Pattern
by sean@clipperadams.com
> I feel like youâve latched onto something that is genuinely a non problemâ¦
I wouldnât call complexity and lack of consistency a ânon problemâ, but it sounds like for you the practical implications outweigh my seemingly-somewhat-ideological/niche concerns. Is that a fair summary? In any case, I appreciate your perspective.
March 18, 2022
Re: Null Object Pattern
by Todd Blanchard
I feel like youâve latched onto something that is genuinely a non problem and if you get your way we all suffer reduced performance and a guarantee that a nil test is universally the same thing.
If you want an overridable nil test, write your own nil test like isNilish and make it mean what you like without disrupting the rest of the system. Problem solved and youâre not violating the open closed principle.
Sent from my iPhone
> On Mar 18, 2022, at 8:39 AM, sean(a)clipperadams.com wrote:
>
> 
> What you can do is turning it off globally in the setting (all compiler option are listed there)
>
> But take care: we can not recompile the image without optimzations as this adds intererrupt possibilities to code that was not interruptable before, which breaks the code in for process switching itself, I think.
>
> So it sounds like my daydream that inlining be turned off by default is a heavier lift than just flipping a switch, correct?
>
> In principle (ignoring the amount of work involved) what are your thoughts RE my musing: âAfter 40+ years of Mooreâs Law, can we turn off these inlines by default?â and my hypothesis that this is an optimization that made sense at the time but now adds complexity for questionable payoff?
March 18, 2022
Re: Null Object Pattern
by sean@clipperadams.com
> What you can do is turning it off globally in the setting (all compiler option are listed there)
>
> But take care: we can not recompile the image without optimzations as this adds intererrupt possibilities to code that was not
> interruptable before, which breaks the code in for process switching itself, I think.
So it sounds like my daydream that inlining be turned off by default is a heavier lift than just flipping a switch, correct?
In principle (ignoring the amount of work involved) what are your thoughts RE my musing: âAfter 40+ years of Mooreâs Law, can we turn off these inlines by default?â and my hypothesis that this is an optimization that made sense at the time but now adds complexity for questionable payoff?
March 18, 2022
Re: Null Object Pattern
by sean@clipperadams.com
> My chief concern is that I am a bear of very little brain,
> and if you change the meaning of #isNil to anything at all
> other than "is the receiver identical to nil" you *WILL*
> (not may) confuse me.
I can understand your probably well-justified concern that power can always be misused. I also understand a key principle of Smalltalk to be âempower and trust the programmerâ. Edge cases like this where Smalltalk principles like pervasive message passing are not true bring their own share of confusion.
> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
> respond to the #âisNilâ message?"
>
> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
> intentions, and give it what semantics you find useful.
I find the concept of âisâ and âequalâ to be generally confusing in Smalltalk. Does \`#=\` mean âall state is the sameâ? âall relevant state is the same (minus e.g. caching)â? âThis represents the same domain objectâ?
I can see how a proxy claiming to be nil is a âlieâ for one/some definitions of âisâ, but I donât think itâs universally true.
Really interesting conversation!
March 18, 2022
Re: Null Object Pattern
by sean@clipperadams.com
> My *concern* with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a *different* implementation. That is, you lose the opportunity to have the *receiver* decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message.
Yes, this is exactly the point I was (apparently badly) trying to convey. Thanks!
March 18, 2022
Re: Null Object Pattern
by Marcus Denker
> On 17 Mar 2022, at 18:00, Esteban Maringolo <emaringolo(a)gmail.com> wrote:
>
> That is great!
>
> Is it possible to disable it for doits and other playground expressions?
>
No, there is no hook yet⦠it would be interesting to see how to do that.
(e.g. per playground compiler parameters, parameters for doit independent of the compiler used for compiling methodsâ¦)
What you can do is turning it off globally in the setting (all compiler option are listed there)
But take care: we can not recompile the image without optimzations as this adds intererrupt possibilities to code that was not
interruptable before, which breaks the code in for process switching itself, I think.
> Regards!
>
> Esteban A. Maringolo
>
> On Thu, Mar 17, 2022 at 1:23 PM Marcus Denker <marcus.denker(a)inria.fr> wrote:
>> On 17 Mar 2022, at 17:17, Richard Sargent <richard.sargent(a)gemtalksystems.com> wrote:
>> A pragma might be the way to go.
>> <noInline: #and:> for example.
>>
>>
>>
>> There is already the #compilerOptions: Pragma, e.g.:
>>
>> <compilerOptions: #(- optionInlineAndOr )>
>> For example this method compiled the and: as a real send:
>> tt
>> <compilerOptions: #(- optionInlineAndOr)>
>> true and: [ false ]
>>
>>
>> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo <emaringolo(a)gmail.com> wrote:
>
>>> A great trade off would be to be able
>>> to enable/disable for certain things instead of it being a global
>>> setting.
March 18, 2022
Re: Null Object Pattern
by Esteban Maringolo
That is great!
Is it possible to disable it for doits and other playground expressions?
Regards!
Esteban A. Maringolo
On Thu, Mar 17, 2022 at 1:23 PM Marcus Denker <marcus.denker(a)inria.fr> wrote:
> On 17 Mar 2022, at 17:17, Richard Sargent <richard.sargent(a)gemtalksystems.com> wrote:
> A pragma might be the way to go.
> <noInline: #and:> for example.
>
>
>
> There is already the #compilerOptions: Pragma, e.g.:
>
> <compilerOptions: #(- optionInlineAndOr )>
> For example this method compiled the and: as a real send:
> tt
> <compilerOptions: #(- optionInlineAndOr)>
> true and: [ false ]
>
>
> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo <emaringolo(a)gmail.com> wrote:
>> A great trade off would be to be able
>> to enable/disable for certain things instead of it being a global
>> setting.
March 17, 2022
Re: Null Object Pattern
by Marcus Denker
> On 17 Mar 2022, at 17:17, Richard Sargent <richard.sargent(a)gemtalksystems.com> wrote:
>
> A pragma might be the way to go.
>
> <noInline: #and:> for example.
There is already the #compilerOptions: Pragma, e.g.:
<compilerOptions: #(- optionInlineAndOr )>
For example this method compiled the and: as a real send:
tt
<compilerOptions: #(- optionInlineAndOr)>
true and: [ false ]
>
> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo <emaringolo(a)gmail.com <mailto:emaringolo@gmail.com>> wrote:
> Just to add another argument in favor of not inlining some message
> sends, is for instance in things like Glorp you need to use a special
> selector for #and:/#or: message sends, breaking not only the naming
> conventions but also the polymorphism.
>
> E.g. you have to use #AND: and #OR: to avoid inlining.
> db read: YourClass where: [:inst | inst name = 'John' AND: [inst color
> = 'blue' OR: [inst color = 'red']]].
>
> This is not only annoying, it also causes that if you want to to use
> something else as a backend (instead of Glorp), your block doesn't
> work anymore, which would perfectly work for a regular collection of
> elements using their underscore #and:/#or: equivalents.
>
> The important thing, IMO, is that the core of OO is message sending,
> and enabling the receiver what to do with a message, which in the
> worst case would mean "I don't understand this message". A procedure
> call inverts the responsibility. A great trade off would be to be able
> to enable/disable for certain things instead of it being a global
> setting.
>
> Regards,
>
> Esteban A. Maringolo
>
> On Thu, Mar 17, 2022 at 11:53 AM James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
> >
> > Richard,
> >
> > I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ and was pointing a student to that article just this week.
> >
> > In any case, I think youâve demonstrated that you now comprehend the argument against inliningâyou just donât agree. Thatâs fair and I think the discussion has been clarified. Would it be fair to say that you have an âideological objectionâ to allowing a Proxy or Stub to transparently stand in for another object (say, in a two-object-space environment such as Pharo and GemStone)? That is, a domain object canât be replaced by a Proxy or Stub without a wholesale rewrite of the rest of the application? I respect that as a reasonable position (demanding perfect clarity), but I see a cost to that position as well.
> >
> > Of course, if you really want to avoid allowing the receiver to chose its response to a message, you can use other messages. So if you want to find out if an object is identical to nil you should use `nil == myObject` to ensure that there was not an override of #âisNilâ or #â==â by the objectâs class.
> >
> > James
> >
> > On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
> >
> > My chief concern is that I am a bear of very little brain,
> > and if you change the meaning of #isNil to anything at all
> > other than "is the receiver identical to nil" you *WILL*
> > (not may) confuse me. This extends to things that happen
> > not to be inlined: if even a god-like Smalltalker like
> > Andres Valloud overloads #, to something other than "combine
> > the collection that is the receiver with the collection that
> > is the argument to yield a new collection" than I *WILL*
> > most certainly be confused and find the code unmaintainable.
> > Smalltalk being Smalltalk, if you admit an inconsistent
> > overload anywhere, I can no longer understand sends of that
> > selector anywhere. One of the things to like about Traits
> > is that you can say "this class doesn't just *happen* to
> > have selectors x and y, it has them *because* it has this
> > whole consistent bundle of selectors."
> >
> > There are more annotations documented for my Smalltalk
> > compiler than are actually implemented. One that *is*
> > implemented is <doNotOverride>, and it has caught more
> > mistakes than I care to admit to. It's particularly
> > important for a bundle of methods with varying arguments
> > that are meant to be routed through a single method,
> > which *is* meant to be overridden. It makes sure that
> > I override the *right* method. (Take #= and #~= as an
> > obvious example.)
> >
> > Once you start down the path of lying about things like #isNil
> > you find that EITHER you have to go very far down that path
> > and override #== and #instVarAt: and a whole lot of other
> > things OR you are working with a semantically incoherent system.
> >
> > "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message?"
> >
> > It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
> > even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
> > cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
> > intentions, and give it what semantics you find useful.
> >
> > "How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?"
> >
> > It should answer false. Period. No ifs, buts, quibbles, or maybes.
> > The whole *point* of the Null Object Pattern is to return something
> > that *isn't* nil, that has quite a different protocol. If you call
> > something that is supposed to return either a Foo or a NullFoo, and
> > it gives you nil instead, there is a BUG in what you just called so
> > the sooner you find out the better. What you want is
> >
> > Foo >> isNullFoo ^false
> > NullFoo >> isNullFoo ^true
> > and no other class defines #isNullFoo.
> >
> > That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
> > (a) you make it clear to someone reading your code what you are expecting
> > (b) if you DON'T get what you are expecting, Smalltalk will tell you.
> >
> > I must admit that on the few occasions when I've used Null Object
> > I've used an all-purpose #isMissing instead of a task-appropriate
> > #isNullFoo, but then I figured out what I was doing wrong. You
> > look at the code, you say "there's *something* off here, but I don't
> > know what." But when you ask "what, exactly, does this method MEAN?"
> > you realise "oh, THAT'S what I was doing wrong." #isMissing told me
> > it was a NullPerson or a NullAddress or a NullPartsList or ... but
> > in this case I needed to know whether it was a NullSummary.
> >
> > And of course you run into E.F.Codd's lesson: "one NULL is never
> > enough, information can be missing for more than one reason".
> > Take the familiar example of a phone number:
> > - I know that Fred's phone number is X
> > - I know that Fred has a phone but I don't know what the number is
> > - I don't know whether Fred has a phone or not
> > - I know that Fred has no phone
> > There's room for three *different* null objects there.
> > Should we have UnknownNumberOfActualPhone to answer false to #isnil
> > and NonNumberOfNonexistentPhone to answer true? Or what?
> >
> > By the way, you may have misunderstood my benchmark.
> > It wasn't that #isNil or even _ ifNotNil: speeded up by
> > 10%, it was the *whole* matrix-munching benchmark that
> > speeded up. Certainly not a big deal, but it's not
> > something I'd be happy to give up in order to get less
> > maintainable code.
> >
> >
> >
> >
> >
> >
> >
> >
> > On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
> >>
> >> Richard,
> >>
> >> My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
> >>
> >> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?
> >>
> >> And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
> >>
> >> Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
> >>
> >> James
> >>
> >> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
> >>
> >> We're still not on the same page.
> >> You seem to have some ideological objection to inlining that
> >> I am completely failing to comprehend.
> >> Just because a procedure call (message send) is inlined doesn't
> >> in the least mean it *isn't* a procedure call (message send),
> >> just as compiling a procedure call (message send) as a jump
> >> (last-call optimisation) doesn't mean it *isn't* a procedure
> >> call (message send).
> >> By the way, forget about "40 years ago".
> >> I just did an experiment in Pharo 9, and found that
> >> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
> >> -- where izNil is a non-inlined self == nil --
> >> gave a 10% speedup, in a test code where real work was going
> >> on as well.
> >> As for turning off all inlining, what do you think that would
> >> do to #ifFalse:ifTrue: and its relatives?
> >>
> >>
> >> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com <mailto:sean@clipperadams.com>> wrote:
> >>>
> >>>
> >>> To start with, why do you CARE whether a particular method is inlined or not?
> >>>
> >>> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
> >>>
> >>> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
> >>>
> >>> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
> >>>
> >>> *or as many as practical
> >>>
> >>> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
> >>>
> >>> I agree that it is in general a smell, but long chains was tangential to the intention above
> >>>
> >>> Can you give an example?
> >>>
> >>> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
> >>>
> >>> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
> >>>
> >>> Agreed. See smell comment above.
> >>
> >>
> >
March 17, 2022
Re: Null Object Pattern
by Richard Sargent
A pragma might be the way to go.
*<noInline: #and:>* for example.
On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo <emaringolo(a)gmail.com>
wrote:
> Just to add another argument in favor of not inlining some message
> sends, is for instance in things like Glorp you need to use a special
> selector for #and:/#or: message sends, breaking not only the naming
> conventions but also the polymorphism.
>
> E.g. you have to use #AND: and #OR: to avoid inlining.
> db read: YourClass where: [:inst | inst name = 'John' AND: [inst color
> = 'blue' OR: [inst color = 'red']]].
>
> This is not only annoying, it also causes that if you want to to use
> something else as a backend (instead of Glorp), your block doesn't
> work anymore, which would perfectly work for a regular collection of
> elements using their underscore #and:/#or: equivalents.
>
> The important thing, IMO, is that the core of OO is message sending,
> and enabling the receiver what to do with a message, which in the
> worst case would mean "I don't understand this message". A procedure
> call inverts the responsibility. A great trade off would be to be able
> to enable/disable for certain things instead of it being a global
> setting.
>
> Regards,
>
> Esteban A. Maringolo
>
> On Thu, Mar 17, 2022 at 11:53 AM James Foster <smalltalk(a)jgfoster.net>
> wrote:
> >
> > Richard,
> >
> > I very much admire Dijkstraâs admonition regarding âThe Humble
> Programmerâ and was pointing a student to that article just this week.
> >
> > In any case, I think youâve demonstrated that you now comprehend the
> argument against inliningâyou just donât agree. Thatâs fair and I think the
> discussion has been clarified. Would it be fair to say that you have an
> âideological objectionâ to allowing a Proxy or Stub to transparently stand
> in for another object (say, in a two-object-space environment such as Pharo
> and GemStone)? That is, a domain object canât be replaced by a Proxy or
> Stub without a wholesale rewrite of the rest of the application? I respect
> that as a reasonable position (demanding perfect clarity), but I see a cost
> to that position as well.
> >
> > Of course, if you really want to avoid allowing the receiver to chose
> its response to a message, you can use other messages. So if you want to
> find out if an object is identical to nil you should use `nil == myObject`
> to ensure that there was not an override of #âisNilâ or #â==â by the
> objectâs class.
> >
> > James
> >
> > On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
> >
> > My chief concern is that I am a bear of very little brain,
> > and if you change the meaning of #isNil to anything at all
> > other than "is the receiver identical to nil" you *WILL*
> > (not may) confuse me. This extends to things that happen
> > not to be inlined: if even a god-like Smalltalker like
> > Andres Valloud overloads #, to something other than "combine
> > the collection that is the receiver with the collection that
> > is the argument to yield a new collection" than I *WILL*
> > most certainly be confused and find the code unmaintainable.
> > Smalltalk being Smalltalk, if you admit an inconsistent
> > overload anywhere, I can no longer understand sends of that
> > selector anywhere. One of the things to like about Traits
> > is that you can say "this class doesn't just *happen* to
> > have selectors x and y, it has them *because* it has this
> > whole consistent bundle of selectors."
> >
> > There are more annotations documented for my Smalltalk
> > compiler than are actually implemented. One that *is*
> > implemented is <doNotOverride>, and it has caught more
> > mistakes than I care to admit to. It's particularly
> > important for a bundle of methods with varying arguments
> > that are meant to be routed through a single method,
> > which *is* meant to be overridden. It makes sure that
> > I override the *right* method. (Take #= and #~= as an
> > obvious example.)
> >
> > Once you start down the path of lying about things like #isNil
> > you find that EITHER you have to go very far down that path
> > and override #== and #instVarAt: and a whole lot of other
> > things OR you are working with a semantically incoherent system.
> >
> > "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to
> nil respond to the #âisNilâ message?"
> >
> > It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like
> nil,
> > even if it is a proxy for nil. A proxy, qua proxy, can do things that
> nil
> > cannot. Use another selector, #isEffectivelyNil, or whatever reveals
> your
> > intentions, and give it what semantics you find useful.
> >
> > "How should the Null Object Pattern (
> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?"
> >
> > It should answer false. Period. No ifs, buts, quibbles, or maybes.
> > The whole *point* of the Null Object Pattern is to return something
> > that *isn't* nil, that has quite a different protocol. If you call
> > something that is supposed to return either a Foo or a NullFoo, and
> > it gives you nil instead, there is a BUG in what you just called so
> > the sooner you find out the better. What you want is
> >
> > Foo >> isNullFoo ^false
> > NullFoo >> isNullFoo ^true
> > and no other class defines #isNullFoo.
> >
> > That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
> > (a) you make it clear to someone reading your code what you are expecting
> > (b) if you DON'T get what you are expecting, Smalltalk will tell you.
> >
> > I must admit that on the few occasions when I've used Null Object
> > I've used an all-purpose #isMissing instead of a task-appropriate
> > #isNullFoo, but then I figured out what I was doing wrong. You
> > look at the code, you say "there's *something* off here, but I don't
> > know what." But when you ask "what, exactly, does this method MEAN?"
> > you realise "oh, THAT'S what I was doing wrong." #isMissing told me
> > it was a NullPerson or a NullAddress or a NullPartsList or ... but
> > in this case I needed to know whether it was a NullSummary.
> >
> > And of course you run into E.F.Codd's lesson: "one NULL is never
> > enough, information can be missing for more than one reason".
> > Take the familiar example of a phone number:
> > - I know that Fred's phone number is X
> > - I know that Fred has a phone but I don't know what the number is
> > - I don't know whether Fred has a phone or not
> > - I know that Fred has no phone
> > There's room for three *different* null objects there.
> > Should we have UnknownNumberOfActualPhone to answer false to #isnil
> > and NonNumberOfNonexistentPhone to answer true? Or what?
> >
> > By the way, you may have misunderstood my benchmark.
> > It wasn't that #isNil or even _ ifNotNil: speeded up by
> > 10%, it was the *whole* matrix-munching benchmark that
> > speeded up. Certainly not a big deal, but it's not
> > something I'd be happy to give up in order to get less
> > maintainable code.
> >
> >
> >
> >
> >
> >
> >
> >
> > On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net>
> wrote:
> >>
> >> Richard,
> >>
> >> My _concern_ with inlining is that since it is designed to
> short-circuit dynamic method lookup, it is impossible to call a _different_
> implementation. That is, you lose the opportunity to have the _receiver_
> decide how to respond to the message. You may think of it as a message, but
> the caller is deciding how the receiver will respondâwhich largely defeats
> the purpose and role of it being a message. Yes, at the machine code level
> you are performing a branch instruction, but when comparing OOP to
> Procedural Programming we typically make a distinction between âmessagesâ
> and "procedure calls." The distinction is that the receiver gets to decide
> how to respond to a message. In C++ this is the distinction between a
> âvirtual" and "non-virtual" function. By inlining, you are converting the
> function from a virtual function to a non-virtual function, and this can
> make a difference (which is why virtual functions exist).
> >>
> >> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to
> nil respond to the #âisNilâ message? How should the Null Object Pattern (
> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?
> >>
> >> And, yes, Iâm sure you can come up with benchmarks that show a
> measurable difference, but what is the impact in realistic code? When
> someone asked about inlining #âyourselfâ in GemStone I believe I measured
> the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10%
> speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
> >>
> >> Note that I described my position as a âconcern,â not an ideological
> objection. Mostly Iâm giving a rationale for something that doesnât seem to
> be explained very well for you. I accept that there may be a time for
> inlining, but I can âcomprehend" another side to the issue.
> >>
> >> James
> >>
> >> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
> >>
> >> We're still not on the same page.
> >> You seem to have some ideological objection to inlining that
> >> I am completely failing to comprehend.
> >> Just because a procedure call (message send) is inlined doesn't
> >> in the least mean it *isn't* a procedure call (message send),
> >> just as compiling a procedure call (message send) as a jump
> >> (last-call optimisation) doesn't mean it *isn't* a procedure
> >> call (message send).
> >> By the way, forget about "40 years ago".
> >> I just did an experiment in Pharo 9, and found that
> >> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
> >> -- where izNil is a non-inlined self == nil --
> >> gave a 10% speedup, in a test code where real work was going
> >> on as well.
> >> As for turning off all inlining, what do you think that would
> >> do to #ifFalse:ifTrue: and its relatives?
> >>
> >>
> >> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
> >>>
> >>>
> >>> To start with, why do you CARE whether a particular method is inlined
> or not?
> >>>
> >>> I care because it makes âeverything is a messageâ a lie! And I suspect
> (no proof and could be wrong) itâs an optimization that only made sense
> with the hardware constraints of 40+ years ago. Arguing against premature
> optimization is hardly something I just made up ;-)
> >>>
> >>> This makes absolutely no sense to me. What makes you think that the
> combination "_ isNil ifFalse: [_]" will NOT be inlined?
> >>>
> >>> I may have been unclear. My intent was to communicate: âIâd like to
> stop ALL* inlining of messages by default if possibleâ
> >>>
> >>> *or as many as practical
> >>>
> >>> The thing that rings loud alarm bells for me is there being "long
> chains" in the first place.
> >>>
> >>> I agree that it is in general a smell, but long chains was tangential
> to the intention above
> >>>
> >>> Can you give an example?
> >>>
> >>> I donât know if I can think of one thatâs not contrived⦠Wrapping
> something external? Squeakâs AppleScript support used to mirror the
> underlying AS, which is pretty much exactly that.
> >>>
> >>> In my own programming, I've generally found that nils turning up in
> the middle of a chain indicates a serious design error somewhere.
> >>>
> >>> Agreed. See smell comment above.
> >>
> >>
> >
>
March 17, 2022
Re: Null Object Pattern
by Esteban Maringolo
Just to add another argument in favor of not inlining some message
sends, is for instance in things like Glorp you need to use a special
selector for #and:/#or: message sends, breaking not only the naming
conventions but also the polymorphism.
E.g. you have to use #AND: and #OR: to avoid inlining.
db read: YourClass where: [:inst | inst name = 'John' AND: [inst color
= 'blue' OR: [inst color = 'red']]].
This is not only annoying, it also causes that if you want to to use
something else as a backend (instead of Glorp), your block doesn't
work anymore, which would perfectly work for a regular collection of
elements using their underscore #and:/#or: equivalents.
The important thing, IMO, is that the core of OO is message sending,
and enabling the receiver what to do with a message, which in the
worst case would mean "I don't understand this message". A procedure
call inverts the responsibility. A great trade off would be to be able
to enable/disable for certain things instead of it being a global
setting.
Regards,
Esteban A. Maringolo
On Thu, Mar 17, 2022 at 11:53 AM James Foster <smalltalk(a)jgfoster.net> wrote:
>
> Richard,
>
> I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ and was pointing a student to that article just this week.
>
> In any case, I think youâve demonstrated that you now comprehend the argument against inliningâyou just donât agree. Thatâs fair and I think the discussion has been clarified. Would it be fair to say that you have an âideological objectionâ to allowing a Proxy or Stub to transparently stand in for another object (say, in a two-object-space environment such as Pharo and GemStone)? That is, a domain object canât be replaced by a Proxy or Stub without a wholesale rewrite of the rest of the application? I respect that as a reasonable position (demanding perfect clarity), but I see a cost to that position as well.
>
> Of course, if you really want to avoid allowing the receiver to chose its response to a message, you can use other messages. So if you want to find out if an object is identical to nil you should use `nil == myObject` to ensure that there was not an override of #âisNilâ or #â==â by the objectâs class.
>
> James
>
> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> My chief concern is that I am a bear of very little brain,
> and if you change the meaning of #isNil to anything at all
> other than "is the receiver identical to nil" you *WILL*
> (not may) confuse me. This extends to things that happen
> not to be inlined: if even a god-like Smalltalker like
> Andres Valloud overloads #, to something other than "combine
> the collection that is the receiver with the collection that
> is the argument to yield a new collection" than I *WILL*
> most certainly be confused and find the code unmaintainable.
> Smalltalk being Smalltalk, if you admit an inconsistent
> overload anywhere, I can no longer understand sends of that
> selector anywhere. One of the things to like about Traits
> is that you can say "this class doesn't just *happen* to
> have selectors x and y, it has them *because* it has this
> whole consistent bundle of selectors."
>
> There are more annotations documented for my Smalltalk
> compiler than are actually implemented. One that *is*
> implemented is <doNotOverride>, and it has caught more
> mistakes than I care to admit to. It's particularly
> important for a bundle of methods with varying arguments
> that are meant to be routed through a single method,
> which *is* meant to be overridden. It makes sure that
> I override the *right* method. (Take #= and #~= as an
> obvious example.)
>
> Once you start down the path of lying about things like #isNil
> you find that EITHER you have to go very far down that path
> and override #== and #instVarAt: and a whole lot of other
> things OR you are working with a semantically incoherent system.
>
> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil respond to the #âisNilâ message?"
>
> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
> intentions, and give it what semantics you find useful.
>
> "How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?"
>
> It should answer false. Period. No ifs, buts, quibbles, or maybes.
> The whole *point* of the Null Object Pattern is to return something
> that *isn't* nil, that has quite a different protocol. If you call
> something that is supposed to return either a Foo or a NullFoo, and
> it gives you nil instead, there is a BUG in what you just called so
> the sooner you find out the better. What you want is
>
> Foo >> isNullFoo ^false
> NullFoo >> isNullFoo ^true
> and no other class defines #isNullFoo.
>
> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
> (a) you make it clear to someone reading your code what you are expecting
> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>
> I must admit that on the few occasions when I've used Null Object
> I've used an all-purpose #isMissing instead of a task-appropriate
> #isNullFoo, but then I figured out what I was doing wrong. You
> look at the code, you say "there's *something* off here, but I don't
> know what." But when you ask "what, exactly, does this method MEAN?"
> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
> it was a NullPerson or a NullAddress or a NullPartsList or ... but
> in this case I needed to know whether it was a NullSummary.
>
> And of course you run into E.F.Codd's lesson: "one NULL is never
> enough, information can be missing for more than one reason".
> Take the familiar example of a phone number:
> - I know that Fred's phone number is X
> - I know that Fred has a phone but I don't know what the number is
> - I don't know whether Fred has a phone or not
> - I know that Fred has no phone
> There's room for three *different* null objects there.
> Should we have UnknownNumberOfActualPhone to answer false to #isnil
> and NonNumberOfNonexistentPhone to answer true? Or what?
>
> By the way, you may have misunderstood my benchmark.
> It wasn't that #isNil or even _ ifNotNil: speeded up by
> 10%, it was the *whole* matrix-munching benchmark that
> speeded up. Certainly not a big deal, but it's not
> something I'd be happy to give up in order to get less
> maintainable code.
>
>
>
>
>
>
>
>
> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net> wrote:
>>
>> Richard,
>>
>> My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
>>
>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?
>>
>> And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>>
>> Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
>>
>> James
>>
>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>>
>> We're still not on the same page.
>> You seem to have some ideological objection to inlining that
>> I am completely failing to comprehend.
>> Just because a procedure call (message send) is inlined doesn't
>> in the least mean it *isn't* a procedure call (message send),
>> just as compiling a procedure call (message send) as a jump
>> (last-call optimisation) doesn't mean it *isn't* a procedure
>> call (message send).
>> By the way, forget about "40 years ago".
>> I just did an experiment in Pharo 9, and found that
>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>> -- where izNil is a non-inlined self == nil --
>> gave a 10% speedup, in a test code where real work was going
>> on as well.
>> As for turning off all inlining, what do you think that would
>> do to #ifFalse:ifTrue: and its relatives?
>>
>>
>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
>>>
>>>
>>> To start with, why do you CARE whether a particular method is inlined or not?
>>>
>>> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
>>>
>>> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>>
>>> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
>>>
>>> *or as many as practical
>>>
>>> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
>>>
>>> I agree that it is in general a smell, but long chains was tangential to the intention above
>>>
>>> Can you give an example?
>>>
>>> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
>>>
>>> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
>>>
>>> Agreed. See smell comment above.
>>
>>
>
March 17, 2022
Re: Null Object Pattern
by James Foster
Richard,
I very much admire Dijkstraâs admonition regarding âThe Humble Programmerâ and was pointing a student to that article just this week.
In any case, I think youâve demonstrated that you now comprehend the argument against inliningâyou just donât agree. Thatâs fair and I think the discussion has been clarified. Would it be fair to say that you have an âideological objectionâ to allowing a Proxy or Stub to transparently stand in for another object (say, in a two-object-space environment such as Pharo and GemStone)? That is, a domain object canât be replaced by a Proxy or Stub without a wholesale rewrite of the rest of the application? I respect that as a reasonable position (demanding perfect clarity), but I see a cost to that position as well.
Of course, if you really want to avoid allowing the receiver to chose its response to a message, you can use other messages. So if you want to find out if an object is identical to nil you should use `nil == myObject` to ensure that there was not an override of #âisNilâ or #â==â by the objectâs class.
James
> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> My chief concern is that I am a bear of very little brain,
> and if you change the meaning of #isNil to anything at all
> other than "is the receiver identical to nil" you *WILL*
> (not may) confuse me. This extends to things that happen
> not to be inlined: if even a god-like Smalltalker like
> Andres Valloud overloads #, to something other than "combine
> the collection that is the receiver with the collection that
> is the argument to yield a new collection" than I *WILL*
> most certainly be confused and find the code unmaintainable.
> Smalltalk being Smalltalk, if you admit an inconsistent
> overload anywhere, I can no longer understand sends of that
> selector anywhere. One of the things to like about Traits
> is that you can say "this class doesn't just *happen* to
> have selectors x and y, it has them *because* it has this
> whole consistent bundle of selectors."
>
> There are more annotations documented for my Smalltalk
> compiler than are actually implemented. One that *is*
> implemented is <doNotOverride>, and it has caught more
> mistakes than I care to admit to. It's particularly
> important for a bundle of methods with varying arguments
> that are meant to be routed through a single method,
> which *is* meant to be overridden. It makes sure that
> I override the *right* method. (Take #= and #~= as an
> obvious example.)
>
> Once you start down the path of lying about things like #isNil
> you find that EITHER you have to go very far down that path
> and override #== and #instVarAt: and a whole lot of other
> things OR you are working with a semantically incoherent system.
>
> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message?"
>
> It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
> even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
> cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
> intentions, and give it what semantics you find useful.
>
> "How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?"
>
> It should answer false. Period. No ifs, buts, quibbles, or maybes.
> The whole *point* of the Null Object Pattern is to return something
> that *isn't* nil, that has quite a different protocol. If you call
> something that is supposed to return either a Foo or a NullFoo, and
> it gives you nil instead, there is a BUG in what you just called so
> the sooner you find out the better. What you want is
>
> Foo >> isNullFoo ^false
> NullFoo >> isNullFoo ^true
> and no other class defines #isNullFoo.
>
> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
> (a) you make it clear to someone reading your code what you are expecting
> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>
> I must admit that on the few occasions when I've used Null Object
> I've used an all-purpose #isMissing instead of a task-appropriate
> #isNullFoo, but then I figured out what I was doing wrong. You
> look at the code, you say "there's *something* off here, but I don't
> know what." But when you ask "what, exactly, does this method MEAN?"
> you realise "oh, THAT'S what I was doing wrong." #isMissing told me
> it was a NullPerson or a NullAddress or a NullPartsList or ... but
> in this case I needed to know whether it was a NullSummary.
>
> And of course you run into E.F.Codd's lesson: "one NULL is never
> enough, information can be missing for more than one reason".
> Take the familiar example of a phone number:
> - I know that Fred's phone number is X
> - I know that Fred has a phone but I don't know what the number is
> - I don't know whether Fred has a phone or not
> - I know that Fred has no phone
> There's room for three *different* null objects there.
> Should we have UnknownNumberOfActualPhone to answer false to #isnil
> and NonNumberOfNonexistentPhone to answer true? Or what?
>
> By the way, you may have misunderstood my benchmark.
> It wasn't that #isNil or even _ ifNotNil: speeded up by
> 10%, it was the *whole* matrix-munching benchmark that
> speeded up. Certainly not a big deal, but it's not
> something I'd be happy to give up in order to get less
> maintainable code.
>
>
>
>
>
>
>
>
> On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net <mailto:smalltalk@jgfoster.net>> wrote:
> Richard,
>
> My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
>
> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?
>
> And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>
> Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
>
> James
>
>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com <mailto:raoknz@gmail.com>> wrote:
>>
>> We're still not on the same page.
>> You seem to have some ideological objection to inlining that
>> I am completely failing to comprehend.
>> Just because a procedure call (message send) is inlined doesn't
>> in the least mean it *isn't* a procedure call (message send),
>> just as compiling a procedure call (message send) as a jump
>> (last-call optimisation) doesn't mean it *isn't* a procedure
>> call (message send).
>> By the way, forget about "40 years ago".
>> I just did an experiment in Pharo 9, and found that
>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>> -- where izNil is a non-inlined self == nil --
>> gave a 10% speedup, in a test code where real work was going
>> on as well.
>> As for turning off all inlining, what do you think that would
>> do to #ifFalse:ifTrue: and its relatives?
>>
>>
>> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com <mailto:sean@clipperadams.com>> wrote:
>>
>>
>> To start with, why do you CARE whether a particular method is inlined or not?
>>
>> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
>>
>> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>
>> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
>>
>> *or as many as practical
>>
>> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
>>
>> I agree that it is in general a smell, but long chains was tangential to the intention above
>>
>> Can you give an example?
>>
>> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
>>
>> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
>>
>> Agreed. See smell comment above.
>>
>
March 17, 2022
ANN: Linux Open Build Service new versions
by Esteban Lorenzano
Hi,
I have been preparing our OBS builds [1] for the Pharo 10 release.
We now include:
Fedora 35
Ubuntu 21.10
Debian 11
And we fixed the rolling releases:
Arch
OpenSUSE Thumbleweed
Enjoy!
Esteban
[1] https://software.opensuse.org//download.html?project=devel%3Alanguages%3Aph…
March 17, 2022
Re: Null Object Pattern
by Richard O'Keefe
My chief concern is that I am a bear of very little brain,
and if you change the meaning of #isNil to anything at all
other than "is the receiver identical to nil" you *WILL*
(not may) confuse me. This extends to things that happen
not to be inlined: if even a god-like Smalltalker like
Andres Valloud overloads #, to something other than "combine
the collection that is the receiver with the collection that
is the argument to yield a new collection" than I *WILL*
most certainly be confused and find the code unmaintainable.
Smalltalk being Smalltalk, if you admit an inconsistent
overload anywhere, I can no longer understand sends of that
selector anywhere. One of the things to like about Traits
is that you can say "this class doesn't just *happen* to
have selectors x and y, it has them *because* it has this
whole consistent bundle of selectors."
There are more annotations documented for my Smalltalk
compiler than are actually implemented. One that *is*
implemented is <doNotOverride>, and it has caught more
mistakes than I care to admit to. It's particularly
important for a bundle of methods with varying arguments
that are meant to be routed through a single method,
which *is* meant to be overridden. It makes sure that
I override the *right* method. (Take #= and #~= as an
obvious example.)
Once you start down the path of lying about things like #isNil
you find that EITHER you have to go very far down that path
and override #== and #instVarAt: and a whole lot of other
things OR you are working with a semantically incoherent system.
"How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
respond to the #âisNilâ message?"
It SHOULD NOT LIE. A proxy *isn't* nil, and it doesn't *behave* like nil,
even if it is a proxy for nil. A proxy, qua proxy, can do things that nil
cannot. Use another selector, #isEffectivelyNil, or whatever reveals your
intentions, and give it what semantics you find useful.
"How should the Null Object Pattern (
https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?"
It should answer false. Period. No ifs, buts, quibbles, or maybes.
The whole *point* of the Null Object Pattern is to return something
that *isn't* nil, that has quite a different protocol. If you call
something that is supposed to return either a Foo or a NullFoo, and
it gives you nil instead, there is a BUG in what you just called so
the sooner you find out the better. What you want is
Foo >> isNullFoo ^false
NullFoo >> isNullFoo ^true
and no other class defines #isNullFoo.
That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
(a) you make it clear to someone reading your code what you are expecting
(b) if you DON'T get what you are expecting, Smalltalk will tell you.
I must admit that on the few occasions when I've used Null Object
I've used an all-purpose #isMissing instead of a task-appropriate
#isNullFoo, but then I figured out what I was doing wrong. You
look at the code, you say "there's *something* off here, but I don't
know what." But when you ask "what, exactly, does this method MEAN?"
you realise "oh, THAT'S what I was doing wrong." #isMissing told me
it was a NullPerson or a NullAddress or a NullPartsList or ... but
in this case I needed to know whether it was a NullSummary.
And of course you run into E.F.Codd's lesson: "one NULL is never
enough, information can be missing for more than one reason".
Take the familiar example of a phone number:
- I know that Fred's phone number is X
- I know that Fred has a phone but I don't know what the number is
- I don't know whether Fred has a phone or not
- I know that Fred has no phone
There's room for three *different* null objects there.
Should we have UnknownNumberOfActualPhone to answer false to #isnil
and NonNumberOfNonexistentPhone to answer true? Or what?
By the way, you may have misunderstood my benchmark.
It wasn't that #isNil or even _ ifNotNil: speeded up by
10%, it was the *whole* matrix-munching benchmark that
speeded up. Certainly not a big deal, but it's not
something I'd be happy to give up in order to get less
maintainable code.
On Thu, 17 Mar 2022 at 18:21, James Foster <smalltalk(a)jgfoster.net> wrote:
> Richard,
>
> My _concern_ with inlining is that since it is designed to short-circuit
> dynamic method lookup, it is impossible to call a _different_
> implementation. That is, you lose the opportunity to have the _receiver_
> decide how to respond to the message. You may think of it as a message, but
> the caller is deciding how the receiver will respondâwhich largely defeats
> the purpose and role of it being a message. Yes, at the machine code level
> you are performing a branch instruction, but when comparing OOP to
> Procedural Programming we typically make a distinction between âmessagesâ
> and "procedure calls." The distinction is that the receiver gets to decide
> how to respond to a message. In C++ this is the distinction between a
> âvirtual" and "non-virtual" function. By inlining, you are converting the
> function from a virtual function to a non-virtual function, and this can
> make a difference (which is why virtual functions exist).
>
> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern) to nil
> respond to the #âisNilâ message? How should the Null Object Pattern (
> https://en.wikipedia.org/wiki/Null_object_pattern) respond to #âisNilâ?
>
> And, yes, Iâm sure you can come up with benchmarks that show a measurable
> difference, but what is the impact in realistic code? When someone asked
> about inlining #âyourselfâ in GemStone I believe I measured the performance
> as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would
> make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>
> Note that I described my position as a âconcern,â not an ideological
> objection. Mostly Iâm giving a rationale for something that doesnât seem to
> be explained very well for you. I accept that there may be a time for
> inlining, but I can âcomprehend" another side to the issue.
>
> James
>
> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> We're still not on the same page.
> You seem to have some ideological objection to inlining that
> I am completely failing to comprehend.
> Just because a procedure call (message send) is inlined doesn't
> in the least mean it *isn't* a procedure call (message send),
> just as compiling a procedure call (message send) as a jump
> (last-call optimisation) doesn't mean it *isn't* a procedure
> call (message send).
> By the way, forget about "40 years ago".
> I just did an experiment in Pharo 9, and found that
> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
> -- where izNil is a non-inlined self == nil --
> gave a 10% speedup, in a test code where real work was going
> on as well.
> As for turning off all inlining, what do you think that would
> do to #ifFalse:ifTrue: and its relatives?
>
>
> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
>
>>
>> To start with, why do you CARE whether a particular method is inlined or
>> not?
>>
>> I care because it makes âeverything is a messageâ a lie! And I suspect
>> (no proof and could be wrong) itâs an optimization that only made sense
>> with the hardware constraints of 40+ years ago. Arguing against premature
>> optimization is hardly something I just made up ;-)
>>
>> This makes absolutely no sense to me. What makes you think that the
>> combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>
>> I may have been unclear. My intent was to communicate: âIâd like to stop
>> ALL* inlining of messages by default if possibleâ
>>
>> *or as many as practical
>>
>> The thing that rings loud alarm bells for me is there being "long chains"
>> in the first place.
>>
>> I agree that it is in general a smell, but long chains was tangential to
>> the intention above
>>
>> Can you give an example?
>>
>> I donât know if I can think of one thatâs not contrived⦠Wrapping
>> something external? Squeakâs AppleScript support used to mirror the
>> underlying AS, which is pretty much exactly that.
>>
>> In my own programming, I've generally found that nils turning up in the
>> middle of a chain indicates a serious design error somewhere.
>>
>> Agreed. See smell comment above.
>>
>
>
March 17, 2022
Re: Null Object Pattern
by Kasper Osterbye
Sean
When the compiler inlines some methods, I would find it most surprising if it was turned of in half the code (or just in yours :-) ). When I am reading some code, I would rather have some consistency.
So I would just implement a whenNil: method which is a true message, and put a comment in its implementation so the next developer who comes by know why you did not just use ifNil:
Best,
Kasper
March 17, 2022
Re: Null Object Pattern
by James Foster
Richard,
My _concern_ with inlining is that since it is designed to short-circuit dynamic method lookup, it is impossible to call a _different_ implementation. That is, you lose the opportunity to have the _receiver_ decide how to respond to the message. You may think of it as a message, but the caller is deciding how the receiver will respondâwhich largely defeats the purpose and role of it being a message. Yes, at the machine code level you are performing a branch instruction, but when comparing OOP to Procedural Programming we typically make a distinction between âmessagesâ and "procedure calls." The distinction is that the receiver gets to decide how to respond to a message. In C++ this is the distinction between a âvirtual" and "non-virtual" function. By inlining, you are converting the function from a virtual function to a non-virtual function, and this can make a difference (which is why virtual functions exist).
How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the #âisNilâ message? How should the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #âisNilâ?
And, yes, Iâm sure you can come up with benchmarks that show a measurable difference, but what is the impact in realistic code? When someone asked about inlining #âyourselfâ in GemStone I believe I measured the performance as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
Note that I described my position as a âconcern,â not an ideological objection. Mostly Iâm giving a rationale for something that doesnât seem to be explained very well for you. I accept that there may be a time for inlining, but I can âcomprehend" another side to the issue.
James
> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <raoknz(a)gmail.com> wrote:
>
> We're still not on the same page.
> You seem to have some ideological objection to inlining that
> I am completely failing to comprehend.
> Just because a procedure call (message send) is inlined doesn't
> in the least mean it *isn't* a procedure call (message send),
> just as compiling a procedure call (message send) as a jump
> (last-call optimisation) doesn't mean it *isn't* a procedure
> call (message send).
> By the way, forget about "40 years ago".
> I just did an experiment in Pharo 9, and found that
> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
> -- where izNil is a non-inlined self == nil --
> gave a 10% speedup, in a test code where real work was going
> on as well.
> As for turning off all inlining, what do you think that would
> do to #ifFalse:ifTrue: and its relatives?
>
>
> On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com <mailto:sean@clipperadams.com>> wrote:
>
>
> To start with, why do you CARE whether a particular method is inlined or not?
>
> I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
>
> This makes absolutely no sense to me. What makes you think that the combination "_ isNil ifFalse: [_]" will NOT be inlined?
>
> I may have been unclear. My intent was to communicate: âIâd like to stop ALL* inlining of messages by default if possibleâ
>
> *or as many as practical
>
> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
>
> I agree that it is in general a smell, but long chains was tangential to the intention above
>
> Can you give an example?
>
> I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
>
> In my own programming, I've generally found that nils turning up in the middle of a chain indicates a serious design error somewhere.
>
> Agreed. See smell comment above.
>
March 17, 2022
Re: Null Object Pattern
by Richard O'Keefe
We're still not on the same page.
You seem to have some ideological objection to inlining that
I am completely failing to comprehend.
Just because a procedure call (message send) is inlined doesn't
in the least mean it *isn't* a procedure call (message send),
just as compiling a procedure call (message send) as a jump
(last-call optimisation) doesn't mean it *isn't* a procedure
call (message send).
By the way, forget about "40 years ago".
I just did an experiment in Pharo 9, and found that
using "_ ifNotNil: " instead of "_ izNil ifFalse: "
-- where izNil is a non-inlined self == nil --
gave a 10% speedup, in a test code where real work was going
on as well.
As for turning off all inlining, what do you think that would
do to #ifFalse:ifTrue: and its relatives?
On Thu, 17 Mar 2022 at 08:34, <sean(a)clipperadams.com> wrote:
>
> To start with, why do you CARE whether a particular method is inlined or
> not?
>
> I care because it makes âeverything is a messageâ a lie! And I suspect (no
> proof and could be wrong) itâs an optimization that only made sense with
> the hardware constraints of 40+ years ago. Arguing against premature
> optimization is hardly something I just made up ;-)
>
> This makes absolutely no sense to me. What makes you think that the
> combination "_ isNil ifFalse: [_]" will NOT be inlined?
>
> I may have been unclear. My intent was to communicate: âIâd like to stop
> ALL* inlining of messages by default if possibleâ
>
> *or as many as practical
>
> The thing that rings loud alarm bells for me is there being "long chains"
> in the first place.
>
> I agree that it is in general a smell, but long chains was tangential to
> the intention above
>
> Can you give an example?
>
> I donât know if I can think of one thatâs not contrived⦠Wrapping
> something external? Squeakâs AppleScript support used to mirror the
> underlying AS, which is pretty much exactly that.
>
> In my own programming, I've generally found that nils turning up in the
> middle of a chain indicates a serious design error somewhere.
>
> Agreed. See smell comment above.
>
March 17, 2022
Re: Pharo VM Release - v9.0.13
by Russ Whaley
Congratulations! And thanks!!
On Wed, Mar 16, 2022 at 6:24 AM tesonep(a)gmail.com <tesonep(a)gmail.com> wrote:
> Hello,
> I have released a new version of the Pharo VM for Pharo 9 and Pharo 10.
> This VM is accessible right now from Zero-Conf, updating it in the Pharo
> Launcher or using the usual downloads (as described in pharo.org/download
> ).
>
> This version includes a series of bug fixes.
>
> Changelog:
>
> - Correct handling OOB (Out of Band Data) in Window
> - Blocking signals while signalling semaphores to avoid deadlocks caused
> by signal handlers
> - Make MAXHOSTNAMELEN at least 256: improving resolution of names in Linux
> - Improving VM Simulator Machine debugger
> - Integrating Processor Simulator for RISCV
> - Using a new SDL2 version built for OSX Mojave compatibility
>
> Thanks a lot, and any doubt please let me know.
> Cheers,
>
> Pablo on behalf of the whole Pharo team.
>
>
> --
> Pablo Tesone.
> tesonep(a)gmail.com
>
--
Russ Whaley
whaley.russ(a)gmail.com
March 17, 2022
Re: Null Object Pattern
by Bernardo Ezequiel Contreras
it's impossible to talk about a project that i don't understand.
this sentence
*In the second code especially, the problem is that `position` could be
many types that are not in the same hierarchy,*
draw my attention, because i did many hierarchies when you don't need to
do it. just use polymorphic messages, objects that have the same protocol.
In that case they don't need to be in the same hierarchy. HTH.
On Wed, Mar 16, 2022 at 4:42 PM <sean(a)clipperadams.com> wrote:
> if you are using the null object pattern then you should not write those
> checks (ifNil:ifNotNil:, isNil, isNotNil). you should send the message to
> an instance of the null object and that object should decide what to do.
> just an opinion.
>
> I agree as a general rule, but it can get complicated, especially when
> crossing library boundaries. Once one uses a null object, no one anywhere
> can use those messages. This might, for example, make experimentation,
> refactoring and porting harder.
>
> At the risk of further distracting the conversation from the question of
> inlining, I was having lots of trouble applying the idea you mentioned to
> this (low level hack):
>
> self transcriptable
>
> ifNil: [
>
> self notify: 'Transcript subject not found'
>
> "We want this to be resumable because maybe e.g. the model just hasn't
> been loaded yet" ]
>
> ifNotNil: [
>
> "This is inside the guard because to get the line, we need a subject"
>
> self line ifNil: [
>
> "Brand new snippet"
>
> self initializeLine.
>
> ^ self ] ].
>
> And this:
>
> self snippet line position ifNotNil: [ :position |
>
> self firePlayerRequest: [ :player | player currentPosition: position ] ]
>
> In the second code especially, the problem is that `position` could be
> many types that are not in the same hierarchy, so to send a message to the
> null object instead probably means further polluting Object for the
> non-null case.
>
--
Bernardo E.C.
Sent from a cheap desktop computer in South America.
March 17, 2022
Re: Null Object Pattern
by Pierre Misse Chanabier
On 3/16/2022 8:33 PM, sean(a)clipperadams.com wrote:
> I care because it makes âeverything is a messageâ a lie! And I suspect
> (no proof and could be wrong) itâs an optimization that only made
> sense with the hardware constraints of 40+ years ago. Arguing against
> premature optimization is hardly something I just made up ;-)
When I read that, I remember that programming languages are a category
of software that cannot run fast enough.
So they still make sense more often than not.
Moreover the few messages that are inlined (or optimized in general) are
heavily used in the core of Pharo.
Also, the quote that you're citing, from Donald Knuth, is often if not
always used incompletely.
I could try to justify it, but I've learned that Scott Meyers is better
at explaining things than i'll ever be [1] =)
Also, I have been overriding core messages that are optimized (#ifTrue
and variant. ifNil and variant and many more) without any problem from
the compiler, so I have had no need to disable this inlining.
Regardless, you should be able to remove all inlining, it's a matter of
tweaking the compiler.
However the compiler is one thing that I have touched very little in the
system.
Pierre
 [1] https://www.youtube.com/watch?v=3WBaY61c9sE
March 16, 2022
Re: Null Object Pattern
by sean@clipperadams.com
> if you are using the null object pattern then you should not write those
> checks (ifNil:ifNotNil:, isNil, isNotNil). you should send the message to
> an instance of the null object and that object should decide what to do.
> just an opinion.
I agree as a general rule, but it can get complicated, especially when crossing library boundaries. Once one uses a null object, no one anywhere can use those messages. This might, for example, make experimentation, refactoring and porting harder.
At the risk of further distracting the conversation from the question of inlining, I was having lots of trouble applying the idea you mentioned to this (low level hack):
self transcriptable
ifNil: \[
self notify: 'Transcript subject not found'
"We want this to be resumable because maybe e.g. the model just hasn't been loaded yet" \]
ifNotNil: \[
"This is inside the guard because to get the line, we need a subject"
self line ifNil: \[
"Brand new snippet"
self initializeLine.
^ self \] \].
And this:
self snippet line position ifNotNil: \[ :position |
self firePlayerRequest: \[ :player | player currentPosition: position \] \]
In the second code especially, the problem is that \`position\` could be many types that are not in the same hierarchy, so to send a message to the null object instead probably means further polluting Object for the non-null case.
March 16, 2022
Re: Null Object Pattern
by sean@clipperadams.com
> To start with, why do you CARE whether a particular
> method is inlined or not?
I care because it makes âeverything is a messageâ a lie! And I suspect (no proof and could be wrong) itâs an optimization that only made sense with the hardware constraints of 40+ years ago. Arguing against premature optimization is hardly something I just made up ;-)
> This makes absolutely no sense to me. What makes you think that the
> combination "_ isNil ifFalse: \[_\]" will NOT be inlined?
I may have been unclear. My intent was to communicate: âIâd like to stop ALL\* inlining of messages by default if possibleâ
\*or as many as practical
> The thing that rings loud alarm bells for me is there being "long chains" in the first place.
I agree that it is in general a smell, but long chains was tangential to the intention above
> Can you give an example?
I donât know if I can think of one thatâs not contrived⦠Wrapping something external? Squeakâs AppleScript support used to mirror the underlying AS, which is pretty much exactly that.
> In my own programming, I've generally found that nils turning up in the
> middle of a chain indicates a serious design error somewhere.
Agreed. See smell comment above.
March 16, 2022
Re: [Pharo-dev] Pharo VM Release - v9.0.13
by Arturo Zambrano
Congratulations on the release :-)
On Wed, Mar 16, 2022 at 11:24 AM tesonep(a)gmail.com <tesonep(a)gmail.com>
wrote:
> Hello,
> I have released a new version of the Pharo VM for Pharo 9 and Pharo 10.
> This VM is accessible right now from Zero-Conf, updating it in the Pharo
> Launcher or using the usual downloads (as described in pharo.org/download
> ).
>
> This version includes a series of bug fixes.
>
> Changelog:
>
> - Correct handling OOB (Out of Band Data) in Window
> - Blocking signals while signalling semaphores to avoid deadlocks caused
> by signal handlers
> - Make MAXHOSTNAMELEN at least 256: improving resolution of names in Linux
> - Improving VM Simulator Machine debugger
> - Integrating Processor Simulator for RISCV
> - Using a new SDL2 version built for OSX Mojave compatibility
>
> Thanks a lot, and any doubt please let me know.
> Cheers,
>
> Pablo on behalf of the whole Pharo team.
>
>
> --
> Pablo Tesone.
> tesonep(a)gmail.com
>
--
Arturo Zambrano
LinkedIn: https://www.linkedin.com/in/arturozambrano/
March 16, 2022
Pharo VM Release - v9.0.13
by tesonep@gmail.com
Hello,
I have released a new version of the Pharo VM for Pharo 9 and Pharo 10.
This VM is accessible right now from Zero-Conf, updating it in the Pharo
Launcher or using the usual downloads (as described in pharo.org/download)
This version includes a series of bug fixes.
Changelog:
- Correct handling OOB (Out of Band Data) in Window
- Blocking signals while signalling semaphores to avoid deadlocks caused by
signal handlers
- Make MAXHOSTNAMELEN at least 256: improving resolution of names in Linux
- Improving VM Simulator Machine debugger
- Integrating Processor Simulator for RISCV
- Using a new SDL2 version built for OSX Mojave compatibility
Thanks a lot, and any doubt please let me know.
Cheers,
Pablo on behalf of the whole Pharo team.
--
Pablo Tesone.
tesonep(a)gmail.com
March 16, 2022
Re: BlockClosure folding
by Richard O'Keefe
Pattern? I'd call it an antipattern myself.
Note that we can already construct
{ block1
. block2
. block3
}
and write
{ block1
. block2
. block3
} allSatisfy: [:each | each value].
so we don't have to abuse the #, selector
or write a single new method to get the "flattened"
structure you're after.
Collection
methods for: 'collections of blocks'
allSatisfied
^self allSatisfy: [:each | each value]
anySatisfied
^self anySatisfy: [:each | each value]
noneSatisfied
^self noneSatisfy: [:each | each value]
if you do feel like adding a few methods, whereupon
{ block1
. block2
. block3
} allSatisfied
Didn't VW recently implement {} syntax natively?
Or was that VAST?
In all seriousness, when is it better to use
ComplexCondition than to rewrite?
On Wed, 16 Mar 2022 at 14:38, Hernán Morales Durand <
hernan.morales(a)gmail.com> wrote:
> This is an interesting pattern.
> Thank you for sharing.
>
> Hernán
>
> El mar, 15 mar 2022 a las 4:43, Julián Maestri (<serpi90(a)gmail.com>)
> escribió:
>
>> Not satisfying the equality, but you can use polymorphism.
>>
>> Block >> , aBlock
>> ^ BlockCompositor andAll: OrderedCollection with: self with: aBlock
>>
>> BlockCompositor >> #, aBlock
>> conditions add: aBlock.
>>
>> BlockCompositor >> value: anObject
>> ^ conditions allSatisfy: [:e | e value: anObject ]
>>
>> I don't really like the name BlockCompositor, but can't think of a better
>> name at the moment.
>>
>> You could also implement logic for #or: using #+ and: #anySatisfy: for
>> example, but need to safeguard against mixing both conditions.
>>
>> On Mon, 14 Mar 2022 at 22:29, Hernán Morales Durand <
>> hernan.morales(a)gmail.com> wrote:
>>
>>> I think I saw a coding pattern a while ago that allows you to do the
>>> following:
>>>
>>> cond1 , cond2 , cond3 , cond4
>>>
>>> And providing a kind of folding selector condition #and: you would get:
>>>
>>> [ cond1 and: [ cond2 and: [ cond3 and: [ cond4 ] ] ] ].
>>>
>>> for example:
>>>
>>> conditions := [ : each | each firstName = 'Boca' ] ,
>>> [ : each | each lastName = 'Baret' ] ,
>>> [ : each | each fullName = 'Virgasia' ].
>>>
>>> such that the following assert is met:
>>>
>>> self assert: conditions equals: [ : each | each firstName = 'Boca' and:
>>> [ each lastName = 'Baret' and: [ each fullName = 'Virgasia' ] ] ].
>>>
>>> Any ideas or pointers?
>>>
>>> Cheers,
>>>
>>> Hernán
>>>
>>>
March 16, 2022