Cascading ?

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

Cascading ?

Damien Cassou-3
Hi,

I'm wondering why the following code does not compile and answers
'Nothing more expected':

test:=OrderedCollection with: 'first'.
test
   add: 'second';
   size negated


It seems we can't send another message to size !

Can somebody explain this to me please ?



--
Damien

Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Klaus D. Witzel
On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:

> Hi,
>
> I'm wondering why the following code does not compile and answers  
> 'Nothing more expected':
>
> test:=OrderedCollection with: 'first'.
> test
>    add: 'second';
>    size negated
>

(test add: 'second'; size) negated is what you can do with the result of  
your cascaded messages.

> It seems we can't send another message to size !

Sure, you can. But when you cascade messages, you have two receivers: the  
cascade receiver and the cascade result. Think that the compiler wants you  
to tell which one you mean.

> Can somebody explain this to me please ?

HTH.

/Klaus


Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Damien Cassou-3
Klaus D. Witzel wrote:

> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>
>> test:=OrderedCollection with: 'first'.
>> test
>>    add: 'second';
>>    size negated
>>
>
> (test add: 'second'; size) negated is what you can do with the result of
> your cascaded messages.


Maybe my example was not clear enough:

test:= MyObjectModel
test
    getAllChanges;
    storageStrategy storeNow;
    readyToContinue

I think it is clear that #storeNow is sent to the result of 'test
storageStrategy'. And #readyToContinue should still be sent to 'test' so
  brackets are not possible in this example.




Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Hilaire Fernandes-3
Damien Cassou a écrit :

> Klaus D. Witzel wrote:
>> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>>
>>> test:=OrderedCollection with: 'first'.
>>> test
>>>    add: 'second';
>>>    size negated
>>>
>>
>> (test add: 'second'; size) negated is what you can do with the result
>> of your cascaded messages.
>
>
> Maybe my example was not clear enough:
>
> test:= MyObjectModel
> test
>    getAllChanges;
>    storageStrategy storeNow;
>    readyToContinue
>
> I think it is clear that #storeNow is sent to the result of 'test
> storageStrategy'. And #readyToContinue should still be sent to 'test' so
>  brackets are not possible in this example.


I think storeNow is sent to storageStrategy, then the returned object
from this message call, which should be a message symbol, is sent to test.
May be it should be written

test:= MyObjectModel
(test
   getAllChanges;
   storageStrategy) storeNow.
test   readyToContinue

Hilaire

Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Damien Cassou-3
Hilaire Fernandes wrote:

> Damien Cassou a écrit :
>> Klaus D. Witzel wrote:
>>> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>>>
>>>> test:=OrderedCollection with: 'first'.
>>>> test
>>>>    add: 'second';
>>>>    size negated
>>>>
>>> (test add: 'second'; size) negated is what you can do with the result
>>> of your cascaded messages.
>>
>> Maybe my example was not clear enough:
>>
>> test:= MyObjectModel
>> test
>>    getAllChanges;
>>    storageStrategy storeNow;
>>    readyToContinue
>>
>> I think it is clear that #storeNow is sent to the result of 'test
>> storageStrategy'. And #readyToContinue should still be sent to 'test' so
>>  brackets are not possible in this example.
>
>
> I think storeNow is sent to storageStrategy, then the returned object
> from this message call, which should be a message symbol, is sent to test.
> May be it should be written
>
> test:= MyObjectModel
> (test
>    getAllChanges;
>    storageStrategy) storeNow.
> test   readyToContinue


I know how to make it work in fact. What I don't understand is why the
smalltalk doesn't allow this kind of construction.


Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Klaus D. Witzel
In reply to this post by Damien Cassou-3
On Thu, 17 Aug 2006 12:07:54 +0200, Damien Cassou wrote:

> Klaus D. Witzel wrote:
>> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>>
>>> test:=OrderedCollection with: 'first'.
>>> test
>>>    add: 'second';
>>>    size negated
>>>
>>  (test add: 'second'; size) negated is what you can do with the result  
>> of your cascaded messages.
>
> Maybe my example was not clear enough:

No it was crystal clear.

> test:= MyObjectModel
> test
>     getAllChanges;
>     storageStrategy storeNow;
>     readyToContinue

  test
      getAllChanges;
      ifNotNil: [test storageStrategy storeNow];
      readyToContinue

