Introduce WAMessageSend #268

Closed
GoogleCodeExporter opened this Issue Mar 25, 2015 · 18 comments

Comments

Projects
None yet
1 participant
@GoogleCodeExporter
Currently Seaside depends on the platform class MessageSend (receiver, 
selector, arguments). This 
class is not part of ANSI Smalltalk and the implementation of this class is 
extremely obscure in 
Squeak, especially when it is evaluated with additional or a variable number of 
arguments.

I suggest to improve the situation by providing a clean implementation of 
WAMessageSend. 
However I do not really see how such a thing could be implemented nicely, so 
that it behaves polymorphic to the evaluation protocol of BlockContext 
(#value:, #value:value:, 
#valueWithArguments:, #valueWithPossibleArguments:) and that #numArgs answers a 
meaningful 
result (so that things like in WAAnchor>>#callback: are not necessary).


Original issue reported on code.google.com by renggli on 3 Jan 2009 at 10:13

@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Original comment by renggli on 3 Jan 2009 at 10:15

  • Added labels: Milestone-2.9b1
  • Removed labels: ****

Original comment by renggli on 3 Jan 2009 at 10:15

  • Added labels: Milestone-2.9b1
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Well, in my opinion, #numArgs on WAMessageSend should return the number of free 
arguments. If an argument 
is already bound you shouldn't be able to change it with a #value* method.

Alternatively, I suppose you could implement #freeArgs (preferably 
#freeArguments actually - I hate 
abbreviations in method names) on WAMessageSend and BlockContext and use that 
but I don't see why that 
should be necessary.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 10:35

  • Added labels: ****
  • Removed labels: ****
Well, in my opinion, #numArgs on WAMessageSend should return the number of free 
arguments. If an argument 
is already bound you shouldn't be able to change it with a #value* method.

Alternatively, I suppose you could implement #freeArgs (preferably 
#freeArguments actually - I hate 
abbreviations in method names) on WAMessageSend and BlockContext and use that 
but I don't see why that 
should be necessary.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 10:35

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Adding free arguments to MessageSend is a very bad idea.  If you need to have 
free
arguments, it's not a MessageSend anymore, rather it's polymorphic with a block 
(plus
some support for currying).  Self can be the first free argument, which nicely 
fixes
the problem with #numArgs.  I would call it WAMessageCallback.

Original comment by bonz...@gnu.org on 3 Jan 2009 at 11:10

  • Added labels: ****
  • Removed labels: ****
Adding free arguments to MessageSend is a very bad idea.  If you need to have 
free
arguments, it's not a MessageSend anymore, rather it's polymorphic with a block 
(plus
some support for currying).  Self can be the first free argument, which nicely 
fixes
the problem with #numArgs.  I would call it WAMessageCallback.

Original comment by bonz...@gnu.org on 3 Jan 2009 at 11:10

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Hmm... Sorry, Paolo, I don't follow your argument... you seem to make some 
assumptions that aren't explicitly 
stated. Are you basing this on an existing implementation of MessageSend 
somewhere other than Squeak?

Why is it not a message send if the arguments are not yet all specified? A 
MessageSend (at least in Squeak and 
as it is used in Seaside) represents a *future* message send. The message can't 
actually be sent until all the 
parameters are specified but there's no reason they all have to be specified 
when the object is created.

And yes, it is polymorphic with a block - so is the existing MessageSend in 
Squeak (at least in theory). From 
the class comment:

"Instances of MessageSend encapsulate message sends to objects. Arguments can 
be either predefined or 
supplied when the message send is performed. 

Use #value to perform a message send with its predefined arguments and 
#valueWithArguments: if additonal 
arguments have to supplied."

The idea of MessageSend (again, at least as used in Seaside) is to optimize by 
replacing block contexts when 
all the block does is call a method with the parameters of the block. Callback 
has a very specific meaning in 
Seaside and this class is more general than that.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 12:48

  • Added labels: ****
  • Removed labels: ****
Hmm... Sorry, Paolo, I don't follow your argument... you seem to make some 
assumptions that aren't explicitly 
stated. Are you basing this on an existing implementation of MessageSend 
somewhere other than Squeak?

Why is it not a message send if the arguments are not yet all specified? A 
MessageSend (at least in Squeak and 
as it is used in Seaside) represents a *future* message send. The message can't 
actually be sent until all the 
parameters are specified but there's no reason they all have to be specified 
when the object is created.

And yes, it is polymorphic with a block - so is the existing MessageSend in 
Squeak (at least in theory). From 
the class comment:

