How do Smalltalk disambiguate messages?

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

How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

gcotelli

The message is "at:put:".  It's a single message send.  I encourage you to try the ProfStef tutorial to understand the basis.


On Oct 16, 2016 01:17, "CodeDmitry" <[hidden email]> wrote:
I am trying to do a JavaScript experiment to make Objects behave like
Smalltalk objects.

example:

    "reminder: Smalltalk arrays start at 1."
    |arr|
    a := Array new: 1.
    a at: 1 put: 'Hello, World'.

Here, the Smalltalk array has a message "at: index put: value" which is
defined many layers of prototype chaining down, at Object in category
accessing.

However there are many messages on the way traversing the prototype chain
that start with "at:", such as(SequenceableCollection) "at: x ifAbsent: y",
"at: x incrementBy: y".

How does Smalltalk tell which message is which? Does it merge the messages
into a single message such as "at: x put: y" to "atPut(x, y)" at some point?

Without knowing this, I have to traverse the whole call chain and check
whether each argument is called in a specific way, which is incredibly
expensive. If there was a single name such as "atPut" I can easily just do a
dictionary lookup for this name and get it at O(1).

Does Smalltalk actually store each message?



--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Tudor Girba-2
Hi,

: is part of the method name. So, the method:

Dictionary>>at: key put: anObject 

has the name #'at:put:' and the object defining this method will understand a message #’at:put:’.

To better understand this, you can play with inspecting the method objects, like below:


Does this answer the question?

Cheers,
Doru

On Oct 16, 2016, at 6:44 AM, CodeDmitry <[hidden email]> wrote:

I understand that it is a single message send, but to know how to handle the
message at runtime, the parser needs to somehow determine where the
implementation of that message is. It must do a lookup based on multiple
keys(at, and put), which is really confusing. "methods" are easy to look up
because they only have one name, but messages have one name which is split
amongst each argument.

Simple concatenation does not make sense, since {at: x, put: y} and {a: x,
tput: y} are different messages.

The only way I can think of this being implemented "easily" is by storing a
table of entries {num_args, arg_names, impl_ref}, and then have the function
"send" do a linear search over this table until it finds an entry with
num_args = 2, each arg_name matching the argument name keys in order, and
then calling the impl_ref with the array of values without the names.

I'm wondering if there is a way to do this without having to loop over every
single message the object has, then every message its' parent object has,
and so on, just to find which function you actually want to call.





--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918948.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


--
www.tudorgirba.com
www.feenk.com

"We can create beautiful models in a vacuum.
But, to get them effective we have to deal with the inconvenience of reality."

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Tudor Girba-2
The value of the method name is at:put:

# denotes a Symbol, which is a subclass of String. The difference between the two is that two symbols with the same value will actually be the same object, while this is not necessarily the case with strings:

stringA := String newFrom: 'string'.
stringB := String newFrom: 'string'.
stringA == stringB
“false".

symbolA := Symbol newFrom: 'symbol'.
symbolB := Symbol newFrom: 'symbol'.
symbolA == symbolB
"true"

Cheers,
Doru


> On Oct 16, 2016, at 7:19 AM, CodeDmitry <[hidden email]> wrote:
>
> So "at: x put: y" translates to a method named #at:put:(or "at:put:")?
>
> |dict|
> dict := Dictionary new.
> dict at: 'foo' put: 'bar'.
>
> So javascript equivalent would be(assuming the Dictionary object existed).
>
> var dict;
>
> dict = new Dictionary;
> dict['at:put:']('foo', 'bar');
>
>
>
> --
> View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918951.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>

--
www.tudorgirba.com
www.feenk.com

"The coherence of a trip is given by the clearness of the goal."






Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

kilon.alios
In reply to this post by CodeDmitry
`There is no equivalent in JavaScript because Javascript does not have function calls with keyword arguments and even if it , it would still be not equivalent at least technically.

The message "at:put:" is indeed a keyword that is part of the dictionary of the object and not just a generic dictionary. So each object has its own dictionary that associates keywords to method calls. So in Smalltalk you can not access neither variables (class or instance) nor methods (class or instance) outside the object, they all are accessed through messages. This happens to hide the implementation, hence the complexity of the object. The user does not need to know how the Object works only how to use it.

The only other languages that have such an implementation are ObjC and Ruby which borrow this directly from Smalltalk. 

Also Javascript uses prototype based OOP while Snalltalk is the first language to implement class based OOP. They are similar but not the same.

On Sun, Oct 16, 2016 at 8:28 AM CodeDmitry <[hidden email]> wrote:
So "at: x put: y" translates to a method named #at:put:(or "at:put:")?

|dict|
dict := Dictionary new.
dict at: 'foo' put: 'bar'.

So javascript equivalent would be(assuming the Dictionary object existed).

var dict;

dict = new Dictionary;
dict['at:put:']('foo', 'bar');



--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918951.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

kilon.alios
"I was actually curious about this in Ruby as well, since Ruby also doesn't
have the Smalltalk message syntax. "

Actually, it does

when i said in my reply

"The only other languages that have such an implementation are ObjC and Ruby which borrow this directly from Smalltalk."

What I mean is that both ObjC and Ruby has a message based OOP system , like Smalltalk.

http://rubylearning.com/blog/2010/11/03/do-you-understand-rubys-objects-messages-and-blocks/



On Sun, Oct 16, 2016 at 11:50 AM CodeDmitry <[hidden email]> wrote:
I was actually curious about this in Ruby as well, since Ruby also doesn't
have the Smalltalk message syntax.

I figure that the magic behind it is that Smalltalk takes strings like "dict
at: 'foo' put: 'bar'" and evaluates them into a JavaScript equivalent of
"dict['at:put:']('foo', 'bar')".

Basically, my proof of concept(I cheated with regex to cut time):

'use strict';

var Dictionary = function Dictionary() {
    this.dict = {};
};
Dictionary.prototype['at:put:'] = function(index, value) {
    this.dict[index] = value;
};
Object.defineProperty(Dictionary, 'new', {
    get: function () {
        return new this;
    }
});

function st_eval(str) {
    var x = str.match(/(dict)\s+(at):\s+'(foo)'\s+(put):\s+'(bar)'/);
    var target = x[1];
    var callName = x[2] + ':' + x[4] + ':';
    var argv = [x[3], x[5]];
    var realTarget = eval(target);
    realTarget[callName].apply(realTarget, argv);
}

var dict = Dictionary.new;
console.log(dict);
//dict['at:put:']('foo', 'bar');
console.log(dict);
st_eval("dict at: 'foo' put: 'bar'");
console.log(dict);





--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918957.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

kilon.alios
Still you don't understand how Ruby syntax works. Every method call every function you see is basically a masquerade message sent. Those calls are just syntactic sugar, they don't exist, they are there to make people to feel more comfortable giving them the illusion that is a call because it looks like a call, but is all message sents.

So there is no need to do what you doing .

Ruby does not just implement message scents, it's basically Smalltalk pretending to be something else. So most of Smalltalk syntax is there.

For me it's is the ONLY language that can claim it's Smalltalk language inspired.

Messages are very hard to implement if not impossible because they required that calls don't exist or be disabled, otherwise the existence of message is pointless. And since no language I am aware of allow you to disable calls and replace them with messages , what you trying to do is pointless .

Of course to be devil's advocate here Smalltalk in vast majority uses messages as calls so there existence is kinda pointless too, risking to be burn in fire by my fellow Smalltalkers , I have only seen the power of message to be taken advantage of in the case of messageNotUnderstood be linked to doesNotUnderstand method. In every other case I have encountered the message always has the same name as the method, which defeats the purpose of the message in the first place. This is also the default behavior of the IDE.
On Sun, 16 Oct 2016 at 12:54, CodeDmitry <[hidden email]> wrote:
I tried so hard to find an example of Ruby using smalltalk message syntax.
You can do something like:

class Dictionary
    attr_accessor :dict

    def initialize()
        @dict = {}
    end

    def at(*args)
        if (args.length == 1) then
            return @dict[args[0]]
        end
        @dict[args[0]] = args[1][:put]
    end
end

dict = Dictionary.new
dict.at 3, put: 4
puts dict.dict
puts dict.at 3


But it's pretty expensive to disambiguate messages to "at" this way.

The JS approach was much simpler since each message like 'at:put:' or 'at'
were sent to appropriate receiver functions, whereas this is just a
spaghetti :\

I'm sure there's more elegant way of doing this in Ruby but I haven't found
it :|



--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918959.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Tudor Girba-2
In reply to this post by CodeDmitry
Hi,


> On Oct 16, 2016, at 10:41 AM, CodeDmitry <[hidden email]> wrote:
>
> I was actually curious about this in Ruby as well, since Ruby also doesn't
> have the Smalltalk message syntax.
>
> I figure that the magic behind it is that Smalltalk takes strings like "dict
> at: 'foo' put: 'bar'" and evaluates them into a JavaScript equivalent of
> "dict['at:put:']('foo', 'bar')”.

There is no magic. This is how the syntax is. Instead of parentheses that accumulate all parameters in a single place like:
        x.atput(a,b);

we can insert the argument inside the message name, like:
        x at: a put: b.

It’s not magic, is just different. That’s all. Except that one makes it possible to write code that resembles natural language.

Doru



> Basically, my proof of concept(I cheated with regex to cut time):
>
> 'use strict';
>
> var Dictionary = function Dictionary() {
>    this.dict = {};
> };
> Dictionary.prototype['at:put:'] = function(index, value) {
>    this.dict[index] = value;
> };
> Object.defineProperty(Dictionary, 'new', {
>    get: function () {
>        return new this;
>    }
> });
>
> function st_eval(str) {
>    var x = str.match(/(dict)\s+(at):\s+'(foo)'\s+(put):\s+'(bar)'/);
>    var target = x[1];
>    var callName = x[2] + ':' + x[4] + ':';
>    var argv = [x[3], x[5]];
>    var realTarget = eval(target);
>    realTarget[callName].apply(realTarget, argv);
> }
>
> var dict = Dictionary.new;
> console.log(dict);
> //dict['at:put:']('foo', 'bar');
> console.log(dict);
> st_eval("dict at: 'foo' put: 'bar'");
> console.log(dict);
>
>
>
>
>
> --
> View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918957.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>

--
www.tudorgirba.com
www.feenk.com

“The smaller and more pervasive the hardware becomes, the more physical the software gets."


Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

CodeDmitry
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Nicolai Hess-3-2

Am 16.10.2016 14:35 schrieb "CodeDmitry" <[hidden email]>:
>
> I define Magic as "An opaque abstraction or an abstraction you think is
> opaque until you learn better.", to a beginner, everything is deeply
> Magical.
>
> That said, much of Smalltalk's opaqueness is not due to the language, but
> due to me being a beginner. I'm sure there's a way to actually force sending
> a message to a dictionary via something like dict['at:put:']('foo', 'bar')
> but I am not familiar enough with Smalltalk to express it, so it feels like
> the only way to send a message is via this multi-part message abstraction.
>

You can always access the method dict directly to get a method and call "perform"
or perform with arguments.

>
>
>
>
>
> --
> View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918966.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

bestlem
In reply to this post by Tudor Girba-2
For an example of a working bridge between the two ways of methods and
function see PyObjc which allows Python code to call Objective C
messaging (e.g in a similar form to your mapping Javascript to Smalltalk
- except Javascript is not class based)


https://pythonhosted.org/pyobjc/core/intro.html


Mark

On 16/10/2016 12:59, Tudor Girba wrote:

> Hi,
>
>
>> On Oct 16, 2016, at 10:41 AM, CodeDmitry <[hidden email]> wrote:
>>
>> I was actually curious about this in Ruby as well, since Ruby also doesn't
>> have the Smalltalk message syntax.
>>
>> I figure that the magic behind it is that Smalltalk takes strings like "dict
>> at: 'foo' put: 'bar'" and evaluates them into a JavaScript equivalent of
>> "dict['at:put:']('foo', 'bar')”.
>
> There is no magic. This is how the syntax is. Instead of parentheses that accumulate all parameters in a single place like:
> x.atput(a,b);
>
> we can insert the argument inside the message name, like:
> x at: a put: b.
>
> It’s not magic, is just different. That’s all. Except that one makes it possible to write code that resembles natural language.
>
> Doru
>
>
>
>> Basically, my proof of concept(I cheated with regex to cut time):
>>
>> 'use strict';
>>
>> var Dictionary = function Dictionary() {
>>    this.dict = {};
>> };
>> Dictionary.prototype['at:put:'] = function(index, value) {
>>    this.dict[index] = value;
>> };
>> Object.defineProperty(Dictionary, 'new', {
>>    get: function () {
>>        return new this;
>>    }
>> });
>>
>> function st_eval(str) {
>>    var x = str.match(/(dict)\s+(at):\s+'(foo)'\s+(put):\s+'(bar)'/);
>>    var target = x[1];
>>    var callName = x[2] + ':' + x[4] + ':';
>>    var argv = [x[3], x[5]];
>>    var realTarget = eval(target);
>>    realTarget[callName].apply(realTarget, argv);
>> }
>>
>> var dict = Dictionary.new;
>> console.log(dict);
>> //dict['at:put:']('foo', 'bar');
>> console.log(dict);
>> st_eval("dict at: 'foo' put: 'bar'");
>> console.log(dict);
>>
>>
>>
>>
>>


--
Mark


Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

kilon.alios
In reply to this post by CodeDmitry
Smalltalk does not allow you to do calls of any kind, everything goes through the messaging system . To have the same in another language you will have to disable the ability to call functions and method and replace them with messages. No language such feature not even lisp, the language that excels at manipulating its syntax . In order to implement this you will have to go deep into the implementation of the language and essentially change it to something , probably a new programming language.


On Sun, 16 Oct 2016 at 15:35, CodeDmitry <[hidden email]> wrote:
I define Magic as "An opaque abstraction or an abstraction you think is
opaque until you learn better.", to a beginner, everything is deeply
Magical.

That said, much of Smalltalk's opaqueness is not due to the language, but
due to me being a beginner. I'm sure there's a way to actually force sending
a message to a dictionary via something like dict['at:put:']('foo', 'bar')
but I am not familiar enough with Smalltalk to express it, so it feels like
the only way to send a message is via this multi-part message abstraction.






--
View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918966.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Ben Coman
In reply to this post by CodeDmitry
On Sun, Oct 16, 2016 at 12:44 PM, CodeDmitry <[hidden email]> wrote:
> I understand that it is a single message send, but to know how to handle the
> message at runtime, the parser needs to somehow determine where the
> implementation of that message is. It must do a lookup based on multiple
> keys(at, and put),

This is wrong :)
it is only one key #at:put:

Define a method....
test
    |arr|
    a := Array new: 1.
    a at: 1 put: 'Hello, World'.

Then in the method pane, right-click and choose Inspect Method,
then look at the [Bytecodes] tab.
You'll see "28 <C1> send: at:put:"
So the parser has already done its part compiling the source code to
bytecode and plays no further part in looking up which implementation
method to execute in response to the message.  That is done by the VM
when the message is sent.  If you look at the chart at the top of [1],
you'll see #interpret calls #dispatchIn:On: which calls
#commonOrdinarySend:.   This calls #internalFindNewMethodOrdinary
which starts the actual method lookup by the VM.  To review these
methods you need to load the VMMaker package, which the instructions
at [2] will do for you.

[1] http://forum.world.st/CogVM-Execution-Flow-td4900675.html
[2] https://github.com/pharo-project/pharo-vm

cheers -ben

which is really confusing. "methods" are easy to look up

> because they only have one name, but messages have one name which is split
> amongst each argument.
>
> Simple concatenation does not make sense, since {at: x, put: y} and {a: x,
> tput: y} are different messages.
>
> The only way I can think of this being implemented "easily" is by storing a
> table of entries {num_args, arg_names, impl_ref}, and then have the function
> "send" do a linear search over this table until it finds an entry with
> num_args = 2, each arg_name matching the argument name keys in order, and
> then calling the impl_ref with the array of values without the names.
>
> I'm wondering if there is a way to do this without having to loop over every
> single message the object has, then every message its' parent object has,
> and so on, just to find which function you actually want to call.
>
>
>
>
>
> --
> View this message in context: http://forum.world.st/How-do-Smalltalk-disambiguate-messages-tp4918946p4918948.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Ben Coman
In reply to this post by Nicolai Hess-3-2
On Sun, Oct 16, 2016 at 8:38 PM, Nicolai Hess <[hidden email]> wrote:

> Am 16.10.2016 14:35 schrieb "CodeDmitry" <[hidden email]>:
>>
>> I define Magic as "An opaque abstraction or an abstraction you think is
>> opaque until you learn better.", to a beginner, everything is deeply
>> Magical.
>>
>> That said, much of Smalltalk's opaqueness is not due to the language, but
>> due to me being a beginner. I'm sure there's a way to actually force
>> sending
>> a message to a dictionary via something like dict['at:put:']('foo', 'bar')
>> but I am not familiar enough with Smalltalk to express it, so it feels
>> like
>> the only way to send a message is via this multi-part message abstraction.
>>
>
> You can always access the method dict directly to get a method and call
> "perform" or perform with arguments.

To put that in more concrete terms...
    a := Array new: 1.
    a perform: #at:put: withArguments: {1. 'Hello, world'}.
    a inspect.

Note how    #at:put:   is a single identifier.

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: How do Smalltalk disambiguate messages?

Charlie Robbats
Banned User
This post was updated on .
In reply to this post by CodeDmitry
CONTENTS DELETED
The author has deleted this message.
12