binary selectors ambiguity and space

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

Re: binary selectors ambiguity and space

Hans-Martin Mosner
Duncan Mak wrote:

> On 5/17/06, Hans-Martin Mosner <[hidden email]> wrote:
>
>>
>> The first is easy, but in my opinion does not add much value - "aNumber
>> next" does not help me understand the code better than "aNumber + 1"
>> does. And of course, it re-uses a selector which is already used in the
>> stream hierarchy and means something completely different.
>
>
> I agree the name might not be the best. I think in  Ruby, they have
> 'succ'.

Yup, succ (or successor) would be more natural. Still it is no great
advantage over aNumber+1 IMO :-)

>
>> The second one is not possible with Smalltalk's semantics. Messages are
>> sent to objects, not to variables. So whatever message you send to
>> variable x, it can't cause x to point to another object (with the
>> exception of #become: but that's a special case). Since numeric objects
>> are immutable, you need to have the assignment x := x+1 either
>> implicitly or explicitly somewhere.
>
>
> I was thinking of using become: to implement something like this, yeah.

But that would get you into trouble. First, become: is not applicable to
immediate objects. And second, it would change all slots pointing to
that object.
You might try this (I'm using floating point numbers because they can be
used with become:):
| a b |
a := Float pi.
b := a.
a become: 3.0.
b printString