"Instances of MessageSend encapsulate message sends to objects. Arguments can 
be either predefined or 
supplied when the message send is performed. 

Use #value to perform a message send with its predefined arguments and 
#valueWithArguments: if additonal 
arguments have to supplied."

The idea of MessageSend (again, at least as used in Seaside) is to optimize by 
replacing block contexts when 
all the block does is call a method with the parameters of the block. Callback 
has a very specific meaning in 
Seaside and this class is more general than that.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 12:48

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

> Why is it not a message send if the arguments are not yet all specified?

Because its definition is not meant to be the same as a message send.  For 
example there should be no 
distinction between receiver and arguments - if the selector has N keywords (0 
for a unary message), the 
"thing" should have N+1 arguments.  Then you can specify a constructor method 
#selector:receiver:, but 
that's just a handy shortcut that sets the first argument.

> it is polymorphic with a block - so is the existing MessageSend in Squeak (at 
least in theory)

The "thing" is polymorphic with a block, the existing MessageSend in Squeak is 
not.  If something can be 
evaluated with #value, its #numArgs should be 0.  Maybe that's what you meant 
by "(at least in theory)".

I don't care much if you call the "thing" WAMessageSend, because anyway in GNU 
Smalltalk the Squeak 
MessageSend is called DirectedMessage.  But in Squeak it'd be confusing to have 
two classes differing only by 
the WA prefix, but with only vaguely similar semantics.

> Callback has a very specific meaning in Seaside

Yeah, you're right.

One problem with the name is that block classes (independent of whether the 
exact name is Block, 
BlockClosure, BlockContext or anything else) are named according to their 
syntax element rather than 
according to their function (kind of like "Proc" in ruby).  Maybe 
"WAMessageSender"?

Original comment by paolo.bo...@gmail.com on 3 Jan 2009 at 2:26

  • Added labels: ****
  • Removed labels: ****
> Why is it not a message send if the arguments are not yet all specified?

Because its definition is not meant to be the same as a message send.  For 
example there should be no 
distinction between receiver and arguments - if the selector has N keywords (0 
for a unary message), the 
"thing" should have N+1 arguments.  Then you can specify a constructor method 
#selector:receiver:, but 
that's just a handy shortcut that sets the first argument.

> it is polymorphic with a block - so is the existing MessageSend in Squeak (at 
least in theory)

The "thing" is polymorphic with a block, the existing MessageSend in Squeak is 
not.  If something can be 
evaluated with #value, its #numArgs should be 0.  Maybe that's what you meant 
by "(at least in theory)".

I don't care much if you call the "thing" WAMessageSend, because anyway in GNU 
Smalltalk the Squeak 
MessageSend is called DirectedMessage.  But in Squeak it'd be confusing to have 
two classes differing only by 
the WA prefix, but with only vaguely similar semantics.

> Callback has a very specific meaning in Seaside

Yeah, you're right.

One problem with the name is that block classes (independent of whether the 
exact name is Block, 
BlockClosure, BlockContext or anything else) are named according to their 
syntax element rather than 
according to their function (kind of like "Proc" in ruby).  Maybe 
"WAMessageSender"?

Original comment by paolo.bo...@gmail.com on 3 Jan 2009 at 2:26

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Ok, it sounds like the only issue you really have here is with the name of the 
class then?

It sounds like there is agreement that Seaside should have a class that holds a 
receiver and a selector, and supports optionally 
currying some or all of the arguments. #numArgs should therefore return the 
number of free arguments and the #value* 
methods should operate on that basis as well.

> Because its definition is not meant to be the same as a message send. For 
example there should be no 
distinction between receiver and arguments

I'm still not sure to what exact thing you are referring by the name "message 
send". I feel like you have some particular 
association with the phrase "message send" that I don't which makes the name 
seem inaccurate to you; the first argument being 
the receiver seems like an implementation detail.

The object we're talking about seems like a reification of the sending of a 
message (receiver, selector, arguments) so 
WAMessageSend makes sense as far as I'm concerned but I'll tune out for now and 
let others chime in on the naming issue.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 3:17

  • Added labels: ****
  • Removed labels: ****
Ok, it sounds like the only issue you really have here is with the name of the 
class then?

It sounds like there is agreement that Seaside should have a class that holds a 
receiver and a selector, and supports optionally 
currying some or all of the arguments. #numArgs should therefore return the 
number of free arguments and the #value* 
methods should operate on that basis as well.

> Because its definition is not meant to be the same as a message send. For 
example there should be no 
distinction between receiver and arguments

