On 8/25/07, Igor Stasenko <[hidden email]> wrote:
> 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'. I certainly hope you didn't mean me by this observation. :) I have no problem with a "forced evaluation" operator. My issue is stating in a load voice that the cascade operator is useless and we should ditch it in favor of the new schematics. |
In reply to this post by Hans-Martin Mosner
On 8/25/07, Hans-Martin Mosner <[hidden email]> wrote:
> > You might get away with ! which is a legal binary selector in current > Smalltalk but is not used anywhere in a standard Squeak image. No! I want that for my planned message send operator. :) > I'm still not convinced that > object someMessage ! message1: arg1 ! message2 > is that much better readable than > ((object someMessage) message1: arg1) message2 > especially since more than one or two levels of parentheses are often a > sign of code smell. I don't like it for that either. But: SomeProcess ! someMessage is ok for me because at least one language works this way already. :) |
In reply to this post by Ramon Leon-5
Why not the $ operator? ! looks funny in the places it would be used
but $ has a president already. The only issue would be that Haskell programmers might get confused when they see it. In Haskell the application is right to left, in Smalltalk it is left to right. But not a big problem I would say. On 8/25/07, Alan Lovejoy <[hidden email]> wrote: > Since the selector #'|' is already taken for other purposes, why not use > #'!' instead (exclamation point instead of the bar)? > > > |
Heh..
you missed another character which can be used for new operator, its a colon ':' But i think its not very good choice, because colon already used to designate a keys in keyword message pattern. And single colon is never used in expressions. Maybe we should make a vote , which character (or char sequence) is the best? For me, there's no matter how it will look like, its a matter how it works. On 26/08/07, Jason Johnson <[hidden email]> wrote: > Why not the $ operator? ! looks funny in the places it would be used > but $ has a president already. > > The only issue would be that Haskell programmers might get confused > when they see it. In Haskell the application is right to left, in > Smalltalk it is left to right. But not a big problem I would say. > > On 8/25/07, Alan Lovejoy <[hidden email]> wrote: > > Since the selector #'|' is already taken for other purposes, why not use > > #'!' instead (exclamation point instead of the bar)? > > > > > > > > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Fabio Filasieno
On 8/25/07, Fabio Filasieno <[hidden email]> wrote:
> > a sequence of filter, map, fold, zip, ... it's extreamly common in any case > you have to do quite some collection manipulation. This kind of programming does come up often from folks who have a lot of functional programming experience (myself included). Sometimes you have an ordered collection and you need to do a series of transformations on it to get the set you want. And it does get annoying to have to keep piling on the parenthesis. But one reason others aren't sympathetic to this is probably because of the nature of Smalltalk. Most of the methods don't have that many statements. If you use the language for a while you will probably also find that once you end up with several statements grouped in the parenthesis that you could in fact use a part of those transformations/reductions/filtering somewhere else, and therefor should break some of it out to other methods. |
In reply to this post by Fabio Filasieno
On 8/26/07, Fabio Filasieno <[hidden email]> wrote:
> > I was a bit provocative because, I don't like the cascade and wanted to show > that you most of the time you could do with out it ... getting more out of > smalltalk ... There was no need to be provocative, and there is no need to get rid of the cascade operator. You don't like it, but it still provides something that requires temporary variables to duplicate without it. You state that it isn't needed because most of the message sends return self anyway, and this may in fact be true. But it might also be wrong. The cascade operator is a guarantee; I don't have to worry *what* the message send returns because I know the other messages I'm cascading go to the original object no matter what. Coming from a functional background, I'm sure you can appreciate the value of such a guarantee. :) > Please, this is really unfair. Nobody ever blamed anybody. We are just > having a good chat. My point was : the cascade operator sucks the pipe > rocks, and I've shown IMHO why it's better. And I love any critic I can get. > > Fabio Filasieno Your aggressive language comes off as blame, etc. And please stop saying "the cascade operator sucks". It's pure opinion and utterly irrelevant to the discussion of whether or not we need a "pipe" statement delimiter. |
In reply to this post by Igor Stasenko
I vote for $
It's only used for single characters otherwise so I don't think it's ambiguous (unless you can use it to specify the space character :( ). On 8/26/07, Igor Stasenko <[hidden email]> wrote: > Heh.. > you missed another character which can be used for new operator, its a colon ':' > But i think its not very good choice, because colon already used to > designate a keys in keyword message pattern. And single colon is never > used in expressions. > > Maybe we should make a vote , which character (or char sequence) is > the best? For me, there's no matter how it will look like, its a > matter how it works. > > > On 26/08/07, Jason Johnson <[hidden email]> wrote: > > Why not the $ operator? ! looks funny in the places it would be used > > but $ has a president already. > > > > The only issue would be that Haskell programmers might get confused > > when they see it. In Haskell the application is right to left, in > > Smalltalk it is left to right. But not a big problem I would say. > > > > On 8/25/07, Alan Lovejoy <[hidden email]> wrote: > > > Since the selector #'|' is already taken for other purposes, why not use > > > #'!' instead (exclamation point instead of the bar)? > > > > > > > > > > > > > > > > -- > Best regards, > Igor Stasenko AKA sig. > > |
In reply to this post by Jason Johnson-5
Duplicate... don't know. I think one temporary variable per activation should be enough, because you can overwrite it.
I can see that. But ... for example. collection := OrderedCollection new. collection add:1. evaluates to one. Why ? Why not to collection ? The collection library has been designed around the mechanics of the cascade operator. I need to now why. to me adding the ";" for... collection add:1; add:1; add:1; yourself. it's not enough. collection add:1 | add: 1 | add:1 at the cost (probably) of one more temporary. Considering the cost reflection, it's nothing. Who cares of the overhead of one temp? I need things like functional composition ... that is a big thing. functional composition is a GOOD reason for adding an operator. Consider this: if you were adding an operator in perl who cares. One more, one less. It doesn't make any difference. But in Smalltalk especially because is so small ... adding an operator is BIG thing. By doing that you are making quite a big statement to the users. If it was perl than it would be just ... "guys here is another one". But not in Smalltalk. To me it's like a godly voice saying ... "You shall use the mighty cascade operator .." and I say, ..."alright, let me see what cool things I can do ..." and the best thing I come up is ... collection add:1; add:1; add:1; yourself. mmm ... If you do the same thing with the Pipe ... instead ... at least to me ... the big godly statement is "You shall combine your object's methods" or "You shall use functional programming"
If you need guarantees than a strongly typed language is better. Why not having guarantees on types etc ... ? A working test is enough of a guarantee. Usually you don't worry about that 10 :append 10 fails, is it ? Why you worry that this could fail... collection add:1 | add: 1 | add:1 We got tests to take care of those problems. Smalltalk-80 is Smalltalk-80, with all it's libraries and design decisions. And that is fine. Cascade won't go away from there. But in a new Smalltalk ? would you keep it ? is there any reason we NEED the ";" operator ? or is just because it's now common use ... We do need the pipe, IMHO, for functional compositions. We do need the cascade operator ... for ... for what ? Not to break libraries and to have a cross vendor smalltalk ... is ok. then for what... I can't cover all cases of the cascade operator but something tells me that I might be able to reproduce the work ";" just be using ... an implied protocol. like ... collection add:1; add:1; add:1; yourself. well just say .. "in a new hypothetical ST we do it this way ..." collection add:1 | add: 1 | add:1 and overall the "|" could do the same thing and that other cases could be covered with another desing that would be extremely clean anyway.
Fair enough. I'll be more careful. But, if we where talking face to face you would see a smile on my face not an ... aggressive face. "The cascade operator sucks" ... ops... :o) Joking. I apologize to everybody for my language. Let me re-frase: if we would design today a NEW Smalltalk, the cascade operator might be an argument of discussion.
I tried to motivate quite a lot my opinion. I might say from my point of view it's pure opinion wether you NEED or not a "cascade" statement delimiter. I might even get convinced otherwise with some examples ... !!! At least I have tried to expose an issue with concrete examples on why the pipe is so important. No examples have come to defend the cascade... of course in a context of a new Smalltalk. This pipe thing is repeated in history too. Haskell's monads are not really a pipe thing, but the monadic bind (>>=) operator is really close to that. |
In reply to this post by Fabio Filasieno
On 8/26/07, Fabio Filasieno <[hidden email]> wrote:
> > So if you want "pipe" behavior you have it already. The only time > parenthesis are needed is when there is ambiguity about evaluation > order. > > No you don't ... > > This is ugly ... > ((( obj collect: [ :x | ....] ) filter: [:x | …] ) select: [:x | …]) > > This is beautiful ... > obj | collect: [ :x | ....] > | filter: [:x | …] > | select: [:x | …] Being ugly and not existing are two very different things. You do have it already, you just have to use parenthesis in the cases where it is ambiguous to the compiler. And I don't find the pipe that pretty as I know it as an "or" operator. > Haskell's $ is ugly again ... > because you would need to write backwards .... there are better ways > (Arrows) It's not ugly, it's exactly what you have here. The difference is Haskell binds right to left and Smalltalk left to right. Well actually Haskell binds left to right in things like Monads and right to left in statements. > Why on hell I have to read from right to left .... Because the last function called is the first thing in the statement. This is exactly the opposite of Smalltalk, which is why the application order is reversed. > There is quite some redundancy - as I stated before - when the method > returns self. > In MY case I use the cascade on setter methods. I don't think you read what I wrote. :) The nice thing about the cascade operator is that I don't have to worry what the message returns. I know for sure that my message sends go to the original object. > And for that you dump the ability to compose processes ?? You dump the power > of UNIX ? There are more powerful OS'es then UNIX. And you're not talking about the power of unix anyway, you're talking about the power of shell. You could do the exact same thing in Windows if the utilities were written that way (or use cygwin that *is* written that way). > I'm not redesigning it, I'm currently writing an interpreter for a > programming language and it happens that I selected Squeak for that ... > I'll probably start hacking Smalltalk a little anyway ... and yes I like > breaking Specs ... you never now. Sometimes something nice comes up ... :-) > > Fabio Breaking specs is fine when it's needed, but in this case it makes no sense. Just add a new operator that behaves how you want. It shouldn't be that hard. |
In reply to this post by Fabio Filasieno
On Aug 25, 2007, at 2:57 PM, Fabio Filasieno wrote:
Thanks for the example. This is a very clean looking bit of code. However, as others have noted, it's not fair to conclude that you've won the argument after comparing it to: ((((db getBlogposts) filter: [ :blogPost | blogPost data < (today - 7 days)]) filter: [ :blogPost | db coolPosts includes: item )]) collectMails ) do: [ :mail | "Happy to announce ..."] You can format the above so that it is very close to your example: ((((db getBlogposts ) filter: [ :blogPost | blogPost data < (today - 7 days)] ) filter: [ :blogPost | db coolPosts includes: item )] ) collectMails ) do: [ :mail | "Happy to announce ..."] In my opinion, your code looks nicer for two reasons. You don't need the initial parentheses, and '|' looks nicer to me than ')'. However, it's been established that '|' is not available, so I tried out your example with some of the other proposals from the thread. db getBlogposts ` filter: [ :blogPost | blogPost data < (today - 7 days)] ` filter: [ :blogPost | db coolPosts includes: item )] ` collectMails ` do: [ :mail | "Happy to announce ..."] db getBlogposts $ filter: [ :blogPost | blogPost data < (today - 7 days)] $ filter: [ :blogPost | db coolPosts includes: item )] $ collectMails $ do: [ :mail | "Happy to announce ..."] db getBlogposts ;; filter: [ :blogPost | blogPost data < (today - 7 days)] ;; filter: [ :blogPost | db coolPosts includes: item )] ;; collectMails ;; do: [ :mail | "Happy to announce ..."] The backtick is perhaps the cleanest-looking alternative, and it doesn't have any conflicting associations with other Smalltalk syntax. I don't like '$' very much... it looks very "heavy", and it looks a lot like a character literal even though it has nothing to do with them. I'm not sure how much we benefit by looking familiar to Haskell programmers. <ducks and covers...> Probably not as much as by adopting Java syntax to be familiar to the curly-brace crowd ;-) . My favorite is ';;'. Most importantly, it shares both visual and semantic similarity with the cascade operator, since both operators affect the receiver of the subsequent message. Also, IMHO it looks quite clean. Josh |
On Aug 26, 2007, at 12:54 PM, Joshua Gargus wrote:
Oops, I forgot about '!'... db getBlogPosts ! filter: [ :blogPost | blogPost data < (today - 7 days)] ! filter: [ :blogPost | db coolPosts includes: item )] ! collectMails ! do: [ :mail | "Happy to announce ..."] This falls in to the same category as the backtick, although personally I don't like it as much visually. I still like ';;' best. Josh
|
In reply to this post by Fabio Filasieno
Just for fun - the tiny attached change-set allows #asPipe to get
piping behavior for cascades: Squeak asPipe ps: 'aux'; grep: 'fabio'; sort It makes these two expressions equivalent ((((4 + 2) * 3) + 3) * 2) 4 asPipe + 2; * 3; + 3; * 2 Now I wouldn't use this in production but for interactive exploration it might actually be useful. Similar to implementing Symbol>>#value: to allow "(1 to: 10) collect: #squared". Btw, did you know each class can declare its own parser and compiler class? Experimenting with the syntax does not necessarily have to break other's stuff. - Bert - Pipe-bf.1.cs.gz (716 bytes) Download Attachment |
In reply to this post by Joshua Gargus-2
Joshua Gargus wrote:
> Oops, I forgot about '!'... > > db getBlogPosts > ! filter: [ :blogPost | blogPost data < (today - 7 days)] > ! filter: [ :blogPost | db coolPosts includes: item )] > ! collectMails > ! do: [ :mail | "Happy to announce ..."] > > This falls in to the same category as the backtick, although > personally I don't like it as much visually. > > I still like ';;' best. > > Josh | today | today := Timepoint today. db getBlogPosts _| filter: [ :blogPost | blogPost date < (today - 7 days)] _| filter: [ :blogPost | db coolPosts includes: item )] _| collectMails _| do: [ :mail | "Happy to announce ..."] |
In reply to this post by Bert Freudenberg
"Bert Freudenberg" <[hidden email]> wrote in message news:[hidden email]... > Just for fun - the tiny attached change-set allows #asPipe to get > piping behavior for cascades: > > Squeak asPipe > ps: 'aux'; > grep: 'fabio'; > sort > > It makes these two expressions equivalent > > ((((4 + 2) * 3) + 3) * 2) > > 4 asPipe + 2; * 3; + 3; * 2 That's nice. Yet another suggestion, similar to this - treat a pipe as having the same syntax as a cascade, but with a marker at the start. e.g. (using ! as the pipe marker) ! 4 + 2; * 3; + 3; * 2 the blog posts example would be... !db getBlogposts; filter: [ :blogPost | blogPost data < (today - 7 days)]; filter: [ :blogPost | db coolPosts includes: item )]; collectMails; do: [ :mail | "Happy to announce ..."] Note that there is no problem having ! at the START of a statement. So, a pipe is just '!' followed by a cascade. Other chars, or sequence of chars, could be chosen instead of ! ? / \ ` ? £ * % ~ @ ] } & + = would all work, but | ^ $ . # wouldn't work ) |
In reply to this post by Bert Freudenberg
Hi Bert --
I was wondering if the Squeak list generally knew that language and compilation (and hence even classes) are object oriented. Thanks for pointing it out. We were at one time going to go further and just let an object also be a virtual address space -- this would allow real encapsulation on anyone else's code and state, etc. Cheers, Alan At 01:42 PM 8/26/2007, Bert Freudenberg wrote: >Just for fun - the tiny attached change-set allows #asPipe to get >piping behavior for cascades: > >Squeak asPipe > ps: 'aux'; > grep: 'fabio'; > sort > >It makes these two expressions equivalent > > ((((4 + 2) * 3) + 3) * 2) > > 4 asPipe + 2; * 3; + 3; * 2 > >Now I wouldn't use this in production but for interactive exploration >it might actually be useful. Similar to implementing Symbol>>#value: >to allow "(1 to: 10) collect: #squared". > >Btw, did you know each class can declare its own parser and compiler >class? Experimenting with the syntax does not necessarily have to >break other's stuff. > >- Bert - > > > > > > |
In reply to this post by Fabio Filasieno
On Aug 26, 2007, at 11:01 , Fabio Filasieno wrote:
> collection := OrderedCollection new. > collection add:1. > > evaluates to one. Why ? Why not to collection ? You do not always add a simple value but the result of an expression. Having the #add: return the argument sometimes lets you avoid introducing a temporary variable. It is more useful this way, and for the cases where you actually want the collection you can use a cascade. A similar point can be made that setters should return the argument instead of the receiver, although usually in Squeak they do not (Tweak revises that policy). - Bert - |
Cascade is useful. It allows me to write code like that:
ogl glTexParameteri: GLTexture2d with: GLTextureMinFilter with: GLLinear; glTexParameteri: GLTexture2d with: GLTextureMagFilter with: GLLinear; glTexParameteri: GLTexture2d with: GLTextureWrapS with: GLClamp; glTexParameteri: GLTexture2d with: GLTextureWrapT with: GLClamp; glPixelMapfv: GLPixelMapIToA with: 2 with: (FloatArray with: 0.0 with: 1.0). But at the same time it stinks because you don't using the evaluation result of previously sent message, you simply drop it. And from this point i feel that something wrong with such design. Why computer needs to waste cycles to evaluate result of message when its simply not used at the end? In contrast , a pipe does not drops evaluation result, but reuses it in expression that follows. From this point i like it more than cascade. Same with period '.' Each time you placing a period in code, you telling compiler to drop the evaluated result of your expression. Can it be considered as good from computational point of view? Of course its not. You forcing a computer to waste the cycles just for nothing. Same with implicit return self from a method. I see a good reasons why i don't want return anything from a method, because it returns nothing useful or meaningful, and never used for continue evaluation in other expressions. And i think that maybe from computational point of view, it might be useful to indicate if we need to return result from a method or don't. So, all messages which chained in cascade expressions can be sent with flag 'drop result=true' and same for messages which is the last before period '.'. In other words we can have two forms of 'send' operation (bytecode): Send with return and send without return. I think this can save us from wasting a processor cycles just for nothing. I know that such semantics belongs mainly to compiler, not language itself, but i just want to point out, how language design influences the implementation, and how good or bad it can turn out at the end. |
In reply to this post by Bert Freudenberg
On Aug 26, 2007, at 11:55 PM, Bert Freudenberg wrote:
and Jason's already said that.
ahaaaa ..... I didn't get temp thing right. ( obj send: (... complex stuff....) ) SendToComplexStuff But I finally got one reason for the cascade!!!!! At last ... (the complex thing helped me on that) I didn't think of that, as I associated a "void" return with returning self ! For instance in C .. when you don't return anything (void) nothing comes out. "In Smalltalk instead" I thought " they do a smart thing. What can you do with void (or Ans) ?Nothing ! So instead of returning a useless void they return self. Smart ! And this worked very well with the functional style that I like. And I thought that side effects only functions like setters would be done perfectly. And easy to read to ! But then ... I thought: " What ? (((( obj sendA: a) sendB: b) sendC: c) sendD: d ). You must me joking !!!!" And my yohuoooooo :-D (no need to return self, it's the default ! ) ..... became argh ... here comes parenthesis. Now if I put into the equation you put a complex expression... you avoid ... #Just Returning self obj property: (complex_stuff) | property | ... and do #fixing it with ... get some more cases under the belt. obj property: (complex_stuff) ; ..... Don't know yet if I like it that way ... But now I see the point; and why somebody might prefer it that way. I wouldn't be so sure now on cutting the ";" cascade out now. I would say - but just now - that there is no pipe vs cascade thing. Thanks for ringing the bell .... and the pipe might be still better than the parenthesis .... :o) obj sendAndReturnComplexStuff: (... complex stuff....) | SendToComplexStuff |
In reply to this post by Igor Stasenko
On Aug 27, 2007, at 1:29 AM, Igor Stasenko wrote:
For side effects ! :-)
This is a very old question on purity and side-effect that seems to have reached a certain kind of agreement with Monads. Lots of papers treat this issue. Some suggested Effects Typing, some Continuations, then the Haskell guys figured out that with type classes they could create a polymorphic monadic bind and did the trick. But I think that what you say doesn't apply to Smalltalk because it's dynamically typed. How would you know at compile time if a method does side-effects .... What if a method called in a cascade does side effects , but the cascade itself seems pure ? I think it's complex stuff... Haskell does the "markings" (excuse the name) you talk about with monads and anything "not marked" doesn't do any sideffects, it's pure. By adding graph manipulation (reducing & updating) at runtime they evaluate functions "by name" and than by updating the runtime graph they avoid re-computation. In haskell basically every expression is in a [ ... ] (well sort of they use graph manipulation) And it's sent the message value only if needed. And when the the value it's returned the block gets removed and it's updated with the value... so no more need to evaluate it, if you need it again. It's a powerful optimization ! Too bad that to get that you need to but Everything in a [ ... ] (strictness analysis fixes that a bit). But the price to pay is high in my opinion ... functional becomes beautiful, but imperative stuff is a bit too hard ( not syntactically because of the 1 ton of syntax sugar) |
In reply to this post by Fabio Filasieno
Looking back at the number of messages in this thread, I figured I'd
contribute a straw man implementation instead of adding to the polemics. The operator used for piping is :>, i.e. (1 to: 10) select: [:x | x odd] :> collect: [:x | x factorial] which doesn't conflict with any syntactically valid messages, is reasonably suggestive and easy to type as both characters are shifted and are close to each other. Most importantly, it looks like a smiley thus improving user-friendliness. Of course, it's quite easy to change the Scanner to recognize pretty much anything else as the #pipe token. Cheers, --Vassili Pipe.1.cs (1K) Download Attachment |
Free forum by Nabble | Edit this page |