Re: [Newbies] Two questions about Smalltalk language design

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

Re: [Newbies] Two questions about Smalltalk language design

Yoshiki Ohshima-3
There are more knowledgeable people around here, but here is my take:

On Wed, Dec 26, 2012 at 4:32 PM, Sebastian Nozzi <[hidden email]> wrote:

> Hello Smalltalkers,
>
> I was interacting the other day with an user in a Scala mailing list,
> and he had some questions about Smalltalk. From his FP (functional
> programming) point of view there were some things that looked strange.
> I tried to reply to the best of my ability, but still I don't really
> know the background for these design decisions. So I come to you, real
> experts, hoping for some answers.
>
> The questions were:
>
> 1) Why do ST methods return "self" if nothing is explicitly returned?
> (he would have expected something like "Unit" in Scala, or "Void" -
> which I know makes little sense in a world like ST's, so I didn't
> include this in the Stackoverflow question)
>
> http://stackoverflow.com/questions/14047887/why-do-methods-return-self-by-default-in-smalltalk

>From the language design POV, it's certainly better than simply
returning the value from the last expression in the method.  If it
returns the last value in the expression: the following method would
return the result from #doSomething; but to know what kind of object
would be returned from it, you need to recursively look into many
methods.

method1: var1
    var1 doSomething.

Why not return something along the line of nil is.... It certainly is
more useful to be able to chain messages for simple setters.

> 2) In Collections, why does "add:" return the object being added, and
> not "self"?
>
> http://stackoverflow.com/questions/14047940/why-does-add-return-the-object-added-in-smalltalk-collections

Smalltalk-72's "vector" had that semantics more or less, when
assigning a new value to a slot.  Check out "to vector" in
http://ftp.squeak.org/goodies/Smalltalk-72/ALLDEFS

I can see some reason for that semantics:

One perhaps was that because assignment was just a message send to a
quoted variable, and you can define its behavior based on the
receiver.  When the receiver is a quoted vector, your assignment can
update a slot of it. In many languages (not in Scheme however), the
value of the assignment is the value to be assigned so you can say:

x := y := 0.

So, it is convenient to make the value of such message to be the value
to be assigned.

Another is that it certainly is convenient to get back the removed
element when you are removing an element from a collection.  Making
add: do the same makes it more symmetric.

--
-- Yoshiki

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Yoshiki Ohshima-3
On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>
>> Why do ST methods return "self" if nothing is explicitly returned?
>
>
> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>
> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.

I thought of it (when I wrote the reply) but isn't this really the
argument for returning self instead of nil for example?  Any message
send pops all arguments including the receiver and pushes the return
value so "self" is not on the stack.  Typical byte code sequence for a
method that returns self is popping the last result and ends the
sequence with "returnSelf"; so it should be equally efficient if such
a method endsWIth "returnNil", if such bytecode exists?

--
-- Yoshiki

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Chris Muller-3
In reply to this post by Yoshiki Ohshima-3
>> 2) In Collections, why does "add:" return the object being added, and
>> not "self"?
>>
>> http://stackoverflow.com/questions/14047940/why-does-add-return-the-object-added-in-smalltalk-collections
>
> Smalltalk-72's "vector" had that semantics more or less, when
> assigning a new value to a slot.  Check out "to vector" in
> http://ftp.squeak.org/goodies/Smalltalk-72/ALLDEFS
>
> I can see some reason for that semantics:
>
> One perhaps was that because assignment was just a message send to a
> quoted variable, and you can define its behavior based on the
> receiver.  When the receiver is a quoted vector, your assignment can
> update a slot of it. In many languages (not in Scheme however), the
> value of the assignment is the value to be assigned so you can say:
>
> x := y := 0.
>
> So, it is convenient to make the value of such message to be the value
> to be assigned.
>
> Another is that it certainly is convenient to get back the removed
> element when you are removing an element from a collection.  Making
> add: do the same makes it more symmetric.

Those are my thoughts about that exactly!  Nice to see someone else
appreciate add:/remove: answering the argument besides myself.   :)

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Casey Ransberger-2
In reply to this post by Yoshiki Ohshima-3
Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.

Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)

Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.

On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:

> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>
>>> Why do ST methods return "self" if nothing is explicitly returned?
>>
>>
>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>
>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>
> I thought of it (when I wrote the reply) but isn't this really the
> argument for returning self instead of nil for example?  Any message
> send pops all arguments including the receiver and pushes the return
> value so "self" is not on the stack.  Typical byte code sequence for a
> method that returns self is popping the last result and ends the
> sequence with "returnSelf"; so it should be equally efficient if such
> a method endsWIth "returnNil", if such bytecode exists?
>
> --
> -- Yoshiki
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Frank Shearar-3
On 31 December 2012 05:13, Casey Ransberger <[hidden email]> wrote:
> Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
>
> Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)

The problem with nil as a sentinel is that it's not sufficiently
different from the other things in one's collection. I recall the
troubles people had trying to store nils in a Set (which used nil for
some special purpose). But there's a trivial way to get a really true
blue unique sentinel: sentinel := Object new.

> Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.

Certainly, if you didn't return self by default you'd lose the trivial
cascading. (Look at the hoops others have to jump through to get their
"fluent" APIs.)

Given my particular interest in the intersection between the
techniques of functional and OO programming I rarely use "return self
by default". I instead get tripped up by forgetting to use a ^ on the
last statement. But I'm not going to suggest we change the return-self
behaviour :)

frank

> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:
>
>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>>
>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>
>>>
>>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>>
>>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>>
>> I thought of it (when I wrote the reply) but isn't this really the
>> argument for returning self instead of nil for example?  Any message
>> send pops all arguments including the receiver and pushes the return
>> value so "self" is not on the stack.  Typical byte code sequence for a
>> method that returns self is popping the last result and ends the
>> sequence with "returnSelf"; so it should be equally efficient if such
>> a method endsWIth "returnNil", if such bytecode exists?
>>
>> --
>> -- Yoshiki
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Nicolas Cellier
2012/12/31 Frank Shearar <[hidden email]>:

> On 31 December 2012 05:13, Casey Ransberger <[hidden email]> wrote:
>> Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
>>
>> Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)
>
> The problem with nil as a sentinel is that it's not sufficiently
> different from the other things in one's collection. I recall the
> troubles people had trying to store nils in a Set (which used nil for
> some special purpose). But there's a trivial way to get a really true
> blue unique sentinel: sentinel := Object new.
>
>> Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.
>
> Certainly, if you didn't return self by default you'd lose the trivial
> cascading. (Look at the hoops others have to jump through to get their
> "fluent" APIs.)
>
> Given my particular interest in the intersection between the
> techniques of functional and OO programming I rarely use "return self
> by default". I instead get tripped up by forgetting to use a ^ on the
> last statement. But I'm not going to suggest we change the return-self
> behaviour :)
>
> frank
>

An argument for NOT returning the result of last statement is that it
would more than often expose internal state of the object to the
outside (in the case you sent last message to an instance variable).

Nicolas

>> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:
>>
>>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>>>
>>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>>
>>>>
>>>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>>>
>>>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>>>
>>> I thought of it (when I wrote the reply) but isn't this really the
>>> argument for returning self instead of nil for example?  Any message
>>> send pops all arguments including the receiver and pushes the return
>>> value so "self" is not on the stack.  Typical byte code sequence for a
>>> method that returns self is popping the last result and ends the
>>> sequence with "returnSelf"; so it should be equally efficient if such
>>> a method endsWIth "returnNil", if such bytecode exists?
>>>
>>> --
>>> -- Yoshiki
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Nicolas Cellier
2012/12/31 Nicolas Cellier <[hidden email]>:

> 2012/12/31 Frank Shearar <[hidden email]>:
>> On 31 December 2012 05:13, Casey Ransberger <[hidden email]> wrote:
>>> Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
>>>
>>> Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)
>>
>> The problem with nil as a sentinel is that it's not sufficiently
>> different from the other things in one's collection. I recall the
>> troubles people had trying to store nils in a Set (which used nil for
>> some special purpose). But there's a trivial way to get a really true
>> blue unique sentinel: sentinel := Object new.
>>
>>> Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.
>>
>> Certainly, if you didn't return self by default you'd lose the trivial
>> cascading. (Look at the hoops others have to jump through to get their
>> "fluent" APIs.)
>>
>> Given my particular interest in the intersection between the
>> techniques of functional and OO programming I rarely use "return self
>> by default". I instead get tripped up by forgetting to use a ^ on the
>> last statement. But I'm not going to suggest we change the return-self
>> behaviour :)
>>
>> frank
>>
>
> An argument for NOT returning the result of last statement is that it
> would more than often expose internal state of the object to the
> outside (in the case you sent last message to an instance variable).
>
> Nicolas
>