I'm still not sure to what exact thing you are referring by the name "message 
send". I feel like you have some particular 
association with the phrase "message send" that I don't which makes the name 
seem inaccurate to you; the first argument being 
the receiver seems like an implementation detail.

The object we're talking about seems like a reification of the sending of a 
message (receiver, selector, arguments) so 
WAMessageSend makes sense as far as I'm concerned but I'll tune out for now and 
let others chime in on the naming issue.

Original comment by jfitz...@gmail.com on 3 Jan 2009 at 3:17

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

> Ok, it sounds like the only issue you really have here is with the name of 
the class then?

I also wanted to make sure that #numArgs and #value* were meant to be as you 
wrote, and not as in 
WAMessageSend.

It sends a message many times (hence my WAMessageSender name).

Original comment by paolo.bo...@gmail.com on 3 Jan 2009 at 3:48

  • Added labels: ****
  • Removed labels: ****
> Ok, it sounds like the only issue you really have here is with the name of 
the class then?

I also wanted to make sure that #numArgs and #value* were meant to be as you 
wrote, and not as in 
WAMessageSend.

It sends a message many times (hence my WAMessageSender name).

Original comment by paolo.bo...@gmail.com on 3 Jan 2009 at 3:48

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

> It sounds like there is agreement that Seaside should have a class that holds 
a receiver and a selector, and 
supports optionally currying some or all of the arguments. #numArgs should 
therefore return the number of free 
arguments and the #value* methods should operate on that basis as well.

Yes, this is what we need.

Are remaining arguments always appended to the end? Or can they be introduced 
at specific positions in any 
order? Is the receiver treated the same way as an argument? For example would 
it be possible to represent the 
following block as a "message send" object?

   [ :x :y | y foo: a1 bar: a2 zork: x ]
   (x, y are free vars; a1, a2 are bound vars; #foo:bar:zork: is the selector)

I think being able to support that would be quite useful in the context of 
Seaside. How would such an object be 
specified? 

It looks a bit like a generalization of Vassili Bykov's "Selectors as Blocks", 
see http://blog.3plus4.org/2007/03/27/selectors-as-blocks/ and the following 
posts.

Original comment by renggli on 3 Jan 2009 at 4:14

  • Added labels: ****
  • Removed labels: ****
> It sounds like there is agreement that Seaside should have a class that holds 
a receiver and a selector, and 
supports optionally currying some or all of the arguments. #numArgs should 
therefore return the number of free 
arguments and the #value* methods should operate on that basis as well.

Yes, this is what we need.

Are remaining arguments always appended to the end? Or can they be introduced 
at specific positions in any 
order? Is the receiver treated the same way as an argument? For example would 
it be possible to represent the 
following block as a "message send" object?

   [ :x :y | y foo: a1 bar: a2 zork: x ]
   (x, y are free vars; a1, a2 are bound vars; #foo:bar:zork: is the selector)

I think being able to support that would be quite useful in the context of 
Seaside. How would such an object be 
specified? 

It looks a bit like a generalization of Vassili Bykov's "Selectors as Blocks", 
see http://blog.3plus4.org/2007/03/27/selectors-as-blocks/ and the following 
posts.

Original comment by renggli on 3 Jan 2009 at 4:14

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

[deleted comment]
[deleted comment]
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

[edited to correct silly implementation mistake I remembered while falling 
asleep :) ]

That's getting pretty fancy - do we have a use case that actually needs it?

I can imagine an implementation a bit like ROE using exactly the block you 
specify above:

s := WADelayedMessageSend send: [:x :y | y foo: a1 bar: a2 zork: x]

the instance creation method would check how many arguments the block had and 
pass special objects in for 
each one. Then it would evaluate the block and be able to tell which argument 
was the receiver and (since the 
method gets called on it, what the parameters were). It's less clear what the 
implementation is if you want to 
specify the receiver at creation time. I guess you have to add the receiver as 
a parameter to the block:

s := WADelayedMessageSend
    receiver: MyClass
    send: [ :receiver :x :y | receiver foo: a1 bar: a2 zork: x]

It's a little wonky and given that it probably the more common use case, that's 
a shame. But it would work.

So, I think that's quite cool actually but... do we need it?

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 12:16

  • Added labels: ****
  • Removed labels: ****
[edited to correct silly implementation mistake I remembered while falling 
asleep :) ]

That's getting pretty fancy - do we have a use case that actually needs it?

I can imagine an implementation a bit like ROE using exactly the block you 
specify above:

s := WADelayedMessageSend send: [:x :y | y foo: a1 bar: a2 zork: x]

