First post here ... few days on Squeak ... some questions ....

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
134 messages Options
1234 ... 7
Reply | Threaded
Open this post in threaded view
|

First post here ... few days on Squeak ... some questions ....

Fabio Filasieno
II'm new at Smalltalk and I have a few questions.
"""Why smalltalk has no operator for piping ?""""

obj collect: [ :x | …] | filter: [:x | …] | select: [:x | …] ?

but has the `;` (cascade operator)?

I don’t care to send messages to the reciever of the previous  
message, because I return self when no return value is important; for  
instance ….

point x: 10 | y: 20 | z: 30

x returns self, y returns self, z returns self -> which is the  
updated point.

works exactly as:

point x:10;  y:20 ;  z:30.

But you lose PIPES !!!!! Can somebody elaborate on this ?

There might be cases where I'm returning a value and I wish to  
discard it and then send again to the previous receiver ... but I  
really don't like to loose the pipe for that ... since I can do that  
returning self.

With Smalltalk ... we've got a homoiconic language and the system  
written in it self, a consistent language in everything, even the if-
then-else that everybody else still don't get right; we've got the  
most wonderful programming experience of all, even better that Ruby/
Python etc ...

but why on earth we have the "cascade operator" instead of the  
PIPE ?????
What I'm I missing ?

I need the `|` to avoid parenthesis, and weird hacks ...

Fabio
Reply | Threaded
Open this post in threaded view
|

Re: pipe

Tapple Gao
On Fri, Aug 24, 2007 at 10:57:48PM +0200, Fabio Filasieno wrote:
> II'm new at Smalltalk and I have a few questions.
> """Why smalltalk has no operator for piping ?""""
>
> obj collect: [ :x | ?] | filter: [:x | ?] | select: [:x | ?] ?

I don't understand what a pipe is or should do, other than save
a few parentheses. I am guessing you want the above to be
equivilant to
 (( obj collect: [ :x | ?] ) filter: [:x | ?] ) select: [:x | ?]

(by the way, filter: is not a Smalltalk message)

One reason there is no pipe operator is that '|' is a valid
message and has many implementors in the image already.

More importantly, the above chain of messages is bordering on
the comprehensable and should probably be split up into more
statements or methods.

> but has the `;` (cascade operator)?
>
> I don?t care to send messages to the reciever of the previous  
> message, because I return self when no return value is important; for  
> instance ?.
>
> point x: 10 | y: 20 | z: 30
>
> x returns self, y returns self, z returns self -> which is the  
> updated point.
>
> works exactly as:
>
> point x:10;  y:20 ;  z:30.
>
> But you lose PIPES !!!!! Can somebody elaborate on this ?
>
> There might be cases where I'm returning a value and I wish to  
> discard it and then send again to the previous receiver ... but I  
> really don't like to loose the pipe for that ... since I can do that  
> returning self.

You raise a fair point; most messages retrurn self anyway, and
they are the ones that ; is usually used with anyway, so it is a
bit redundant.

> With Smalltalk ... we've got a homoiconic language and the system  
> written in it self, a consistent language in everything, even the if-
> then-else that everybody else still don't get right; we've got the  
> most wonderful programming experience of all, even better that Ruby/
> Python etc ...
>
> but why on earth we have the "cascade operator" instead of the  
> PIPE ?????
> What I'm I missing ?
>
> I need the `|` to avoid parenthesis, and weird hacks ...

Like what?

What do you mean by pipes? Are you refering to some kind of
streaming like in bash where output can be generated from one
process and input to another with finite memory? If so, I am not
sure that is possible in general; objects are not always
serializable.

What kind of use case do you have in mind?

--
Matthew Fulmer -- http://mtfulmer.wordpress.com/
Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Igor Stasenko
> > I need the `|` to avoid parenthesis, and weird hacks ...
>
> Like what?
>
> What do you mean by pipes? Are you refering to some kind of
> streaming like in bash where output can be generated from one
> process and input to another with finite memory? If so, I am not
> sure that is possible in general; objects are not always
> serializable.
>
> What kind of use case do you have in mind?
>
let me elaborate:

a message1 | message2

is equal to:

a message1 message2

and:

a message1: param | message2: param2

is equeal to:

(a message1: param) message2: param2


and as you can see writing code with so-called 'pipes' makes code much cleaner


> --
> Matthew Fulmer -- http://mtfulmer.wordpress.com/
> Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808
>
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Blake-5
On Fri, 24 Aug 2007 19:39:17 -0700, Igor Stasenko <[hidden email]>  
wrote:

> a message1 | message2
>
> is equal to:
>
> a message1 message2
>
> and:
>
> a message1: param | message2: param2
>
> is equeal to:
>
> (a message1: param) message2: param2
>
> and as you can see writing code with so-called 'pipes' makes code much  
> cleaner

Huh. I don't see it. The first one...okay, I guess, maybe.

But the parens in the ST in the second one are almost a graphic  
representation of the object being created, to which the message2 is being  
passed.

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Tapple Gao
In reply to this post by Igor Stasenko
On Sat, Aug 25, 2007 at 05:39:17AM +0300, Igor Stasenko wrote:

> > > I need the `|` to avoid parenthesis, and weird hacks ...
> >
> > Like what?
> >
> > What do you mean by pipes? Are you refering to some kind of
> > streaming like in bash where output can be generated from one
> > process and input to another with finite memory? If so, I am not
> > sure that is possible in general; objects are not always
> > serializable.
> >
> > What kind of use case do you have in mind?
> >
> let me elaborate:
>
> a message1 | message2
>
> is equal to:
>
> a message1 message2
>
> and:
>
> a message1: param | message2: param2
>
> is equeal to:
>
> (a message1: param) message2: param2
>
>
> and as you can see writing code with so-called 'pipes' makes code much cleaner

Those two examples are exactly the same length in characters, so
I don't see what metric qualifies one as much cleaner than the
other.

Parenthesis are not very common in squeak, and this would be
less common as parenthesis. Parentheses are more general
too; you could not do this with pipes:

dict at: (self keyFor: anItem) put: 3

I am really missing what the point of this is

--
Matthew Fulmer -- http://mtfulmer.wordpress.com/
Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Igor Stasenko
On 25/08/07, Matthew Fulmer <[hidden email]> wrote:

> On Sat, Aug 25, 2007 at 05:39:17AM +0300, Igor Stasenko wrote:
> > > > I need the `|` to avoid parenthesis, and weird hacks ...
> > >
> > > Like what?
> > >
> > > What do you mean by pipes? Are you refering to some kind of
> > > streaming like in bash where output can be generated from one
> > > process and input to another with finite memory? If so, I am not
> > > sure that is possible in general; objects are not always
> > > serializable.
> > >
> > > What kind of use case do you have in mind?
> > >
> > let me elaborate:
> >
> > a message1 | message2
> >
> > is equal to:
> >
> > a message1 message2
> >
> > and:
> >
> > a message1: param | message2: param2
> >
> > is equeal to:
> >
> > (a message1: param) message2: param2
> >
> >
> > and as you can see writing code with so-called 'pipes' makes code much cleaner
>
> Those two examples are exactly the same length in characters, so
> I don't see what metric qualifies one as much cleaner than the
> other.
>

try write following using pipes and see the difference. The point is
not a number of characters , but how easy you can read the code:

(((a message1: param1) message2:param2) ifTrue: [ b ] ifFalse: [ c ])
message3:param3


> Parenthesis are not very common in squeak, and this would be
> less common as parenthesis. Parentheses are more general
> too; you could not do this with pipes:
>
> dict at: (self keyFor: anItem) put: 3
>
no, you can't do this with pipes. pipes is like a cascade, but with
same message passing semantics like regular continuation and allow you
to mix binary or keyword messages in one continuation without using
parenthesis:

a + b | mixWith: c | squared + 5



> I am really missing what the point of this is
>
> --
> Matthew Fulmer -- http://mtfulmer.wordpress.com/
> Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808
>
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: First post here ... few days on Squeak ... some questions ....

Matthias Berth-2
In reply to this post by Fabio Filasieno
Hi Fabio,


welcome to the list! I guess what you would express with pipes would
be written in Smalltalk like this?

(((obj collect: [ :x | …])
   filter: [:x | …] )
      select: [:x | …])

And with a pipe operator you would save a few parntheses here?

With unary message sends, the syntax gives you a kind of piping for
free, just chain the messages:

'abc' reverse first isVowel

With keyword messages the syntax is in favor of multiple keyword
message selectors:

'abc' detect: [:a | a isVowel] ifAbsent: ['']

is the message #detect:ifAbsent: and not a cascade of two messages
#detect and #ifAbsent.

Smalltalk syntax was deliberately designed to be simple, based on a
few mechanisms. By the way, your pipe idea is reflected in some
methods in the collection hierarchy:

Collection>>select:thenDo:
Collection>>select:thenCollect:


Cheers

Matthias

On 8/24/07, Fabio Filasieno <[hidden email]> wrote:

> II'm new at Smalltalk and I have a few questions.
> """Why smalltalk has no operator for piping ?""""
>
> obj collect: [ :x | …] | filter: [:x | …] | select: [:x | …] ?
>
> but has the `;` (cascade operator)?
>
> I don't care to send messages to the reciever of the previous
> message, because I return self when no return value is important; for
> instance ….
>
> point x: 10 | y: 20 | z: 30
>
> x returns self, y returns self, z returns self -> which is the
> updated point.
>
> works exactly as:
>
> point x:10;  y:20 ;  z:30.
>
> But you lose PIPES !!!!! Can somebody elaborate on this ?
>
> There might be cases where I'm returning a value and I wish to
> discard it and then send again to the previous receiver ... but I
> really don't like to loose the pipe for that ... since I can do that
> returning self.
>
> With Smalltalk ... we've got a homoiconic language and the system
> written in it self, a consistent language in everything, even the if-
> then-else that everybody else still don't get right; we've got the
> most wonderful programming experience of all, even better that Ruby/
> Python etc ...
>
> but why on earth we have the "cascade operator" instead of the
> PIPE ?????
> What I'm I missing ?
>
> I need the `|` to avoid parenthesis, and weird hacks ...
>
> Fabio
>

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Fabio Filasieno
In reply to this post by Igor Stasenko

On Aug 25, 2007, at 4:39 AM, Igor Stasenko wrote:

let me elaborate:


a message1 | message2


is equal to:


a message1 message2


and:


a message1: param | message2: param2


is equeal to:


(a message1: param) message2: param2



and as you can see writing code with so-called 'pipes' makes code much cleaner



Igor expressed what I'm after....


On Aug 25, 2007, at 4:43 AM, Blake wrote:
But the parens in the ST in the second one are almost a graphic representation of the object being created, to which the message2 is being passed.


Look down ... the graphic representation is a poor one because It's too costly: too may parenthesis. 

On Aug 25, 2007, at 4:51 AM, Matthew Fulmer wrote:
Those two examples are exactly the same length in characters, so
I don't see what metric qualifies one as much cleaner than the
other.


check this out ... 

(((((((((((obj message1: param) message2:param) message1: param) message2:param) message1: param) message2:param) message1: param) message2:param) message1: param) message2:param) message1: param) message2:param

there is this thing > (((((((((((( 

now look the cleaner 
pipe ....
obj message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param

now some mix and match ...

obj | send
       | left: a right:b
       | send | send | send
       | left: a right:b
       | message

The pipe is needed to support a pipe&filter style of programming. That perfectly works with Smalltalk syntax, and truly
opens up a better way of doing functional transformations.


On Aug 25, 2007, at 4:51 AM, Matthew Fulmer wrote:
Parenthesis are not very common in squeak, and this would be
less common as parenthesis. Parentheses are more general
too; you could not do this with pipes:

dict at: (self keyFor: anItem) put: 3

I am really missing what the point of this is

It's less general but since functional transformations are a very powerful idiom (Haskells monads, Haskells Arrows, 
the Unix pipe, ... just to name a few) a little help from the language would be nice. 
It' not a parentesis vs pipe problem, it's a pipe vs cascade. Why ST has the cascade ? Can someone explain it me ... Why need a special operator for that ? I don't care about cascading... but maybe there is something I'm missing.

 Parentheses are more general too

Use Lisp than. Everything is a pair... and you'll have as many general parenthesis you want :-p ....  just joking ... I see you point but ... my argument is not pipe vs parenthesis, but pipe vs cascade, because I want the the pipe&filter style of programming 

I state that:

 >>>>>>>>> cascade is useless <<<<<<<<<<<<

because it's redundant :

Example :

point x:10; y:10; z:10. 

Your could write in fact.
(((point x:10) y:10) z:10)
since x:10 returns self anyway, y:10 returns self anyway and z:10 returns self anyway.

but thanks to the ";" (cascade) you can write ...
point x:10; y:10; z:10. 

Then I say ... ok so the designer wants to remove those ugly parenthesis ...
why not do a better job by using a more general operator ??

I can do the cascade stuff ...

point x:10 | y:10 | z:10

and .. magic ...
I can do better functional transformations, pipe&filters style.

obj message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param
     | message1: param
     | message2:param

With the pipe I removed parenthesis from much wider selection of cases, I enable a cleaner way of writing functional transformations, and therefore it's a better design.

Fabio's proposal:

make the ";" cascade operator send the message not the the previous receiver but to the object returned by the previous message send.



Fabio Filasieno






Reply | Threaded
Open this post in threaded view
|

Re: First post here ... few days on Squeak ... some questions ....

Fabio Filasieno
In reply to this post by Matthias Berth-2

On Aug 25, 2007, at 10:43 AM, Matthias Berth wrote:

> Hi Fabio,
>
>
> welcome to the list!

Thanks :-). Love to be here.

> (((obj collect: [ :x | …])
>    filter: [:x | …] )
>       select: [:x | …])
>
> And with a pipe operator you would save a few parntheses here?
>

Yes but there is a problem with that.
to quote you:

"
(((point x:10) y:20) z:10)

And with a cascade operator you would save a few parntheses here?
"
I'm not on the `pipe vs parenthesis problem`, but `pipe vs cascade`.


> With unary message sends, the syntax gives you a kind of piping for
> free, just chain the messages:
>
> 'abc' reverse first isVowel
>

Ahaaaaa.... :-D ... got you ... so you DO like functional  
transformations...
Then why not ...

'abc' reverse first isVowel asChars
          | filter: [ :char | char isCaps]
          | fold: [: xxx | ... ] with: 0 | toList
          | collect: [:number | number + 1]

(messages are invented)

>
> Smalltalk syntax was deliberately designed to be simple, based on a
> few mechanisms. By the way, your pipe idea is reflected in some
> methods in the collection hierarchy:
>
> Collection>>select:thenDo:
> Collection>>select:thenCollect:

This is very very ugly ... It's like hardcoding.
Dump all those do:thenDo:thenDo. It's the ugliest part of smalltalk.
I saw posts on the internet with the same argument and I don't buy it.

I't the hardcoded sequence that sucks.

The pipe is what made Unix powerful ... imagine a Unix system where  
you need
to hardcode compositions of processes.

example:
Do your prefer  to have  ...

ls
grep
lsThenGrep

or

lr
grep
ls ... | grep ...

??

I want flexible compositions !

Just dump the cascade for the pipe ... and you have just added to  
smalltalk
part of the power of the unix pipe&filter.

It's better because the cascade is redundant.

(((point x:10) y:10) z:10) ... see it's redundant (it's might be in  
95% of cases, I don't have stats).

Can anyone do a stat on Smalltalk messages
to see how many times the cascade operator is used and the previous  
message
returns self ? If this number is very high(say 90-95%) then this  
would prove that the cascade operator
is useless, as parenthesis could be used;
then we would need a way to reduce parenthesis and an interesting  
solution would be the Pipe operator.

we could get cascading

point x:10 | y:10 |  z:10...

and get for free pipes & filters

x select: [:item | ... ]
    | collect: [:item | ...]
    | doThis doThat
    | fold: [:item | ...] with:0
    | mailItto: 'xxxx'
    | log: [ :result | .... ]

Cascading is redundant if the previous message returns self as  
parenthesis could be used.
In MY case, ALL cascade operations are redundant as I use them for  
setting properties during object initialization, therefore returning  
self.
Since cascading is redundant (in my case), therefore we can remove  
the cascade operator.
No we need a better way reduce parenthesis in as many cases as  
possible. The pipe happens to work quite well as I can both do the  
initialization of objects AND it supports the flexible pipe & filters  
style.

proposal ...


make the ";" cascade operator send the message not the the previous  
receiver but to the object returned by the previous message send.




Fabio


Reply | Threaded
Open this post in threaded view
|

Re: pipe

Joshua Gargus-2
In reply to this post by Fabio Filasieno

On Aug 25, 2007, at 6:17 AM, Fabio Filasieno wrote:

>
> obj message1: param
>      | message2:param
>      | message1: param
>      | message2:param
>      | message1: param
>      | message2:param
>      | message1: param
>      | message2:param
>      | message1: param
>      | message2:param
>      | message1: param
>      | message2:param
>
> now some mix and match ...
>
> obj | send
>        | left: a right:b
>        | send | send | send
>        | left: a right:b
>        | message
>
> The pipe is needed to support a pipe&filter style of programming.  
> That perfectly works with Smalltalk syntax, and truly
> opens up a better way of doing functional transformations.
>

This all seems very hypothetical.  In what problem domain would you  
end up writing code like this?  I've never written such code myself,  
and I haven't seen anyone else write such code either.  Maybe that's  
just because people shy away from it because of all of the  
parentheses, but I can't accept that without a real code example to  
support it.

Josh

Reply | Threaded
Open this post in threaded view
|

Re: First post here ... few days on Squeak ... some questions ....

Jason Johnson-5
In reply to this post by Fabio Filasieno
On 8/25/07, Fabio Filasieno <[hidden email]> wrote:
>

Hi, welcome to the list and Smalltalk. :)

> I'm not on the `pipe vs parenthesis problem`, but `pipe vs cascade`.

There is no "pipe vs cascade" problem.  In Smalltalk the language is
based sending messages to objects.  If you want to send a message to
the result of the last send then you can just do it.  If you wish
instead to send more messages to a previous object you can use the
cascade operator.

So if you want "pipe" behavior you have it already.  The only time
parenthesis are needed is when there is ambiguity about evaluation
order.

Haskell uses the $ operator to reduce the need to have parenthesis in
a manner you're suggesting.

> Ahaaaaa.... :-D ... got you ... so you DO like functional
> transformations...

Of course, Smalltalk is full of them.

> This is very very ugly ... It's like hardcoding.
> Dump all those do:thenDo:thenDo. It's the ugliest part of smalltalk.
> I saw posts on the internet with the same argument and I don't buy it.

These are just convenience methods.

> Just dump the cascade for the pipe ... and you have just added to
> smalltalk
> part of the power of the unix pipe&filter.
>
> It's better because the cascade is redundant.

In what way?

>
> (((point x:10) y:10) z:10) ... see it's redundant (it's might be in
> 95% of cases, I don't have stats).

Are you sure you know what the cascade operator is doing?  It can't be
redundant because there is no other way to do what it's doing without
using temp variables.

E.g. if "point x: 10" returns 10 then you can't go:

(point x: 10) y: 10

because the "y: 10" goes to the other 10.  You must either use
different statements as in:

point x: 10.
point y: 10.
"..."

Or you can use the cascade operator as in:

point x: 10; y: 10.

So where is the redundancy?

> Cascading is redundant if the previous message returns self as
> parenthesis could be used.
> In MY case, ALL cascade operations are redundant as I use them for
> setting properties during object initialization, therefore returning
> self.
> Since cascading is redundant (in my case), therefore we can remove
> the cascade operator.

Lol.  *You* don't need cascading so we should break with the Smalltalk
80 spec, break backward compatibility with.... pretty much all
Smalltalk code written until now, and have to type out verbose repeat
statements over and over since we have no cascade operator anymore?
Does that really seem logical/realistic to you?

My suggestion would be to learn the language before redesigning it. ;)

Reply | Threaded
Open this post in threaded view
|

Re: First post here ... few days on Squeak ... some questions ....

Jason Johnson-5
Oh and by the way, you may have heard about the Seaside framework
that's gaining popularity right now.  The API it uses to create HTML
is built around the cascade operator.

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Jason Johnson-5
In reply to this post by Igor Stasenko
On 8/25/07, Igor Stasenko <[hidden email]> wrote:

> >
> let me elaborate:
>
> a message1 | message2
>
> is equal to:
>
> a message1 message2
>
> and:
>
> a message1: param | message2: param2
>
> is equeal to:
>
> (a message1: param) message2: param2
>
>
> and as you can see writing code with so-called 'pipes' makes code much cleaner

It is true that it can be nice to avoid using so many parenthesis.
This is why Haskell made the $ operator which does precisely the same
thing.

But this issue has nothing to do with the very useful and needed
cascade operator.

Reply | Threaded
Open this post in threaded view
|

RE: pipe

Gary Chambers-4
I think the simplicity of operator precedence more than makes up for the
extra parentheses IMHO. Though the cascade operator is a special case, in a
way!

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Jason
Johnson
Sent: 25 August 2007 7:18 pm
To: The general-purpose Squeak developers list
Subject: Re: pipe


On 8/25/07, Igor Stasenko <[hidden email]> wrote:

> >
> let me elaborate:
>
> a message1 | message2
>
> is equal to:
>
> a message1 message2
>
> and:
>
> a message1: param | message2: param2
>
> is equeal to:
>
> (a message1: param) message2: param2
>
>
> and as you can see writing code with so-called 'pipes' makes code much
> cleaner

It is true that it can be nice to avoid using so many parenthesis. This is
why Haskell made the $ operator which does precisely the same thing.

But this issue has nothing to do with the very useful and needed cascade
operator.


Reply | Threaded
Open this post in threaded view
|

Re: pipe

Jason Johnson-5
In reply to this post by Igor Stasenko
On 8/25/07, Igor Stasenko <[hidden email]> wrote:
> > > >
> no, you can't do this with pipes. pipes is like a cascade, but with
> same message passing semantics like regular continuation and allow you
> to mix binary or keyword messages in one continuation without using
> parenthesis:
>
> a + b | mixWith: c | squared + 5

Well, pipe is probably a bad name for this.  It is a statement
delimiter symbol like . or ; but it is short hand for allowing one to
send a message to the result of the previous expression.

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Jason Johnson-5
In reply to this post by Fabio Filasieno
On 8/25/07, Fabio Filasieno <[hidden email]> wrote:
>
> check this out ...
>
> (((((((((((obj message1: param) message2:param) message1: param)
> message2:param) message1: param) message2:param) message1: param)
> message2:param) message1: param) message2:param) message1: param)
> message2:param

This is a bit contrived.  If you ever did find the need to do this it
should look like:


(((((((((((obj message1: param)
  message2:param)
    message1: param)
      message2:param)
        message1: param)
          message2:param)
            message1: param)
              message2:param)
                message1: param)
                  message2:param)
                    message1: param)
                      message2:param

Code smell to be sure, but you pile what you don't like on one line
and say you can't read it while formatting what you do like and saying
"see!".

> The pipe is needed to support a pipe&filter style of programming. That
> perfectly works with Smalltalk syntax, and truly
> opens up a better way of doing functional transformations.

pipe&filter style of programming?  Most people call this "functional
programming" and it doesn't require a pipe operator to work.  Such an
operator can make certain code cleaner to be sure, but it doesn't
"open up a better way of doing functional transforms" by any means.
Just saves you one character per function call.

>  >>>>>>>>> cascade is useless <<<<<<<<<<<<
>
> because it's redundant :
>
> Example :
>
> point x:10; y:10; z:10.
>
> Your could write in fact.
> (((point x:10) y:10) z:10)
> since x:10 returns self anyway, y:10 returns self anyway and z:10 returns
> self anyway.

In this case yes, one could use parenthesis, the cascade operator or a
new statement delimiter (which you call "pipe").  But sometimes you
wish to send a bunch of messages to an object that may not return
self.

> With the pipe I removed parenthesis from much wider selection of cases, I
> enable a cleaner way of writing functional transformations, and therefore
> it's a better design.

You don't have a conflict between cascade and your "pipe" unless you
want to use the ; symbol.  Cascade is a special message that causes
the compiler to put in some op codes for duplicating the cascaded
object on the stack.  What you want is just the current behavior
without needing the parenthesis to disambiguate.  I don't think it
would be too hard to add a new symbol that has the compiler treat it's
left side the same as it would if the statement was in parenthesis.

Reply | Threaded
Open this post in threaded view
|

Re: pipe

Fabio Filasieno
In reply to this post by Jason Johnson-5

On Aug 25, 2007, at 8:23 PM, Jason Johnson wrote:

On 8/25/07, Igor Stasenko <[hidden email]> wrote:

no, you can't do this with pipes. pipes is like a cascade, but with
same message passing semantics like regular continuation and allow you
to mix binary or keyword messages in one continuation without using
parenthesis:

a + b | mixWith: c | squared + 5

Well, pipe is probably a bad name for this.  It is a statement
delimiter symbol like . or ; but it is short hand for allowing one to
send a message to the result of the previous expression.


You are totally right ... since it was close to the Unix pipe I just called ... .pipe ...
But it would be a delimiter exactly as you say.

Fabio





Reply | Threaded
Open this post in threaded view
|

Re: pipe

Alan Kay
In reply to this post by Jason Johnson-5
Just a kibitz from the peanut gallery....

It's not a question of functionality, but of simple readability and
writeability. This idea has come up a number of times in the past,
and it is a very reasonable one. In fact, there are a number of other
perfectly reasonable additions that would be nice to have in
Smalltalk. The basic idea of having a flat precedence for binary
operators came from the same practice in APL -- if you have a zillion
of them, then just using grouping instead of precedence can be a
reasonable solution.

But, for example, the "." could be considered to be a kind of
operator (that is like a procedural "AND") that tests to see if the
previous expression SUCCEEDed before moving to the next expression.
We could think of it as being defined in Class Object. If we think of
"precedence" then we want everything else in expressions to be more
closely bound.

This opens up the possibility of having something like "|" (apologies
for using this for a different purpose) to deal with the "OR" case.
So if an expression FAILs, then the OR path will be taken. It is easy
to see why we should use precedence ideas here to avoid parentheses.

Note that the overloading of these operators with a little more
processing could lead both to a "Prolog" way of thinking about things
on the one hand, and a way to think of parsing and searching, on the
other. Both of these would be great additions to the basic semantics
of Smalltalk.

And so would pipes. They provide a syntactical way of writing very
useful sequences of processing that is much nicer than functional
application syntax (which gives a difficult to read "backwards
view"), and Haskell did absolutely the right thing in making an
operator for this.

Since Squeak is a completely open Smalltalk, and intended to be
extended in major as well as minor ways, there is no reason
whatsoever to prevent these ideas and more to be added (and I wish
that people would take it upon themselves to extend the language).

Cheers,

Alan

At 11:40 AM 8/25/2007, Jason Johnson wrote:

>On 8/25/07, Fabio Filasieno <[hidden email]> wrote:
> >
> > check this out ...
> >
> > (((((((((((obj message1: param) message2:param) message1: param)
> > message2:param) message1: param) message2:param) message1: param)
> > message2:param) message1: param) message2:param) message1: param)
> > message2:param
>
>This is a bit contrived.  If you ever did find the need to do this it
>should look like:
>
>
>(((((((((((obj message1: param)
>   message2:param)
>     message1: param)
>       message2:param)
>         message1: param)
>           message2:param)
>             message1: param)
>               message2:param)
>                 message1: param)
>                   message2:param)
>                     message1: param)
>                       message2:param
>
>Code smell to be sure, but you pile what you don't like on one line
>and say you can't read it while formatting what you do like and saying
>"see!".
>
> > The pipe is needed to support a pipe&filter style of programming. That
> > perfectly works with Smalltalk syntax, and truly
> > opens up a better way of doing functional transformations.
>
>pipe&filter style of programming?  Most people call this "functional
>programming" and it doesn't require a pipe operator to work.  Such an
>operator can make certain code cleaner to be sure, but it doesn't
>"open up a better way of doing functional transforms" by any means.
>Just saves you one character per function call.
>
> >  >>>>>>>>> cascade is useless <<<<<<<<<<<<
> >
> > because it's redundant :
> >
> > Example :
> >
> > point x:10; y:10; z:10.
> >
> > Your could write in fact.
> > (((point x:10) y:10) z:10)
> > since x:10 returns self anyway, y:10 returns self anyway and z:10 returns
> > self anyway.
>
>In this case yes, one could use parenthesis, the cascade operator or a
>new statement delimiter (which you call "pipe").  But sometimes you
>wish to send a bunch of messages to an object that may not return
>self.
>
> > With the pipe I removed parenthesis from much wider selection of cases, I
> > enable a cleaner way of writing functional transformations, and therefore
> > it's a better design.
>
>You don't have a conflict between cascade and your "pipe" unless you
>want to use the ; symbol.  Cascade is a special message that causes
>the compiler to put in some op codes for duplicating the cascaded
>object on the stack.  What you want is just the current behavior
>without needing the parenthesis to disambiguate.  I don't think it
>would be too hard to add a new symbol that has the compiler treat it's
>left side the same as it would if the statement was in parenthesis.


Reply | Threaded
Open this post in threaded view
|

Re: pipe

Fabio Filasieno
In reply to this post by Jason Johnson-5

On Aug 25, 2007, at 8:40 PM, Jason Johnson wrote:

This is a bit contrived.  If you ever did find the need to do this it

should look like:



(((((((((((obj message1: param)

  message2:param)

    message1: param)

      message2:param)

        message1: param)

          message2:param)

            message1: param)

              message2:param)

                message1: param)

                  message2:param)

                    message1: param)

                      message2:param


Code smell to be sure, but you pile what you don't like on one line

and say you can't read it while formatting what you do like and saying

"see!".


To me there is not much difference between ...
(((((((((((obj message1: param)
  message2:param)
    message1: param)
      message2:param)
        message1: param)
          message2:param)
            message1: param)
              message2:param)
                message1: param)
                  message2:param)
                    message1: param)
                      message2:param

and 

(((((((((((obj message1: param) message2:param) message1: param) message2:param) message1: param) message2:param) message1: param) essage2:param) message1: param) message2:param) message1: param) message2:param

1. They both suck ...
2. While writing and thinking ... I have always to stop and think ... "ok, now where do I need to put the bloody parenthesis"



The pipe is needed to support a pipe&filter style of programming. That

perfectly works with Smalltalk syntax, and truly

opens up a better way of doing functional transformations.


pipe&filter style of programming?  Most people call this "functional

programming" and it doesn't require a pipe operator to work.  Such an

operator can make certain code cleaner to be sure, but it doesn't

"open up a better way of doing functional transforms" by any means.

Just saves you one character per function call.



I call it too functional programming ... but there are many definitions of it ...
for somebody functional programming is no side-effects and nothing else,
for others higher order functions is ok ...

since I didn't want to get into that, I just said pipe&filters ... i thought it was alright ... thanks for this clarification ... now everybody now we are talking about ...

Such an operator can make certain code cleaner to be sure, but it doesn't
"open up a better way of doing functional transforms" by any means.
Just saves you one character per function call.

Not only it can make " certain code cleaner" , but It changes the way you think, because it's like the full stop in regular English ...

Simple train of thought example ...

----
>>here I'm Thinking<<
here I'm doing
----


>>ok so what do I have to do ... first get I get some objects<<<

storage getSomeObject >> than .... (and I put my pipe symbol ) ... put a PIPE <<
           | 

Already here it cool ...I don't have to ... think .. "Gee I need to go back and put a parenthesis .."

........

storage   getSomeCollection >> than .... aaaaand PIPE <<
              | filter: [:obj | obj creationDate >10]     >>>>> some more mumble mumble .... aaaaaand PIPE<<
              | collect: [:obj | obj.name]        >>>>  some more mumble mumble .... and PIPE <<
>> .... her some more mumble mumble .... because I'm not sure what to do BUT 
I do know that I've got some names.... I never need to go back and put parenthesis .. and this does not break my thoughts ....<<<<

......

storage   getSomeCollection >>> than .... (and I put my pipe symbol ) <<<
              | filter: [:obj | obj creationDate >10]     >>>>> than .... (and I put my pipe symbol )... and PIPE <<
              | collect: [:obj | obj.name]        >>>>than .... (and I put my pipe symbol )... and PIPE<<
              | filter: [:name | name isFemale ]
              | filter: [:name | beutifullGirlsDB contains:name ] 
              | do: [:name | mailTo: (beutifullGirlsDB getWithName:name) message: "What are you doing tonight ?" ] 
>>>mmm ... I could do a few things better ... filter and collect less ... so I'll do another pass ....
At this point I might write a Unit test and later I'll make it faster ...
 etc etc ....<<<

---------------------------------

To me it's like a full stop in english. Maybe you are different. But I think that most people like full stops when a sentence ends.


The pipe is the full stop ... ready to start the next manipulation ...





Fabio Filasieno







Reply | Threaded
Open this post in threaded view
|

Re: pipe

Igor Stasenko
In reply to this post by Alan Kay
As observation..

This discussion is a good example of purists who trowing away any new
ideas just because they 'don't follow standard' or 'can be done with
current syntax'.

Honestly i see no harm in adding a pipe '|' symbol as a special syntax
symbol, like cascade ';' or period '.'
A pipe is like continuation which simply does: evaluate expression to
the left, then continue evaluation with expression to the right,
taking left result as receiver.
We need only minor changes to parser to add this syntax sugar, and no
changes in complier because it don't breaks old syntax or message
passing semantics.

1234 ... 7