Or, from an other point of view, that means that Smalltalk is more
imperative tan functional...

Nicolas

>>> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:
>>>
>>>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>>>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>>>>
>>>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>>>
>>>>>
>>>>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>>>>
>>>>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>>>>
>>>> I thought of it (when I wrote the reply) but isn't this really the
>>>> argument for returning self instead of nil for example?  Any message
>>>> send pops all arguments including the receiver and pushes the return
>>>> value so "self" is not on the stack.  Typical byte code sequence for a
>>>> method that returns self is popping the last result and ends the
>>>> sequence with "returnSelf"; so it should be equally efficient if such
>>>> a method endsWIth "returnNil", if such bytecode exists?
>>>>
>>>> --
>>>> -- Yoshiki
>>>>
>>>
>>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Frank Shearar-3
On 31 December 2012 10:04, Nicolas Cellier
<[hidden email]> wrote:

> 2012/12/31 Nicolas Cellier <[hidden email]>:
>> 2012/12/31 Frank Shearar <[hidden email]>:
>>> On 31 December 2012 05:13, Casey Ransberger <[hidden email]> wrote:
>>>> Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
>>>>
>>>> Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)
>>>
>>> The problem with nil as a sentinel is that it's not sufficiently
>>> different from the other things in one's collection. I recall the
>>> troubles people had trying to store nils in a Set (which used nil for
>>> some special purpose). But there's a trivial way to get a really true
>>> blue unique sentinel: sentinel := Object new.
>>>
>>>> Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.
>>>
>>> Certainly, if you didn't return self by default you'd lose the trivial
>>> cascading. (Look at the hoops others have to jump through to get their
>>> "fluent" APIs.)
>>>
>>> Given my particular interest in the intersection between the
>>> techniques of functional and OO programming I rarely use "return self
>>> by default". I instead get tripped up by forgetting to use a ^ on the
>>> last statement. But I'm not going to suggest we change the return-self
>>> behaviour :)
>>>
>>> frank
>>>
>>
>> An argument for NOT returning the result of last statement is that it
>> would more than often expose internal state of the object to the
>> outside (in the case you sent last message to an instance variable).
>>
>> Nicolas
>>
>
> Or, from an other point of view, that means that Smalltalk is more
> imperative tan functional...

Well, I don't know about that. Certainly many of the standard APIs are
imperative (like remove: returning the deleted element rather than a
new collection with the element removed). But for instance, how about
"there's no distinction between a statement and an expression", which
is a pretty Functional (tm) feature.

frank

> Nicolas
>
>>>> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:
>>>>
>>>>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>>>>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>>>>>
>>>>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>>>>
>>>>>>
>>>>>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>>>>>
>>>>>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>>>>>
>>>>> I thought of it (when I wrote the reply) but isn't this really the
>>>>> argument for returning self instead of nil for example?  Any message
>>>>> send pops all arguments including the receiver and pushes the return
>>>>> value so "self" is not on the stack.  Typical byte code sequence for a
>>>>> method that returns self is popping the last result and ends the
>>>>> sequence with "returnSelf"; so it should be equally efficient if such
>>>>> a method endsWIth "returnNil", if such bytecode exists?
>>>>>
>>>>> --
>>>>> -- Yoshiki
>>>>>
>>>>
>>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Nicolas Cellier
2012/12/31 Frank Shearar <[hidden email]>:

> On 31 December 2012 10:04, Nicolas Cellier
> <[hidden email]> wrote:
>> 2012/12/31 Nicolas Cellier <[hidden email]>:
>>> 2012/12/31 Frank Shearar <[hidden email]>:
>>>> On 31 December 2012 05:13, Casey Ransberger <[hidden email]> wrote:
>>>>> Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
>>>>>
>>>>> Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)
>>>>
>>>> The problem with nil as a sentinel is that it's not sufficiently
>>>> different from the other things in one's collection. I recall the
>>>> troubles people had trying to store nils in a Set (which used nil for
>>>> some special purpose). But there's a trivial way to get a really true
>>>> blue unique sentinel: sentinel := Object new.
>>>>
>>>>> Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.
>>>>
>>>> Certainly, if you didn't return self by default you'd lose the trivial
>>>> cascading. (Look at the hoops others have to jump through to get their
>>>> "fluent" APIs.)
>>>>
>>>> Given my particular interest in the intersection between the
>>>> techniques of functional and OO programming I rarely use "return self
>>>> by default". I instead get tripped up by forgetting to use a ^ on the
>>>> last statement. But I'm not going to suggest we change the return-self
>>>> behaviour :)
>>>>
>>>> frank
>>>>
>>>
>>> An argument for NOT returning the result of last statement is that it
>>> would more than often expose internal state of the object to the
>>> outside (in the case you sent last message to an instance variable).
>>>
>>> Nicolas
>>>
>>
>> Or, from an other point of view, that means that Smalltalk is more
>> imperative tan functional...
>
> Well, I don't know about that. Certainly many of the standard APIs are
> imperative (like remove: returning the deleted element rather than a
> new collection with the element removed). But for instance, how about
> "there's no distinction between a statement and an expression", which
> is a pretty Functional (tm) feature.
>
> frank
>

Certainly, one of imperative language with most functional features...
I played with these snippets:

(SystemNavigation default allMethodsSelect: [:e |
        | scanner |
        scanner := InstructionStream on: e.
        scanner scanFor: [:byte | byte = 120]]) size.
-> 21944

(SystemNavigation default allMethodsSelect: [:e |
        | scanner |
        scanner := InstructionStream on: e.
        scanner scanFor: [:byte | (byte between: 121 and: 124)]]) size.
-> 23668

Byte code 120 does return the receiver, 121 true, 12 false, 123 nil,
124 stack top, 125 is for block local return.
So above snippets means that roughly 50% of methods return the receiver (self).

The snippet is not perfect, because some methods return both self and
another object
(SystemNavigation default allMethodsSelect: [:e |
        | scanner |
        scanner := InstructionStream on: e.
        (scanner scanFor: [:byte | (byte between: 121 and: 124)])
                and: [scanner scanFor: [:byte | byte = 120]]]) size.
-> 1478

Also, it does not cover all methods
(SystemNavigation default allMethodsSelect: [:e |  true]) size.
-> 47547

The 3627 simple method that just return an Object (a literal or an
instance variable) were not caught by the InstructionStream
SystemNavigation default browseAllSelect: [:e |
        | scanner |
        scanner := InstructionStream on: e.
        (scanner scanFor: [:byte | (byte between: 120 and: 124)]) not].

Nicolas

>> Nicolas
>>
>>>>> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:
>>>>>
>>>>>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>>>>>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>>>>>>
>>>>>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>>>>>
>>>>>>>
>>>>>>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>>>>>>
>>>>>>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>>>>>>
>>>>>> I thought of it (when I wrote the reply) but isn't this really the
>>>>>> argument for returning self instead of nil for example?  Any message
>>>>>> send pops all arguments including the receiver and pushes the return
>>>>>> value so "self" is not on the stack.  Typical byte code sequence for a
>>>>>> method that returns self is popping the last result and ends the
>>>>>> sequence with "returnSelf"; so it should be equally efficient if such
>>>>>> a method endsWIth "returnNil", if such bytecode exists?
>>>>>>
>>>>>> --
>>>>>> -- Yoshiki
>>>>>>
>>>>>
>>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Hannes Hirzel
Thank you, Nicolas, for these instructive code snippets and Happy New Year 2013

--Hannes

On 12/31/12, Nicolas Cellier <[hidden email]> wrote:

> 2012/12/31 Frank Shearar <[hidden email]>:
>> On 31 December 2012 10:04, Nicolas Cellier
>> <[hidden email]> wrote:
>>> 2012/12/31 Nicolas Cellier <[hidden email]>:
>>>> 2012/12/31 Frank Shearar <[hidden email]>:
>>>>> On 31 December 2012 05:13, Casey Ransberger <[hidden email]>
>>>>> wrote:
>>>>>> Worth pointing out (at least I *think*) there's little real value in
>>>>>> returning nil by default, even though it makes a certain amount of
>>>>>> visceral sense.
>>>>>>
>>>>>> Why would I return nil? Maybe as a sentinel value for something (often
>>>>>> I prefer nil to zero for that when there's a nil concept and I want a
>>>>>> sentinel.)
>>>>>
>>>>> The problem with nil as a sentinel is that it's not sufficiently
>>>>> different from the other things in one's collection. I recall the
>>>>> troubles people had trying to store nils in a Set (which used nil for
>>>>> some special purpose). But there's a trivial way to get a really true
>>>>> blue unique sentinel: sentinel := Object new.
>>>>>
>>>>>> Likewise, there's an argument for returning the last value of a method
>>>>>> (like we do with blocks presently, and Self does everywhere) across
>>>>>> the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics
>>>>>> had a lot of time to evolve. The advantages to answering self by
>>>>>> default have stood the test of time in this context, I think:) though
>>>>>> that certainly doesn't mean we shouldn't continue to ask questions and
>>>>>> look for a better idea.
>>>>>
>>>>> Certainly, if you didn't return self by default you'd lose the trivial
>>>>> cascading. (Look at the hoops others have to jump through to get their
>>>>> "fluent" APIs.)
>>>>>
>>>>> Given my particular interest in the intersection between the
>>>>> techniques of functional and OO programming I rarely use "return self
>>>>> by default". I instead get tripped up by forgetting to use a ^ on the
>>>>> last statement. But I'm not going to suggest we change the return-self
>>>>> behaviour :)
>>>>>
>>>>> frank
>>>>>
>>>>
>>>> An argument for NOT returning the result of last statement is that it
>>>> would more than often expose internal state of the object to the
>>>> outside (in the case you sent last message to an instance variable).
>>>>
>>>> Nicolas
>>>>
>>>
>>> Or, from an other point of view, that means that Smalltalk is more
>>> imperative tan functional...
>>
>> Well, I don't know about that. Certainly many of the standard APIs are
>> imperative (like remove: returning the deleted element rather than a
>> new collection with the element removed). But for instance, how about
>> "there's no distinction between a statement and an expression", which
>> is a pretty Functional (tm) feature.
>>
>> frank
>>
>
> Certainly, one of imperative language with most functional features...
> I played with these snippets:
>
> (SystemNavigation default allMethodsSelect: [:e |
> | scanner |
> scanner := InstructionStream on: e.
> scanner scanFor: [:byte | byte = 120]]) size.
> -> 21944
>
> (SystemNavigation default allMethodsSelect: [:e |
> | scanner |
> scanner := InstructionStream on: e.
> scanner scanFor: [:byte | (byte between: 121 and: 124)]]) size.
> -> 23668
>
> Byte code 120 does return the receiver, 121 true, 12 false, 123 nil,
> 124 stack top, 125 is for block local return.
> So above snippets means that roughly 50% of methods return the receiver
> (self).
>
> The snippet is not perfect, because some methods return both self and
> another object
> (SystemNavigation default allMethodsSelect: [:e |
> | scanner |
> scanner := InstructionStream on: e.
> (scanner scanFor: [:byte | (byte between: 121 and: 124)])
> and: [scanner scanFor: [:byte | byte = 120]]]) size.
> -> 1478
>
> Also, it does not cover all methods
> (SystemNavigation default allMethodsSelect: [:e |  true]) size.
> -> 47547
>
> The 3627 simple method that just return an Object (a literal or an
> instance variable) were not caught by the InstructionStream
> SystemNavigation default browseAllSelect: [:e |
> | scanner |
> scanner := InstructionStream on: e.
> (scanner scanFor: [:byte | (byte between: 120 and: 124)]) not].
>
> Nicolas
>
>>> Nicolas
>>>
>>>>>> On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima
>>>>>> <[hidden email]> wrote:
>>>>>>
>>>>>>> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg
>>>>>>> <[hidden email]> wrote:
>>>>>>>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Why do ST methods return "self" if nothing is explicitly returned?
>>>>>>>>
>>>>>>>>
>>>>>>>> One very simple reason has not been stated yet: In the Virtual
>>>>>>>> Machine, returning self is simpler and more efficient than returning
>>>>>>>> any other object.
>>>>>>>>
>>>>>>>> Smalltalk byte codes implement a stack machine. That means arguments
>>>>>>>> are passed by pushing them onto a stack, rather than putting them
>>>>>>>> into registers. In addition to the arguments as listed in the method
>>>>>>>> signature, a hidden argument is always passed, which is the receiver
>>>>>>>> of the message. So even for unary methods (those without arguments)
>>>>>>>> the receiver is pushed onto the stack, then the method is executed,
>>>>>>>> and the receiver value on the stack is how the method knows "self".
>>>>>>>> By returning "self" if no explicit return statement is given, the VM
>>>>>>>> can just leave the "self" oop on the stack, which saves at least one
>>>>>>>> memory store operation. So from an efficiency and simplicity
>>>>>>>> standpoint, returning "self" is the most elegant thing to do.
>>>>>>>
>>>>>>> I thought of it (when I wrote the reply) but isn't this really the
>>>>>>> argument for returning self instead of nil for example?  Any message
>>>>>>> send pops all arguments including the receiver and pushes the return
>>>>>>> value so "self" is not on the stack.  Typical byte code sequence for
>>>>>>> a
>>>>>>> method that returns self is popping the last result and ends the
>>>>>>> sequence with "returnSelf"; so it should be equally efficient if
>>>>>>> such
>>>>>>> a method endsWIth "returnNil", if such bytecode exists?
>>>>>>>
>>>>>>> --
>>>>>>> -- Yoshiki
>>>>>>>
>>>>>>
>>>>>
>>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Eliot Miranda-2
In reply to this post by Casey Ransberger-2



On Sun, Dec 30, 2012 at 9:13 PM, Casey Ransberger <[hidden email]> wrote:
Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.

turns out in a distributed systems context nil is far cheaper to return; no minting of a proxy for the result.  That's a specialized use.  But answering nil when there's no result has a safety aspect, i that it guards somewhat against using the return value when its not intended (nil has some protocol).



Why would I return nil? Maybe as a sentinel value for something (often I prefer nil to zero for that when there's a nil concept and I want a sentinel.)

Likewise, there's an argument for returning the last value of a method (like we do with blocks presently, and Self does everywhere) across the board, like e.g. Ruby does, but I'd note: Smalltalk's semantics had a lot of time to evolve. The advantages to answering self by default have stood the test of time in this context, I think:) though that certainly doesn't mean we shouldn't continue to ask questions and look for a better idea.

On Dec 30, 2012, at 11:39 AM, Yoshiki Ohshima <[hidden email]> wrote:

> On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg <[hidden email]> wrote:
>> On 2012-12-27, at 01:32, Sebastian Nozzi <[hidden email]> wrote:
>>
>>> Why do ST methods return "self" if nothing is explicitly returned?
>>
>>
>> One very simple reason has not been stated yet: In the Virtual Machine, returning self is simpler and more efficient than returning any other object.
>>
>> Smalltalk byte codes implement a stack machine. That means arguments are passed by pushing them onto a stack, rather than putting them into registers. In addition to the arguments as listed in the method signature, a hidden argument is always passed, which is the receiver of the message. So even for unary methods (those without arguments) the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is how the method knows "self". By returning "self" if no explicit return statement is given, the VM can just leave the "self" oop on the stack, which saves at least one memory store operation. So from an efficiency and simplicity standpoint, returning "self" is the most elegant thing to do.
>
> I thought of it (when I wrote the reply) but isn't this really the
> argument for returning self instead of nil for example?  Any message
> send pops all arguments including the receiver and pushes the return
> value so "self" is not on the stack.  Typical byte code sequence for a
> method that returns self is popping the last result and ends the
> sequence with "returnSelf"; so it should be equally efficient if such
> a method endsWIth "returnNil", if such bytecode exists?
>
> --
> -- Yoshiki
>




--
best,
Eliot


Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Igor Stasenko
On 3 January 2013 03:56, Eliot Miranda <[hidden email]> wrote:

>
>
>
> On Sun, Dec 30, 2012 at 9:13 PM, Casey Ransberger <[hidden email]>
> wrote:
>>
>> Worth pointing out (at least I *think*) there's little real value in
>> returning nil by default, even though it makes a certain amount of visceral
>> sense.
>
>
> turns out in a distributed systems context nil is far cheaper to return; no
> minting of a proxy for the result.  That's a specialized use.  But answering
> nil when there's no result has a safety aspect, i that it guards somewhat
> against using the return value when its not intended (nil has some
> protocol).
>

I was also thinking that way before i found that in distributed systems
nil is no longer a singleton:
- suppose i extended Object class with some method, lets say #foo.
- then my user code sends some remote message to some arbitrary object
in a system with such extension,
which evaluates answer to nil
- and then i sending #foo message to result.

now if you substitute remote nil with own nil, you will get DNU, because remote
system nil can understand that message, but local is not.

But in case of return self, this is actually works much better: the
communication layer can check that
message answer is same as a receiver (using identity check), and then,
indeed, it can
do a shortcut and tell the remote sender system that it
can reuse the same proxy (which it used for sending a message) for
further operations.

--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Andreas.Raab
In reply to this post by Casey Ransberger-2
Casey Ransberger-2 wrote
Worth pointing out (at least I *think*) there's little real value in returning nil by default, even though it makes a certain amount of visceral sense.
There are two major reasons why returning nil by default makes sense:
* It is consistent with what people see when looking at the code, i.e., if a method doesn't return anything visibly it shouldn't silently do something completely different. This makes the language easier to learn since there are fewer special cases to know about.
* It prevents implicitly leaking authority. This of course is only relevant for people who care about security aspects but in this case returning self is really the wrong choice (so is evaluating the last statement of blocks to be the block return value; block return should be explicit too).

Cheers,
  - Andreas
Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Andreas.Raab
In reply to this post by Igor Stasenko
Igor Stasenko wrote
On 3 January 2013 03:56, Eliot Miranda <[hidden email]> wrote:
>
> turns out in a distributed systems context nil is far cheaper to return; no
> minting of a proxy for the result.  That's a specialized use.  But answering
> nil when there's no result has a safety aspect, i that it guards somewhat
> against using the return value when its not intended (nil has some
> protocol).
>

I was also thinking that way before i found that in distributed systems
nil is no longer a singleton:
- suppose i extended Object class with some method, lets say #foo.
- then my user code sends some remote message to some arbitrary object
in a system with such extension,
which evaluates answer to nil
- and then i sending #foo message to result.

now if you substitute remote nil with own nil, you will get DNU, because remote
system nil can understand that message, but local is not.

But in case of return self, this is actually works much better: the
communication layer can check that
message answer is same as a receiver (using identity check), and then,
indeed, it can
do a shortcut and tell the remote sender system that it
can reuse the same proxy (which it used for sending a message) for
further operations.
But in general, the problem lies in delegation. As long as you return the receiver of the message the return is simple. But if the receiver delegates to another object along the lines of:

doSomethingWithFoo: arg
    "Do something with my ivar foo and the argument"
    ^foo doSomethingWith: arg

then the implicit return of self from foo will cause you to create excess proxies. Much better to return nil. You can still proxy nil as a "real object" if you really want to treat remote nil different from local nil (although I've never found a situation where this proved useful).

One real-world example of how implicit returns negatively affect distributed systems, we found that in Croquet, the implicit return from blocks would create a ton of garbage promises that were never used. For example, if one were to write:

  foo ifNotNil:[foo future yourself].

this would create a (completely useless) promise for the future as it would be referred to as the result from the block. We changed this so that futures that were the last statement of a block return nil and do not create a promise (and nobody ever complained :-)

Also, note that the problem would be compounded if the return would require a network round-trip too (in Croquet it doesn't); in this case you pay for the promise and for proxying an implicit self return from some completely uninteresting object that nobody will look at afterwards.

The negative effects of implicit returns are definitely noticable in distributed systems when you're trying to utilize proxies efficiently. Knowing when (not) to create a proxy and when (not) to return an object is a major help in making the system efficient.

Cheers,
  - Andreas
Reply | Threaded
Open this post in threaded view
|

Re: [Newbies] Two questions about Smalltalk language design

Stefan Marr-3
In reply to this post by Andreas.Raab
Hi:

On 03 Jan 2013, at 13:37, Andreas.Raab wrote:

> * It prevents implicitly leaking authority. This of course is only relevant
> for people who care about security aspects but in this case returning self
> is really the wrong choice (so is evaluating the last statement of blocks to
> be the block return value; block return should be explicit too).

Then you would need second kind of return operator to distinguish between value returns and non-local returns from methods, no?

Just curious.

Best regards
Stefan


--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525