>
>> I'd like to know concrete use cases where you would prefer an increment
>> method over an explicit x := x+1. My gut feeling is that such cases
>> probably could be handled even better by still other constructs (for
>> example, collections or streams), but of course this can't be said
>> generally for all cases.
>
>
> I think you're probably right, but still I think having a particular
> message send for 'increment' is not a bad idea in general. I think
> something like this is most often used when implementing some sort of
> counter.
>
> It is true that
>
>    names select: [:each | each startsWith: 'a'] size
>
> is more elegant than something like:
>
>    names do: [:each | each startsWith: 'a' ifTrue: [count := count + 1]
>
> but what if you want to count multiple conditions in a single iteration?

First think about which code is more readable:
  namesBeginningWithA := (names select: [:each | each startsWith: 'a'])
size.
  namesBeginningWithZ := (names select: [:each | each startsWith: 'z'])
size.
or
  namesBeginningWithA := Counter new.
  namesBeginningWithZ := Counter new.
  names do: [:each |
    (each startsWith: 'a') ifTrue: [namesBeginningWithA increment].
    (each startsWith: 'z') ifTrue: [namesBeginningWithZ increment].
  ]
?
Iterating is pretty cheap.
And if you worry about performance, you still can optimize later. For
example, you could implement a class Categorizer and use it like that:
  categorizer := Categorizer new.
  categorizer justCountElements; allowDuplicates.
  categorizer
    category: 'namesBeginningWithA' predicate: [:obj | obj startsWith: 'a'];
    category: 'namesBeginningWithZ' predicate: [:obj | obj startsWith: 'z'].
  categorizer categorizeAll: names.
  categorizer categories
Granted, this code is even larger than the second example above, and
maybe it's even less readable. That's what you get when I invent
something off the top of my head. Some further study would probably come
up with a much more elegant solution.

Cheers,
Hans-Martin

Reply | Threaded
Open this post in threaded view
|

Re: binary selectors ambiguity and space

timrowledge
In reply to this post by Duncan Mak-2

On 17-May-06, at 9:36 AM, Duncan Mak wrote:


>
> I was thinking of using become: to implement something like this,  
> yeah.
You can't do that. Smallintegers cannot be become:'d. Other numbers  
shouldn't be. A number is a number - a manifest object that is what  
it is.  You *cannot* increment a number. There is nothing you can do  
to '3' to make it anything but '3'.

I fear you're still stuck in the C rape-and-pillage mindset where you  
get to plunder memory locations and have your wicked way with them  
like some rampaging Assyrian horde-member. It just isn't how  
Smalltalk works, so try to put that aside.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Fractured Idiom:- RESPONDEZ S'IL VOUS PLAID - Honk if you're Scots



Reply | Threaded
Open this post in threaded view
|

Re: binary selectors ambiguity and space

Dan Ingalls
In reply to this post by Hans-Martin Mosner
>Duncan Mak wrote:
>>I have always wondered why the standard image doesn't come with a next method and an increment method for Integers, where next would answer x + 1 and increment would set x to be x + 1.

and Hans-Martin Mosner <[hidden email]> replied...
>The first is easy, but in my opinion does not add much value - "aNumber next" does not help me understand the code better than "aNumber + 1" does. And of course, it re-uses a selector which is already used in the stream hierarchy and means something completely different.
>
>The second one is not possible with Smalltalk's semantics. Messages are sent to objects, not to variables. So whatever message you send to variable x, it can't cause x to point to another object (with the exception of #become: but that's a special case). Since numeric objects are immutable, you need to have the assignment x := x+1 either implicitly or explicitly somewhere.
>
>I'd like to know concrete use cases where you would prefer an increment method over an explicit x := x+1. My gut feeling is that such cases probably could be handled even better by still other constructs (for example, collections or streams), but of course this can't be said generally for all cases.

We have several times contemplated a Smalltalk with the completely complementary point of view about integers - namely that the system is built around accumulator objects - mutable holders of raw integer values. If you follow this through, it has significant benefits:

1.  You get a homogeneous address space - no more tag bits to check for SmallInts.

2.  The format and range of integers is the same as C and native code.

3.  Patterns like "i increment" can be wicked fast because the receiver knows the type,
        can use a native increment instruction, and can use the native overflow
        test to check bounds.

4.  The extension to Floats has similar benefits, plus
        iterative code need not create tons of little objects for intermediate values
                (ie (0.0 to: 10000 by: 0.01) do: [] would not create a million Floats

Of course literals would use read-only subclasses of these objects.

I post this just because it's fun to think about and share such alternate approaches.  In spite of these attractive characteristics, I like the functional composition of immutable objects as the basic model to teach and work with, and I think the average newbie is a bit more ready for integers than accumulators.

        - Dan

Reply | Threaded
Open this post in threaded view
|

Re: binary selectors ambiguity and space

johnmci
In reply to this post by timrowledge
Likely it's constructive to use the source, er Tim, so lets consider  
what + really does...

foo := 1 +  2  compiled results in bytecodes

5 <76> pushConstant: 1
6 <77> pushConstant: 2
7 <B0> send: +
8 <68> popIntoTemp: 0

For other forms it would be pushOops, pushOops,  + and popIntoSomething.

The bytecode prim is on Interpreter>>
bytecodePrimAdd

"normally you think we would invoke the message send, but that is  
slow, we want to avoid that if we are dealing with special cases, like
SmallIntegers or Floats,
We grab the two values off the stack then see if both are integers,  
if so we
add them together, then see if the result is still a SmallInteger, if  
so  we pop the stack and push the result, and process the next byte  
code, we are done.
If one or more of the parms are not SmallIntegers we attempt to do a  
floating point add, which loads the values as Double Float or  
converts from
SmallInteger to Double Float. If that fails we end up scheduling a  
proper message send of '+' to the receiver.

Note how we at the end pop the 2 values off the stack then push the  
result onto the stack, then after bytecode finishs the top item on  
the stack is
the value we store somewhere, like back into an instance variable,  
class variable, temporary slot...

        | rcvr arg result |
        rcvr := self internalStackValue: 1.
        arg := self internalStackValue: 0.
        (self areIntegers: rcvr and: arg)
                ifTrue: [result := (self integerValueOf: rcvr) + (self  
integerValueOf: arg).
                                (self isIntegerValue: result) ifTrue:
                                        [self internalPop: 2 thenPush: (self integerObjectOf: result).
                                        ^ self fetchNextBytecode "success"]]
                ifFalse: [successFlag := true.
                                self externalizeIPandSP.
                                self primitiveFloatAdd: rcvr toArg: arg.
                                self internalizeIPandSP.
                                successFlag ifTrue: [^ self fetchNextBytecode "success"]].

        messageSelector := self specialSelector: 0.
        argumentCount := 1.
        self normalSend

Optimizations.

A few years back I considered what if they are large integers in the  
range of +- 2 billion and the result was a 32  bit integer, could we  
load as 32bit integers, do the math and store a smallInteger result  
or convert to largeInteger? I did write some code for that, but it  
was deemed a bit too specialized and really what application would  
need it?


On 17-May-06, at 11:34 AM, tim Rowledge wrote:

>
> On 17-May-06, at 9:36 AM, Duncan Mak wrote:
>
>
>>
>> I was thinking of using become: to implement something like this,  
>> yeah.
> You can't do that. Smallintegers cannot be become:'d. Other numbers  
> shouldn't be. A number is a number - a manifest object that is what  
> it is.  You *cannot* increment a number. There is nothing you can  
> do to '3' to make it anything but '3'.
>
> I fear you're still stuck in the C rape-and-pillage mindset where  
> you get to plunder memory locations and have your wicked way with  
> them like some rampaging Assyrian horde-member. It just isn't how  
> Smalltalk works, so try to put that aside.
>
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Fractured Idiom:- RESPONDEZ S'IL VOUS PLAID - Honk if you're Scots
>
>
>

--
========================================================================
===
John M. McIntosh <[hidden email]> 1-800-477-2659
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===


Reply | Threaded
Open this post in threaded view
|

Re: binary selectors ambiguity and space

Wolfgang Helbig-2
In reply to this post by Nicolas Cellier-3
Dear List,

please find my resume of this thread at

        http://www.ba-stuttgart.de/~helbig/st80/Grammar.txt
       
Thank you all for the insights I've got while discussing with you about  
Smalltalk.

Greetings,
Wolfgang
--
Weniger, aber besser.


123