[Pharo-users] Re: Null Object Pattern

2022-03-21 Thread Esteban Maringolo
Being able to proxy to another object is such an important feature,
that even in ES6 (aka "Javascript") there is a Proxy object [1] that
allows you to intercept/redefine operations for that object.

In the case of Smalltalk, and coming back to the original topic of
this thread, that is even more powerful because you have first class
messages that can be resolved via DNU handling. If anything, I would
like to give the receiver of a message more control of the handling of
such a message rather than having a DNU as the last resort, or worse,
some messages that are written to be sent, but then are inlined during
execution.

Regards,

[1] 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Esteban A. Maringolo

On Mon, Mar 21, 2022 at 5:47 PM Tim Mackinnon  wrote:
>
> This has been an interesting thread to read on the side, and I appreciate the 
> thought provoking conversion.
>
> On Sun, 20 Mar 2022, at 6:11 AM, Richard O'Keefe wrote:
>
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?
>
>
> However I am confused by the above - as in Pharo and Dolphin (and I suspect 
> other Smalltalks) - you don't have to make your proxy a subclass of Object 
> right? If you want to forward as much behaviour as possible - you can 
> subclass ProtoObject (or equivalent). The width of methods on that is much 
> reduced (59 from a quick glance), and loading other packages doesn't tend to 
> extend at that level, so keeping things much more stable. The downside, is 
> that such objects are tricky to view in an inspector etc.  There is a mocking 
> framework in Pharo called Ghost that leverages this quite well from memory.
>
> So I think that some of the side arguments on downsides might not be quite as 
> bad as indicated.
>
> Tim
>
>


[Pharo-users] Re: Null Object Pattern

2022-03-21 Thread Tim Mackinnon
This has been an interesting thread to read on the side, and I appreciate the 
thought provoking conversion.

On Sun, 20 Mar 2022, at 6:11 AM, Richard O'Keefe wrote:
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?

However I am confused by the above - as in Pharo and Dolphin (and I suspect 
other Smalltalks) - you don't have to make your proxy a subclass of Object 
right? If you want to forward as much behaviour as possible - you can subclass 
ProtoObject (or equivalent). The width of methods on that is much reduced (59 
from a quick glance), and loading other packages doesn't tend to extend at that 
level, so keeping things much more stable. The downside, is that such objects 
are tricky to view in an inspector etc.  There is a mocking framework in Pharo 
called Ghost that leverages this quite well from memory.

So I think that some of the side arguments on downsides might not be quite as 
bad as indicated.

Tim



[Pharo-users] Re: Null Object Pattern

2022-03-21 Thread James Foster
Richard,

My primary reference for the Proxy Pattern is the classic "Design Patterns, 
Elements of Reusable Object-Oriented Software" by Gamma, Helm, Johnson, and 
Vlissides (Addison-Wesley 1995). In describing how to implement the pattern the 
“Gang of Four (or GOF)" advise “using doesNotUnderstand in Smalltalk” (p. 212). 
Furthermore, as to typing, they say that “Proxy doesn’t always have to know the 
type of real subject” (213). 

The GOF anticipated the problem with inlined selectors and caution that “a few 
special messages ... are handled directly by the virtual machine [and] do not 
cause the usual method look-up” (p. 212). So, I think it is reasonable, in the 
context of a discussion of the Proxy Pattern, to suggest that the Proxy Pattern 
would be more effective with fewer inlined selectors.

As to where the Proxy Pattern was developed, the GOF describe “Known Uses” 
including remote objects in NEXTSTEP (1994) and in Smalltalk (1987). In the 
remote object context, a Proxy has no need to know the type of the target, it 
just needs to know how to forward messages and return results. While there is 
typically a way to find out if something is a proxy or not (e.g., #’_isProxy’) 
the beauty of the Proxy Pattern is that you don’t have to rewrite the entire 
application and use something like #’apparentClass’ or #’apparentlyNil’. Only 
the parts of the application that care if you have a proxy (which will 
typically not be the main domain code) need to look more deeply (with special 
selectors or reflection).

It appears that you believe that a untyped proxy to a remote object is bad and 
that all the code in an application should be written to be aware of the 
possible “remoteness” of certain objects. It is my understanding that a 
transparent untyped proxy to a remote object is well-accepted, extremely 
useful, and can be implemented reliably. 

I don’t think I can contribute much more to the conversation than that so I’ll 
leave it there.

Regards,

James

> On Mar 20, 2022, at 4:55 PM, Richard O'Keefe  wrote:
> 
> Never forget that the Proxy pattern was developed in the context of a TYPED 
> programming
> language.  So "Clients can't tell whether they work with a subject or its 
> proxy” means WITH REFERENCE
> TO A STATED PROTOCOL.  Doing this in Ada or Java is fine, because you define 
> an interface type, and that
> makes it safe.  Here is a sentence from a typical description of the pattern: 
> "Since the proxy implements the 
> INTERFACE as the original class, it can be passed to any client that expects 
> a real service object."  Having
> a specified and *enforced* smallish interface prevents the maintenance issues 
> that plague attempts to use
> this pattern in Smalltalk.
> 
> Remote objects and local objects have different semantics because remote 
> messages and local messages
> have different semantics.  Local messages cannot be lost, duplicated, or 
> reordered, nor can communication
> with a local object drop out for no local reason.  Version skew is a much 
> bigger problem with distributed
> systems than local ones, so once again, it is proxying WITH REFERENCE TO A 
> STATED PROTOCOL (and
> that not a large one!) that counts.  There is no such thing as a 100% 
> transparent remote proxy.  So it is
> very useful to know what an object really is as well as what it pretends to 
> be.  That is,
>   #class#apparentClass
>   #isNil #apparentlyNil
> are *different*,
> 
> So the argument thus far is
> - a selector should not be inlined if it might need to be overridden
> - such as in an application of the Proxy pattern
> - but well-designed Proxies are such WITH REFERENCE TO STATED PROTOCOLS
> - meaning that selectors that are NOT in such protocols are fair game for 
> inlining.
> 



[Pharo-users] Re: Null Object Pattern

2022-03-20 Thread Richard O'Keefe
Never forget that the Proxy pattern was developed in the context of a TYPED
programming
language.  So "Clients can't tell whether they work with a subject or its
proxy” means WITH REFERENCE
TO A STATED PROTOCOL.  Doing this in Ada or Java is fine, because you
define an interface type, and that
makes it safe.  Here is a sentence from a typical description of the
pattern: "Since the proxy implements the
INTERFACE as the original class, it can be passed to any client that
expects a real service object."  Having
a specified and *enforced* smallish interface prevents the maintenance
issues that plague attempts to use
this pattern in Smalltalk.

Remote objects and local objects have different semantics because remote
messages and local messages
have different semantics.  Local messages cannot be lost, duplicated, or
reordered, nor can communication
with a local object drop out for no local reason.  Version skew is a much
bigger problem with distributed
systems than local ones, so once again, it is proxying WITH REFERENCE TO A
STATED PROTOCOL (and
that not a large one!) that counts.  There is no such thing as a 100%
transparent remote proxy.  So it is
very useful to know what an object really is as well as what it pretends to
be.  That is,
  #class#apparentClass
  #isNil #apparentlyNil
are *different*,

So the argument thus far is
- a selector should not be inlined if it might need to be overridden
- such as in an application of the Proxy pattern
- but well-designed Proxies are such WITH REFERENCE TO STATED PROTOCOLS
- meaning that selectors that are NOT in such protocols are fair game for
inlining.


[Pharo-users] Re: Null Object Pattern

2022-03-20 Thread James Foster
Hello Richard,

> What part of … is hard to understand?

Did you mean for this to come off as condescending? Or are you are honestly 
wondering how effectively you are communicating? In either case, all of it is 
hard for me to understand since it doesn’t describe the Proxy Pattern which 
requires that "Clients can't tell whether they work with a subject or its 
proxy” (https://en.wikipedia.org/wiki/Proxy_pattern 
). My understanding of a proxy is 
that it will rarely/never happen that "there will be *more* selectors you 
needed to think about but didn’t." So, far from being (an instance of) the 
problem, an override of #’doesNotUnderstand:’ is the elegant solution.

> I wanted something that was like an OrderedCollection but could only hold 
> elements of a specific class.

It seems what you want is not a Proxy but a Facade 
(https://en.wikipedia.org/wiki/Facade_pattern 
) in which you "may perform 
additional functionality [such as type checking] before ... forwarding a 
request” (https://en.wikipedia.org/wiki/Facade_pattern 
). 

> I *could* make a proxy by going through #doesNotUnderstand: but I am not 
> going to.

That’s fine, and a proxy is probably inappropriate for the things you do. But 
there are a few usage scenarios 
 where 
they are appropriate. My primary experience with them is with distributed 
object communication 
 where they are 
appropriate.

> I *could* make a batch of ricin and store it in my granddaughter's bedroom, 
> but I'm not going to.

I’m glad to hear it. To take a more realistic example, I could try to fly a 747 
but I’m not going to (since my commercial pilot’s license doesn’t include that 
rating). That doesn’t mean that no one should fly a 747 (or implement a 
Proxy—the people who make GemBuilder for Smalltalk 
 should certainly use proxies). I 
remember hearing a joke about Kent Beck holding a sign saying “Will override 
#doesNotUnderstand: for food”! I took it as not saying that only a genius can 
understand DNU but that you should think carefully about how it will be used 
(and in many cases something else would be appropriate). Everything else about 
Kent Beck’s work makes it clear that leaving behind clear maintainable code is 
a top priority.

James

> On Mar 19, 2022, at 11:11 PM, Richard O'Keefe  wrote:
> 
> An override of #doesNotUnderstand: *is* (an instance of) the problem.
> What part of "you may think you know what to forward now, but just
> wait a couple of months or install an additional package and there
> will be *more* selectors you needed to think about but didn't" is
> hard to understand?
> 
> Proxies done right are proxies *relative to a specified protocol*.
> 
> Let me give you a personal example.
> I wanted something that was like an OrderedCollection but
> could only hold elements of a specific class.
> No worries, just make a proxy.  Make a bare-bones object,
> define all the #add... methods to check their argument,
> and use #doesNotUnderstand to forward everything else to
> the underlying OrderedCollection.
> 
> The first problem is the selectors that the bare-bones
> object *does* understand by virtue of being an object.
> (Remember there are *hundreds* of these selectors in
> Squeak, Pharo, VisualWorks, even in gst there are more
> than 120).  You must, for example, ensure that #instVarAt:
> is forwarded, not handled locally, BUT you must also
> ensure that #instVarAt:put: is handled locally, not forwarded.
> And then one day you find that your program has broken,
> because mutable collections now have
>   aMutableCollection inPlaceCollect: collectBlock
> and that can put unacceptable results in the collection
> *without* going through any #add... method.  
> 
> Eventually you realise "handing out a wrapper for this
> collection constrained to only allow adding certain things"
> is the wrong way to do it, and you do something like
> 
> constrainedAdder: constraint
>   ^[:x | (constraint value: x)
>ifTrue:  [self add: x]
>ifFalse: [DomainError receiver: self selector: #add:]]
> 
> or you do something else entirely, like handing out a wrapper with
> a *narrow* interface that doesn't make the slightest pretence of
> *being* the other object.
> 
> I *could* make a batch of ricin and store it in my
> granddaughter's bedroom, but I'm not going to.
> I *could* make a proxy by going through #doesNotUnderstand:
> but I am not going to.  That would be a textbook example of
> maxim 38: "Just because it's easy for you doesn't mean it
> can't be hard on your clients."
> 
> 
> 
> 
> 
> 
> On Sun, 20 Mar 2022 at 15:18, James Foster  > wrote:
> I don’t understand. Wouldn’t an 

[Pharo-users] Re: Null Object Pattern

2022-03-20 Thread Richard O'Keefe
An override of #doesNotUnderstand: *is* (an instance of) the problem.
What part of "you may think you know what to forward now, but just
wait a couple of months or install an additional package and there
will be *more* selectors you needed to think about but didn't" is
hard to understand?

Proxies done right are proxies *relative to a specified protocol*.

Let me give you a personal example.
I wanted something that was like an OrderedCollection but
could only hold elements of a specific class.
No worries, just make a proxy.  Make a bare-bones object,
define all the #add... methods to check their argument,
and use #doesNotUnderstand to forward everything else to
the underlying OrderedCollection.

The first problem is the selectors that the bare-bones
object *does* understand by virtue of being an object.
(Remember there are *hundreds* of these selectors in
Squeak, Pharo, VisualWorks, even in gst there are more
than 120).  You must, for example, ensure that #instVarAt:
is forwarded, not handled locally, BUT you must also
ensure that #instVarAt:put: is handled locally, not forwarded.
And then one day you find that your program has broken,
because mutable collections now have
  aMutableCollection inPlaceCollect: collectBlock
and that can put unacceptable results in the collection
*without* going through any #add... method.

Eventually you realise "handing out a wrapper for this
collection constrained to only allow adding certain things"
is the wrong way to do it, and you do something like

constrainedAdder: constraint
  ^[:x | (constraint value: x)
   ifTrue:  [self add: x]
   ifFalse: [DomainError receiver: self selector: #add:]]

or you do something else entirely, like handing out a wrapper with
a *narrow* interface that doesn't make the slightest pretence of
*being* the other object.

I *could* make a batch of ricin and store it in my
granddaughter's bedroom, but I'm not going to.
I *could* make a proxy by going through #doesNotUnderstand:
but I am not going to.  That would be a textbook example of
maxim 38: "Just because it's easy for you doesn't mean it
can't be hard on your clients."






On Sun, 20 Mar 2022 at 15:18, James Foster  wrote:

> I don’t understand. Wouldn’t an override of #'doesNotUnderstand:’ solve
> this problem? The proxies I’ve seen subclass from nil or ProtoObject and
> forward almost everything to the target. It’s really very easy.
>
> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe  wrote:
>
> An object should be a Proxy or Stub only with reference to a specific
> protocol, which should be kept narrow.
>
> Being a Proxy is a form of coupling.  Proxying a wide
> interface creates maintenance problems:
> Squeak 5.3 : Object selectors size => 485
> Pharo 9.0  : Object selectors size => 435
> astc   : Object selectors size => 325
> VW 8.3PUL  : Object selectors size => 304
>
> The interface of Object is HUGE.  You want to bet that
> your Proxy got *all* of the methods right?  This
> interface didn't get that way all at once; it grew.
> The number was 78 in Smalltalk-80.  At a minimum, then,
> Smalltalk systems have accreted one extra Object method
> every two months.
>
> So you set up your proxy to *flawlesly* mirror Object,
> and then, WHOOPS, upgrade Smalltalk and now there is a
> method that Object has and your Proxy either lacks (if
> it descends from ProtoObject but not Object) or inherits
> an inappropriate version of (if it descends from Object).
>
> What this means is that nobody ever *does* flawlessly
> mock everything in the public interface of an object
> they are Proxying.  They proxy a *limited* protocol.
> Because that is all they *can* do.
>
> Look, I know that people who have been trained to work
> with the stuff can use C4 as cooking fuel.  But I haven't
> had that training, so I won't touch the stuff.  In the
> same way, I dare say there are things *you* can safely
> do in Smalltalk that fumblefingers here would be burnt
> badly by.  There are many things that *can* be done that
> I *won't* do.  In a chemistry lab, I would not work with
> ClF3 let alone O2F2.  In Smalltalk, I don't monkey with
> #isNil.
>
> On Fri, 18 Mar 2022 at 03:52, James Foster  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 

[Pharo-users] Re: Null Object Pattern

2022-03-19 Thread James Foster
I don’t understand. Wouldn’t an override of #'doesNotUnderstand:’ solve this 
problem? The proxies I’ve seen subclass from nil or ProtoObject and forward 
almost everything to the target. It’s really very easy.

> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe  wrote:
> 
> An object should be a Proxy or Stub only with reference to a specific 
> protocol, which should be kept narrow.
> 
> Being a Proxy is a form of coupling.  Proxying a wide
> interface creates maintenance problems:
> Squeak 5.3 : Object selectors size => 485
> Pharo 9.0  : Object selectors size => 435
> astc   : Object selectors size => 325
> VW 8.3PUL  : Object selectors size => 304
> 
> The interface of Object is HUGE.  You want to bet that
> your Proxy got *all* of the methods right?  This
> interface didn't get that way all at once; it grew.
> The number was 78 in Smalltalk-80.  At a minimum, then,
> Smalltalk systems have accreted one extra Object method
> every two months.
> 
> So you set up your proxy to *flawlesly* mirror Object,
> and then, WHOOPS, upgrade Smalltalk and now there is a
> method that Object has and your Proxy either lacks (if
> it descends from ProtoObject but not Object) or inherits
> an inappropriate version of (if it descends from Object).
> 
> What this means is that nobody ever *does* flawlessly
> mock everything in the public interface of an object
> they are Proxying.  They proxy a *limited* protocol.
> Because that is all they *can* do.
> 
> Look, I know that people who have been trained to work
> with the stuff can use C4 as cooking fuel.  But I haven't
> had that training, so I won't touch the stuff.  In the
> same way, I dare say there are things *you* can safely
> do in Smalltalk that fumblefingers here would be burnt
> badly by.  There are many things that *can* be done that
> I *won't* do.  In a chemistry lab, I would not work with
> ClF3 let alone O2F2.  In Smalltalk, I don't monkey with
> #isNil.
> 
> On Fri, 18 Mar 2022 at 03:52, James Foster  > 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 > > 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 , 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 
>> 

[Pharo-users] Re: Null Object Pattern

2022-03-19 Thread Richard O'Keefe
An object should be a Proxy or Stub only with reference to a specific
protocol, which should be kept narrow.

Being a Proxy is a form of coupling.  Proxying a wide
interface creates maintenance problems:
Squeak 5.3 : Object selectors size => 485
Pharo 9.0  : Object selectors size => 435
astc   : Object selectors size => 325
VW 8.3PUL  : Object selectors size => 304

The interface of Object is HUGE.  You want to bet that
your Proxy got *all* of the methods right?  This
interface didn't get that way all at once; it grew.
The number was 78 in Smalltalk-80.  At a minimum, then,
Smalltalk systems have accreted one extra Object method
every two months.

So you set up your proxy to *flawlesly* mirror Object,
and then, WHOOPS, upgrade Smalltalk and now there is a
method that Object has and your Proxy either lacks (if
it descends from ProtoObject but not Object) or inherits
an inappropriate version of (if it descends from Object).

What this means is that nobody ever *does* flawlessly
mock everything in the public interface of an object
they are Proxying.  They proxy a *limited* protocol.
Because that is all they *can* do.

Look, I know that people who have been trained to work
with the stuff can use C4 as cooking fuel.  But I haven't
had that training, so I won't touch the stuff.  In the
same way, I dare say there are things *you* can safely
do in Smalltalk that fumblefingers here would be burnt
badly by.  There are many things that *can* be done that
I *won't* do.  In a chemistry lab, I would not work with
ClF3 let alone O2F2.  In Smalltalk, I don't monkey with
#isNil.

On Fri, 18 Mar 2022 at 03:52, James Foster  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  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 , 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, 

[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread Todd Blanchard via Pharo-users



> On Mar 18, 2022, at 11:39 AM, Esteban Maringolo  wrote:
> 
> You say that Smalltalk is not so hot for system developments because
> it's extremely malleable? What are you measuring it against?

Lots of things but to keep things simple lets go with Objective C since it is 
quite similar in concept and style but the library classes are closed to 
modification without extraordinary effort (you can replace a method but you're 
gonna have to work to do it because you don't have the source code for the core 
classes).

> 
> It is still easy to break almost anything, without having to resort to
> compiler pragmas. :-)

Yeah, that's kind of my point.  I have junked a lot of images in my wake.

>> If anything, I would like to see more immutable structure in the core 
>> classes.  Add methods?  Always.   Casually override anything?  There be 
>> dragons there.
> 
> Something like  "final" classes and "const" globals or not being able
> to extend classes such as [Proto]Object?


IDK exactly.  Yeah, maybe a pragma that was part of the core library that would 
prevent an override of a key method that say, the browser, depends on.

Smalltalk is great for building things, but unlike when I build, say, a car, I 
don't have to drag around the entire factory I used to build the car behind it 
everywhere.

Toying with the idea of using one image to host remote developer tools that we 
do not change and using it to operate on a second image that has minimal dev 
tools but will be the production version of my app.  That would provide the 
separation that would keep me from destroying toolkit by accident while trying 
to tweak the app.

Just musing here.  I've become kind of dissatisfied with Pharo development of 
late.  Hard to build anything that lasts very long.


> 
> 
> 
>> 
>> On Mar 18, 2022, at 11:06 AM, s...@clipperadams.com wrote:
>> 
>> 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.
>> 
>> 


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread Esteban Maringolo
On Fri, Mar 18, 2022 at 3:24 PM Todd Blanchard via Pharo-users
 wrote:
>
> What, exactly, is inconsistent about a key message isNil being allowed to be 
> overridden?

Overrides are not the issue here.

> There is a VERY simple solution to your problem that does not involve 
> disrupting the platform.

No, it's not a simple solution.

> But you'd rather change the platform.

I'd bet that the change to inline those message sends came after the
implementation of the message sending.

> Part of the reason Smalltalk has not been the greatest platform to build 
> software on is its extreme malleability.  It is a double edged sword for 
> sure.  It is great for research.  Not so hot for actual systems development.

You say that Smalltalk is not so hot for system developments because
it's extremely malleable? What are you measuring it against?

> "The key in making great and growable systems is much more to design how its 
> modules communicate rather than what their internal properties and behaviors 
> should be. " -Alan Kay

That's exactly the point of this conversion, a user might want the
modules to communicate by means of sending messages between them,
so writes the code with that expectation and then an external thing (the
compiler) decides to do something else that involves not actually
sending the message, because it focuses on the "internal properties
and behaviors".

> The inlined methods implement key operations that I believe *should* be 
> immutable.  Because the system is implemented in terms of itself, it is not 
> very hard to completely destroy an image and render it unusable by overriding 
> the wrong message in the wrong class (try overriding #environment at the 
> class level and let me know how long before your image completely packs up 
> under a torrent of walkbacks).

It is still easy to break almost anything, without having to resort to
compiler pragmas. :-)

> If anything, I would like to see more immutable structure in the core 
> classes.  Add methods?  Always.   Casually override anything?  There be 
> dragons there.

Something like  "final" classes and "const" globals or not being able
to extend classes such as [Proto]Object?

In any case, I think the options for this inlining thing were laid on
the table, and there is a partial solution for these looking for
"semantic optimization" (as in true message sends) rather than
performance optimization (as in inlining).

Regards!

Esteban A. Maringolo



>
> On Mar 18, 2022, at 11:06 AM, s...@clipperadams.com wrote:
>
> 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.
>
>


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread Todd Blanchard via Pharo-users
What, exactly, is inconsistent about a key message isNil being allowed to be 
overridden?

There is a VERY simple solution to your problem that does not involve 
disrupting the platform.  

But you'd rather change the platform.

Part of the reason Smalltalk has not been the greatest platform to build 
software on is its extreme malleability.  It is a double edged sword for sure.  
It is great for research.  Not so hot for actual systems development.  

"The key in making great and growable systems is much more to design how its 
modules communicate rather than what their internal properties and behaviors 
should be. Think of the internet – to live, it (a) has to allow many different 
kinds of ideas and realizations that are beyond any single standard and (b) to 
allow varying degrees of safe interoperability between these ideas." -Alan Kay

The inlined methods implement key operations that I believe *should* be 
immutable.  Because the system is implemented in terms of itself, it is not 
very hard to completely destroy an image and render it unusable by overriding 
the wrong message in the wrong class (try overriding #environment at the class 
level and let me know how long before your image completely packs up under a 
torrent of walkbacks).

If anything, I would like to see more immutable structure in the core classes.  
Add methods?  Always.   Casually override anything?  There be dragons there.

> On Mar 18, 2022, at 11:06 AM, s...@clipperadams.com wrote:
> 
> 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.
> 



[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread sean
> 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.


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread Todd Blanchard via Pharo-users
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, s...@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?


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread sean
> 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?


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread sean
> 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!


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread sean
> 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!


[Pharo-users] Re: Null Object Pattern

2022-03-18 Thread Marcus Denker



> On 17 Mar 2022, at 18:00, Esteban Maringolo  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  wrote:
>> On 17 Mar 2022, at 17:17, Richard Sargent 
>>  wrote:
>> A pragma might be the way to go.
>>  for example.
>> 
>> 
>> 
>> There is already the #compilerOptions: Pragma, e.g.:
>> 
>> 
>> For example this method compiled the and: as a real send:
>> tt
>> 
>> true and: [ false ]
>> 
>> 
>> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo  
>> wrote:
> 
>>> A great trade off would be to be able
>>> to enable/disable for certain things instead of it being a global
>>> setting.


[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread 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  wrote:
> On 17 Mar 2022, at 17:17, Richard Sargent 
>  wrote:
> A pragma might be the way to go.
>  for example.
>
>
>
> There is already the #compilerOptions: Pragma, e.g.:
>
> 
> For example this method compiled the and: as a real send:
> tt
> 
> true and: [ false ]
>
>
> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo  
> wrote:

>> A great trade off would be to be able
>> to enable/disable for certain things instead of it being a global
>> setting.


[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread Marcus Denker


> On 17 Mar 2022, at 17:17, Richard Sargent 
>  wrote:
> 
> A pragma might be the way to go.
> 
>  for example.


There is already the #compilerOptions: Pragma, e.g.:




For example this method compiled the and: as a real send:


tt


true and: [ false ]

> 
> On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo  > 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  > 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  > > 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 , 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 

[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread Richard Sargent
A pragma might be the way to go.

** for example.

On Thu, Mar 17, 2022 at 8:17 AM Esteban Maringolo 
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 
> 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  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 , 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, 

[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread 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  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  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 , 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 

[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread 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  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 , 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 

[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread 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 , 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  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 

[Pharo-users] Re: Null Object Pattern

2022-03-17 Thread 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

[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread 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 
) 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  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,  > 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.
> 



[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread 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,  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.
>


[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread 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  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.


[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread Pierre Misse Chanabier

On 3/16/2022 8:33 PM, s...@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


[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread sean
> 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.


[Pharo-users] Re: Null Object Pattern

2022-03-16 Thread sean
> 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.


[Pharo-users] Re: Null Object Pattern

2022-03-15 Thread Bernardo Ezequiel Contreras
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.


On Tue, Mar 15, 2022 at 3:16 PM  wrote:

> I had some chaining that was getting too complex due to many nil checks,
> so I started to refactor using a Null Object.
>
> However, I’m struggling a bit with the refactor due to inlining. Since
> #ifNil: variants might be inlined, it seems that something like:
>
> anObject with a long chain of messages ifNotNil: [ :result | “…” ]
>
> must be changed into something like:
>
> anObject with a long chain of messages isNil ifFalse: [ anObject with a
> long chain of messages “…” ].
>
> Obviously, I can use a temp to have:
>
> result := anObject with a long chain of messages.
>
> result isNil ifFalse: [ result “…” ].
>
> But both seem ugly and make me question using this pattern.
>
>1.
>
>What am I missing?
>2.
>
>After 40+ years of Moore’s Law, can we turn off these inlines by
>default?
>
>

-- 
Bernardo E.C.

Sent from a cheap desktop computer in South America.


[Pharo-users] Re: Null Object Pattern

2022-03-15 Thread Todd Blanchard via Pharo-users
Why do you not just do something like

[ “complicated code that might fail somewhere in here” ] 
on: Error 
do: [:error | nil]

Use the on:do: exception handling to stay safe.

Result := [anObject long chain of messages that might return a nilValue ]
on: Error do: [:e | nil].

> On Mar 15, 2022, at 11:16 AM, s...@clipperadams.com wrote:
> 
> I had some chaining that was getting too complex due to many nil checks, so I 
> started to refactor using a Null Object.
> 
> However, I’m struggling a bit with the refactor due to inlining. Since 
> #ifNil: variants might be inlined, it seems that something like:
> 
> anObject with a long chain of messages ifNotNil: [ :result | “…” ]
> 
> must be changed into something like:
> 
> anObject with a long chain of messages isNil ifFalse: [ anObject with a long 
> chain of messages “…” ].
> 
> Obviously, I can use a temp to have:
> 
> result := anObject with a long chain of messages.
> 
> result isNil ifFalse: [ result “…” ].
> 
> But both seem ugly and make me question using this pattern.
> 
> What am I missing?
> 
> After 40+ years of Moore’s Law, can we turn off these inlines by default?
> 



[Pharo-users] Re: Null Object Pattern

2022-03-15 Thread Richard O'Keefe
I have a bad feeling about this.
To start with, why do you CARE whether a particular
method is inlined or not?


However, I’m struggling a bit with the refactor due to inlining. Since
#ifNil: variants might be inlined, it seems that something like:

anObject with a long chain of messages ifNotNil: [ :result | “…” ]

must be changed into something like:

anObject with a long chain of messages isNil ifFalse: [ anObject with a
long chain of messages “…” ].


This makes absolutely no sense to me.  What makes you think that the
combination "_ isNil ifFalse: [_]" will NOT be inlined?  In Squeak,
x ifNotNil: [...]
turns into x; nil; ==; jumpFalse
and
x isNil ifFalse: [...]
turns into x; send isNil; jumpFalse
where "send isNil" is a single byte.  I don't see a substantial difference
here.
(I'd have checked in Pharo, but after many interface changes I no longer
know
how to do view|bytecode.)
The thing that rings loud alarm bells for me is there being "long chains"
in the first place.

Can you give an example?

In my own programming, I've generally found that nils turning up in the
middle of a chain indicates a serious design error somewhere.

On Wed, 16 Mar 2022 at 07:16,  wrote:

> I had some chaining that was getting too complex due to many nil checks,
> so I started to refactor using a Null Object.
>
> However, I’m struggling a bit with the refactor due to inlining. Since
> #ifNil: variants might be inlined, it seems that something like:
>
> anObject with a long chain of messages ifNotNil: [ :result | “…” ]
>
> must be changed into something like:
>
> anObject with a long chain of messages isNil ifFalse: [ anObject with a
> long chain of messages “…” ].
>
> Obviously, I can use a temp to have:
>
> result := anObject with a long chain of messages.
>
> result isNil ifFalse: [ result “…” ].
>
> But both seem ugly and make me question using this pattern.
>
>1.
>
>What am I missing?
>2.
>
>After 40+ years of Moore’s Law, can we turn off these inlines by
>default?
>
>


[Pharo-users] Re: Null Object Pattern

2022-03-15 Thread Esteban Maringolo
+1

Inlining breaks the fundamental piece of OOP: Message sends.

I'm sure there are use cases where inlining adds a significant
speedup, but for some messages, I prefer them to be sent.

Regards!

Esteban A. Maringolo

On Tue, Mar 15, 2022 at 3:16 PM  wrote:
>
> I had some chaining that was getting too complex due to many nil checks, so I 
> started to refactor using a Null Object.
>
> However, I’m struggling a bit with the refactor due to inlining. Since 
> #ifNil: variants might be inlined, it seems that something like:
>
> anObject with a long chain of messages ifNotNil: [ :result | “…” ]
>
> must be changed into something like:
>
> anObject with a long chain of messages isNil ifFalse: [ anObject with a long 
> chain of messages “…” ].
>
> Obviously, I can use a temp to have:
>
> result := anObject with a long chain of messages.
>
> result isNil ifFalse: [ result “…” ].
>
> But both seem ugly and make me question using this pattern.
>
> What am I missing?
>
> After 40+ years of Moore’s Law, can we turn off these inlines by default?