does not compile (lack of support from parser/compiler) but

| test |
test := nil.
  test
      yourself;
      ifNotNilDo: [:ignored | test yourself isNil];
      yourself

does.

> I think it is clear that #storeNow is sent to the result of 'test  
> storageStrategy'. And #readyToContinue should still be sent to 'test'

See above, it is.

> so   brackets are not possible in this example.

Brackets are but parentheses aren't, in your 2nd example.

/Klaus


Reply | Threaded
Open this post in threaded view
|

Re: Re: Cascading ?

Lukas Renggli
In reply to this post by Damien Cassou-3
> >> test:= MyObjectModel
> >> test
> >>    getAllChanges;
> >>    storageStrategy storeNow;
> >>    readyToContinue
> >>
> I know how to make it work in fact. What I don't understand is why the
> smalltalk doesn't allow this kind of construction.

Because it is ambiguous. How should the compiler know if it should
send #readyToContinue to 'test' or the result of 'test
storageStrategy'?

Lukas


--
Lukas Renggli
http://www.lukas-renggli.ch

Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Klaus D. Witzel
In reply to this post by Klaus D. Witzel
Instead of #ifNotNilDo: you can use #in: but there are no examples in the  
image for using #in: for cascading.

/Klaus

On Thu, 17 Aug 2006 12:34:26 +0200, Klaus wrote:

> On Thu, 17 Aug 2006 12:07:54 +0200, Damien Cassou wrote:
>> Klaus D. Witzel wrote:
>>> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>>>
>>>> test:=OrderedCollection with: 'first'.
>>>> test
>>>>    add: 'second';
>>>>    size negated
>>>>
>>>  (test add: 'second'; size) negated is what you can do with the result  
>>> of your cascaded messages.
>>
>> Maybe my example was not clear enough:
>
> No it was crystal clear.
>
>> test:= MyObjectModel
>> test
>>     getAllChanges;
>>     storageStrategy storeNow;
>>     readyToContinue
>
>   test
>       getAllChanges;
>       ifNotNil: [test storageStrategy storeNow];
>       readyToContinue
>
> does not compile (lack of support from parser/compiler) but
>
> | test |
> test := nil.
>   test
>       yourself;
>       ifNotNilDo: [:ignored | test yourself isNil];
>       yourself
>
> does.
>
>> I think it is clear that #storeNow is sent to the result of 'test  
>> storageStrategy'. And #readyToContinue should still be sent to 'test'
>
> See above, it is.
>
>> so   brackets are not possible in this example.
>
> Brackets are but parentheses aren't, in your 2nd example.
>
> /Klaus
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Klaus D. Witzel
In reply to this post by Lukas Renggli
On Thu, 17 Aug 2006 12:43:54 +0200, Lukas Renggli wrote:

>> >> test:= MyObjectModel
>> >> test
>> >>    getAllChanges;
>> >>    storageStrategy storeNow;
>> >>    readyToContinue
>> >>
>> I know how to make it work in fact. What I don't understand is why the
>> smalltalk doesn't allow this kind of construction.
>
> Because it is ambiguous. How should the compiler know if it should
> send #readyToContinue to 'test' or the result of 'test
> storageStrategy'?

It would be interesting to find a language construct which does support  
Damien's expression. Not that I want everybody to write as much cascades  
as possible but, I want to be able to do so.

/Klaus

> Lukas
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Re: Cascading ?

Lukas Renggli
> > Because it is ambiguous. How should the compiler know if it should
> > send #readyToContinue to 'test' or the result of 'test
> > storageStrategy'?
>
> It would be interesting to find a language construct which does support
> Damien's expression. Not that I want everybody to write as much cascades
> as possible but, I want to be able to do so.

I think #in: is a good solution for that particular problem. I use it
sometimes with Seaside and script.aculo.us, both frameworks make
extensive use of cascades to build and configure html-tags and
JavaScript objects.

An example: The CSS class 'red' is only added, if a specific condition is met.

html div
     id: 'foo';
     class: 'border';
     in: [ :tag | condition ifTrue: [ tag class: 'red' ] ];
     with: 'contents'

However, as the code doesn't make me feel cosy I added a helper method
to the receiver of the cascade. After the refactoring (yeah, a
refactoring, not an change ... I finally got it, yeah, yeah, ...) it
looks like:

html div
     idd: 'foo';
     class: 'border';
     class: 'red' if: condition;
     with: 'contents'

Such a refactoring can be always applied and is probably better
practice than to start using blocks ...

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

Reply | Threaded
Open this post in threaded view
|

Re: Re: Cascading ?

Klaus D. Witzel
This is one of the best examples of a) lack of *language* support; b)  
quick&dirty solution using blocks; c) refactoring; sequence that I've ever  
seen :)

Thank you for posting this one, Damien & Lukas.

/Klaus

On Thu, 17 Aug 2006 13:14:35 +0200, Lukas Renggli wrote:

>> > Because it is ambiguous. How should the compiler know if it should
>> > send #readyToContinue to 'test' or the result of 'test
>> > storageStrategy'?
>>
>> It would be interesting to find a language construct which does support
>> Damien's expression. Not that I want everybody to write as much cascades
>> as possible but, I want to be able to do so.
>
> I think #in: is a good solution for that particular problem. I use it
> sometimes with Seaside and script.aculo.us, both frameworks make
> extensive use of cascades to build and configure html-tags and
> JavaScript objects.
>
> An example: The CSS class 'red' is only added, if a specific condition  
> is met.
>
> html div
>      id: 'foo';
>      class: 'border';
>      in: [ :tag | condition ifTrue: [ tag class: 'red' ] ];
>      with: 'contents'
>
> However, as the code doesn't make me feel cosy I added a helper method
> to the receiver of the cascade. After the refactoring (yeah, a
> refactoring, not an change ... I finally got it, yeah, yeah, ...) it
> looks like:
>
> html div
>      idd: 'foo';
>      class: 'border';
>      class: 'red' if: condition;
>      with: 'contents'
>
> Such a refactoring can be always applied and is probably better
> practice than to start using blocks ...
>
> Lukas
>



Reply | Threaded
Open this post in threaded view
|

Re: About brackets and parenthesis

Damien Cassou-3
In reply to this post by Klaus D. Witzel
Klaus D. Witzel wrote:

> On Thu, 17 Aug 2006 12:07:54 +0200, Damien Cassou wrote:
>> Klaus D. Witzel wrote:
>>> On Thu, 17 Aug 2006 11:12:36 +0200, Damien Cassou wrote:
>>>
>>>> test:=OrderedCollection with: 'first'.
>>>> test
>>>>    add: 'second';
>>>>    size negated
>>>>
>>>  (test add: 'second'; size) negated is what you can do with the
>>> result of your cascaded messages.
>>
>> Maybe my example was not clear enough:
>
> No it was crystal clear.
>
>> test:= MyObjectModel
>> test
>>     getAllChanges;
>>     storageStrategy storeNow;
>>     readyToContinue
>
>  test
>      getAllChanges;
>      ifNotNil: [test storageStrategy storeNow];
>      readyToContinue
>
> does not compile (lack of support from parser/compiler) but
>
> | test |
> test := nil.
>  test
>      yourself;
>      ifNotNilDo: [:ignored | test yourself isNil];
>      yourself
>
> does.
>
>> I think it is clear that #storeNow is sent to the result of 'test
>> storageStrategy'. And #readyToContinue should still be sent to 'test'
>
> See above, it is.
>
>> so   brackets are not possible in this example.
>
> Brackets are but parentheses aren't, in your 2nd example.


Stop confusing me ;-) Just before writing the mail, I had a look at my
dictionary because I've never managed to know how those following
symbols are called in english:

() [] {}

My dictionary told me:

() brackets or parenthesis (for US)
[] square brackets
{} braces or curly brackets

When I said: 'so brackets are not possible in this example', I meant
parenthesis :-)

Two minutes ago, I verified in wikipedia and it seems that 'Bracket' is
the superclass of Parenthesis.

Which one is correct :-) ?

Reply | Threaded
Open this post in threaded view
|

Re: About brackets and parenthesis

Klaus D. Witzel
On Thu, 17 Aug 2006 15:54:43 +0200, Damien Cassou wrote:

> Klaus wrote:
>>> so   brackets are not possible in this example.
>>  Brackets are but parentheses aren't, in your 2nd example.
>
> Stop confusing me ;-) Just before writing the mail, I had a look at my  
> dictionary because I've never managed to know how those following  
> symbols are called in english:
>
> () [] {}
>
> My dictionary told me:
>
> () brackets or parenthesis (for US)
> [] square brackets
> {} braces or curly brackets
>
> When I said: 'so brackets are not possible in this example', I meant  
> parenthesis :-)
>
> Two minutes ago, I verified in wikipedia and it seems that 'Bracket' is  
> the superclass of Parenthesis.
>
> Which one is correct :-) ?

The comments in Smalltalk code are correct. But if in doubt, the Blue Book  
ultimatively is correct: you will find parentheses and brackets explained  
in chapter #2, Expression Syntax.

This way all Smalltalkers can talk about the same things using the same  
names, even if none of them has ever seen *your* dictionary and even if  
the wikipedia server is down ;-)

/Klaus


Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

timrowledge
In reply to this post by Lukas Renggli
Cascading allows a sequence of message sends to be 'stacked up' for  
sending to the same receiver. If you look at the EBNF spec (as shown  
in the Blue Book) for cascading you will see that it allows for
receiver
        message send;
        message send;
        ....
A message send is a *single* message send to receiver and so the  
final 'size negated' in the original example given clearly doesn't  
count. I suspect there is a tendency to allow some C-think to creep  
in and treat the semi-colon as some sort of statement separator.
Note that you *can* do things like
|test|
test:=OrderedCollection with: 'first'.
test
   add: 'second', 'third';
   size
because the 'second','third' is not a message send to 'test' but a  
separate clause that gets evaluated earlier.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Java:  the best argument for Smalltalk since C++



Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Nicolas Cellier-3
In reply to this post by Damien Cassou-3
Hi tim,
It has nothing to deal with C, but rather with streaming...
Streaming has a natural correspondance with cascading messages.
But in situations when you just want to make code a little bit complex, you are forced to insert variables and make code less readable than would be a simple cascade...
That's the only reason.
Lukas provided a brilliant illustrating example.

Nicolas


Le Jeudi 17 Août 2006 18:49, tim Rowledge a écrit :

> Cascading allows a sequence of message sends to be 'stacked up' for
> sending to the same receiver. If you look at the EBNF spec (as shown
> in the Blue Book) for cascading you will see that it allows for
> receiver
>  message send;
>  message send;
>  ....
> A message send is a *single* message send to receiver and so the
> final 'size negated' in the original example given clearly doesn't
> count. I suspect there is a tendency to allow some C-think to creep
> in and treat the semi-colon as some sort of statement separator.
> Note that you *can* do things like
>
> |test|
>
> test:=OrderedCollection with: 'first'.
> test
>    add: 'second', 'third';
>    size
> because the 'second','third' is not a message send to 'test' but a
> separate clause that gets evaluated earlier.
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Java:  the best argument for Smalltalk since C++


________________________________________________________________________
iFRANCE, exprimez-vous !
http://web.ifrance.com


Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

Damien Cassou-3
In reply to this post by Lukas Renggli
Lukas Renggli wrote:

>> >> test:= MyObjectModel
>> >> test
>> >>    getAllChanges;
>> >>    storageStrategy storeNow;
>> >>    readyToContinue
>> >>
>> I know how to make it work in fact. What I don't understand is why the
>> smalltalk doesn't allow this kind of construction.
>
> Because it is ambiguous. How should the compiler know if it should
> send #readyToContinue to 'test' or the result of 'test
> storageStrategy'?

You mean something like:

test:= MyObjectModel
test
   getAllChanges;
   storageStrategy
     storeNow;
     readyToContinue


Yes, you are perfectly right. Thank you

Reply | Threaded
Open this post in threaded view
|

RE: Re: Cascading ?

Ramon Leon-5
In reply to this post by Lukas Renggli
> html div
>      id: 'foo';
>      class: 'border';
>      in: [ :tag | condition ifTrue: [ tag class: 'red' ] ];
>      with: 'contents'
>

That's a nice trick Lucas, now I have to go rewrite a bunch of code, damn!


Reply | Threaded
Open this post in threaded view
|

Re: Cascading ?

stéphane ducasse-2
In reply to this post by Lukas Renggli
yes much nicer to read

On 17 août 06, at 13:14, Lukas Renggli wrote:

> html div
>     idd: 'foo';
>     class: 'border';
>     class: 'red' if: condition;
>     with: 'contents'
>
> Such a refactoring can be always applied and is probably better
> practice than to start using blocks ...