2012/12/31 Frank Shearar frank.shearar@gmail.com:
On 31 December 2012 10:04, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
2012/12/31 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2012/12/31 Frank Shearar frank.shearar@gmail.com:
On 31 December 2012 05:13, Casey Ransberger casey.obrien.r@gmail.com 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 Yoshiki.Ohshima@acm.org wrote:
On Sun, Dec 30, 2012 at 7:40 AM, Bert Freudenberg bert@freudenbergs.de wrote: > On 2012-12-27, at 01:32, Sebastian Nozzi sebnozzi@gmail.com 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