the instance creation method would check how many arguments the block had and 
pass special objects in for 
each one. Then it would evaluate the block and be able to tell which argument 
was the receiver and (since the 
method gets called on it, what the parameters were). It's less clear what the 
implementation is if you want to 
specify the receiver at creation time. I guess you have to add the receiver as 
a parameter to the block:

s := WADelayedMessageSend
    receiver: MyClass
    send: [ :receiver :x :y | receiver foo: a1 bar: a2 zork: x]

It's a little wonky and given that it probably the more common use case, that's 
a shame. But it would work.

So, I think that's quite cool actually but... do we need it?

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 12:16

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

That seems to be a bit too much magic for Seaside. To be able to properly use 
such such block you need to know 
how it is implemented, and to understand that you almost need to be a Smalltalk 
wizard. At least this is my 
experience from ROE.

I guess in most cases the reordering is not needed and appending to the end is 
just fine. If really necessary the 
reordering and the default arguments can always be inserted using a helper 
method.

Original comment by renggli on 4 Jan 2009 at 12:41

  • Added labels: ****
  • Removed labels: ****
That seems to be a bit too much magic for Seaside. To be able to properly use 
such such block you need to know 
how it is implemented, and to understand that you almost need to be a Smalltalk 
wizard. At least this is my 
experience from ROE.

I guess in most cases the reordering is not needed and appending to the end is 
just fine. If really necessary the 
reordering and the default arguments can always be inserted using a helper 
method.

Original comment by renggli on 4 Jan 2009 at 12:41

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

I agree with Lukas and BTW I like WADelayedMessageSend as a name.

The only common case I foresee of reordering is to give fixed arguments and 
apply the
first argument as a receiver.  But I think we can live without it until an 
actual use
case pops up.

Original comment by bonz...@gnu.org on 4 Jan 2009 at 12:45

  • Added labels: ****
  • Removed labels: ****
I agree with Lukas and BTW I like WADelayedMessageSend as a name.

The only common case I foresee of reordering is to give fixed arguments and 
apply the
first argument as a receiver.  But I think we can live without it until an 
actual use
case pops up.

Original comment by bonz...@gnu.org on 4 Jan 2009 at 12:45

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Yup, I agree. And a helper method is the obvious workaround if you absolutely 
don't want to just use a block. :)

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 1:20

  • Added labels: ****
  • Removed labels: ****
Yup, I agree. And a helper method is the obvious workaround if you absolutely 
don't want to just use a block. :)

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 1:20

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

I posted an implementation on seaside-dev.

Original comment by bonz...@gnu.org on 4 Jan 2009 at 1:32

  • Added labels: Type-Patch
  • Removed labels: Type-CleanUp
I posted an implementation on seaside-dev.

Original comment by bonz...@gnu.org on 4 Jan 2009 at 1:32

  • Added labels: Type-Patch
  • Removed labels: Type-CleanUp
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Original comment by bonz...@gnu.org on 4 Jan 2009 at 1:32

  • Changed state: Started
  • Added labels: ****
  • Removed labels: ****

Original comment by bonz...@gnu.org on 4 Jan 2009 at 1:32

  • Changed state: Started
  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

(attaching the implementation posted to the mailing list)

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 3:16

  • Added labels: ****
  • Removed labels: ****

Attachments:

(attaching the implementation posted to the mailing list)

Original comment by jfitz...@gmail.com on 4 Jan 2009 at 3:16

  • Added labels: ****
  • Removed labels: ****

Attachments:

@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

Started at integrating.

Original comment by philippe...@gmail.com on 10 Jan 2009 at 5:07

  • Added labels: ****
  • Removed labels: ****
Started at integrating.

Original comment by philippe...@gmail.com on 10 Jan 2009 at 5:07

  • Added labels: ****
  • Removed labels: ****
@GoogleCodeExporter

This comment has been minimized.

Show comment
Hide comment
@GoogleCodeExporter

GoogleCodeExporter Mar 25, 2015

We went for a slightly different design. We have an abstract superclass 
WADelayedSend with two concrete subclasses. That removes a lot of self testing. 
We 
also went for a protocol based on ANSI. Details will follow on the list.

Original comment by philippe...@gmail.com on 11 Jan 2009 at 9:34

  • Changed state: Fixed
  • Added labels: ****
  • Removed labels: ****
We went for a slightly different design. We have an abstract superclass 
WADelayedSend with two concrete subclasses. That removes a lot of self testing. 
We 
also went for a protocol based on ANSI. Details will follow on the list.

Original comment by philippe...@gmail.com on 11 Jan 2009 at 9:34

  • Changed state: Fixed
  • Added labels: ****
  • Removed labels: ****
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment