Michael Lazzaro wrote: > On Monday, January 20, 2003, at 12:30 PM, Smylers wrote: > > > It was only on reading that (and discovering that you hadn't > > previously known about the 'optional comma with closure argument' > > rule) that I understood why you had previously been so in favour of > > proposed new syntaxes: through a desire to banish the Perl 5 syntax. > > Yes. Again, it's not that I never knew about the perl5 rule,
Sorry, I wasn't meaning to suggest that you didn't know Perl 5; I was specifically referring to your saying that you'd presumed that conditions and loops were special cases in the grammar, but that actually they'll be dealt with by the general Perl _6_ rule about commas and closure arguments. > it's that I _dislike_ the perl5 rule, ... Oh. That's "dislike" rather than "disliked"? My question was predicated on your declaration "I emphatically withdraw my objection", which I took to mean that your knowledge of the infrared comma rule -- or whatever it's called -- meant you no longer disliked the Perl 5 syntax? > as I dislike most special-case grammar rules. So do I! I was particularly impressed by the ultraviolet comma rule, and how it avoids special cases, when Damian paraded it at a talk last summer. I also don't reckon it's _that_ special. So long as the rule is that such commas are optional, as distinct from their absence being mandatory, then the rule is a very general one: commas may be omitted where they aren't needed to delimit list items. Obviously with string and numeric values commas are always required: $a -1 They are the only way of determining op/term for the minus sign: a single argument of one less than the value in C<$a>, or two arguments with the second being minus one? But closures can be unambiguously determined without commas. Since whitespace is no longer allowed in hash look-ups, space followed by an open brace must be the start of a closure, and hence another argument. Similarly once the closing brace has been reached the closure is ... ahem, closed, so anything following must be a separate argument. > If we dropped C<map>, etc., we could drop the inferred-comma rule as > well (unless we're really successful in making C<if> a simple > function, in which case we need the rule anyway, so who cares?) I guess that's the crucial issue. Since it was Damian saying that it is possible to have C<if> and friends as functions -- and since this was something that'd already been dealt with before I joined this list, and so presumably would've had any impossibility pointed out -- I believed it to be true. There's another sub-thread casting doubt on -- and trying to resolve -- the issue. I completely agree that whether the infrared comma rule is needed over there makes a big difference to its use here. But I think I disagree about the "who cares" part ... > But the inferred-comma rule is tangential to my dislike of the current > C<map> syntax. I'd dislike C<map>, and like pipelines, even if the > inferred-comma rule wasn't there. As you've not doubt noticed, I'm the opposite: I like C<map> and don't (yet?) see the point of right-left pipelines. (That means not that I claim you're in some way 'wrong' to have those preferences, merely that we think differently to each other.) There's one Perl slogan that'd suggest having both ways in the language, so both of us get to code in the way we like. Countering that is the risk of adding too many ways of doing things and just causing confusion for everybody with all the different ways of invoking functions/methods on data. Hence my quibble with "who cares": I could probably be persuaded that it's 'better' for the language not to have the Perl 5 syntax, my preference, than to have so many alternative syntaxes. (I'm not sure.) > > Mike ... do you still find right-left pipelines as compelling as > > you've previously argued? > > Yes, very much so. ... I've seen quite a few newbies struggle with > the C<map> syntax; Me too. The most-strugglable bit for many has been the right-left data flow, that you start by typing where you want the data to end up, then the process it goes through last, then the process it goes through first, and lastly the data that's being processed. Left-right pipelines should be great at fixing this. > the most frequent mistake is to reverse the order of the arguments, > saying > > map @a, {...} That happens if you conceptualize C<map> as taking two arguments. In my mind C<map> operates on items in a list (and it just so happens that in Perl an array provides a list): map { ... } $a, $b, $c; So C<map> takes _many_ arguments, and one of these arguments is not like the others. And it makes sense to put the 'special' argument first. (That's also how I remember which way round things like C<join> are.) Thinking of it as operating on a list of things also helps to emphasize that C<map> processes just a single item at a time, that it isn't an agregate operation on the items as a group. > (Another common one is to not understand what C<map {...} @a, @b> > would do.) That's easily dealt with once somebody's got the idea that map processes lists -- and that Perl flattens lists, something that I admit isn't intuitive but is fundamental, useful, and applies to so many places in Perl that failing to grasp it leads to difficulties in many more areas than just with C<map>. > There's a couple of reasons for that, IMO, but the wording I often get > when I'm trying to get people to verbalize "what this statement does" > is that "it takes @a, and does <blah> to it". > > In other words, when newcomers verbalize the statement, they tend to > think of the C<map> as operating on @a. Which is true. You might > also say "it does <blah> to @a", which is also true. Kind-of. I go for "it does blah to each item in the list, individually". I want to think about a single item in isolation (then extrapolate that once my code works for that item, it'll work for the rest of them). > The simple fix would seem to be to emphasis the "it operates on @a" > part, so that people more easily remember it from the way they > verbalize it. My trouble with that is that it's emphasizing an array, and I reckon it's thinking about arrays that's causing the confusion! Also, this still needs to work on arbitrary lists. I know that an implicit array ref can be assumed, but then the OO syntax leads to emphasizing something that isn't even there. > Obviously, an OO style fixes that easily: > > @a.map {...}; Putting the 'special' argument first means that it can be seen. The Perl 5 syntax means that the code and the beginning of the list are easily seen together; the end of the list may've scrolled off the screen, but the unseen items are probably going to be similar to the ones you can see. Putting the list first means having to read through all the items before finding out what on earth is happening to any of them. > That's very intuitive to people, esp. new converts from other > languages. I'll grant that many converts are likely to find it intuitive, but I don't find it intuitive, especially when applied to lists. Converts from those 'other' languages are unlikely to be familiar with the power of throwing arbitrary lists around the place, so are unlikely to state a preference for a syntax that permits doing so. (Indeed people with strong OO backgrounds are likely to prefer an OO syntax for everything, but that isn't sufficient reason to make all of Perl OO!) > And, happily, it's very easy to implement and extend. But it works > only in one direction, L2R. (And, as Damian stated, chaining: > > @a.map {...} .sort {...}; > > probably wouldn't work at all, unless you tossed some parens around > all your curlies. Yuck.) Thanks; I'd missed that and had the mistaken impression that chaining was possible. Being corrected makes me dislike this syntax even more. Having some limits in a language so as to keep backwards compatibility is irritating but understandable; specifically adding in a _new_ syntax for operating on list items that doesn't permit chaining (piping, sticking the output of one op into the next, whatever) seems a little odd. It may help some language converts initially, but they are going to have to learn a completely different syntax to do more general things with C<map> and friends. That's more things to learn in total (and means that while they are on the 'conversion' syntax they are baffled on seeing others' code with other syntaxes -- much more so than if they'd initially learnt a more flexible syntax). > So fine, we convert C<map>, etc., to be methods of collections, as is > typical programming practice these days. I don't want Perl to be a _typical_ language!! I want it to be a really good language!! > And, in fact, we _are_ doing that elsewhere in the language. Things > like C<length @a> will become C<@a.length> or similar. But length is a property of an array as a whole, not of its elements treated individually. The OO syntax definitely makes sense here, but it doesn't follow that it's great everywhere. > But in doing that, we lose a lot of functionality -- mainly, the > simple L2R and R2L chaining that we have now. Yup. > So people want to keep C<map> as functions, not methods, and use the > old syntax. Well, that's OK, but we're back to the beginning. Some of us don't mind the beginning! > Here's where the pipeline suggestions come in. > > @out = map {...} <- @a; > > Here's the important part: This same syntax will work on ANY object, > and ANY method of that object. So you're removing the specific global > functions C<map>, C<grep>, C<sort>, etc., and replacing them with a > generic syntax for right-to-left chaining for any operations object. > You don't have to _build_ functions that can support chaining, because > _any_ method can be chained. But at the moment any function/method can be chained simply by returning something which is accepted as input to another one. > And it provides a very visual way to define any pipe-like algorithm, in > either direction: > > $in -> lex -> parse -> codify -> optimize -> $out; # L2R > > $out <- optimize <- codify <- parse <- lex <- $in; # R2L > > It's clear, from looking at either of those, that they represent data > pipes. Yes; that is nice. I'm just not convinced that it's sufficiently nice to require adding yet another way of passing data around to the language. I'm happy enough with the asymmetry that occurs just having the arrows to indicate 'reverse flow' data. > Whether you would code a pipeline as L2R or R2L depends on the specific > algorithm you're representing, and is purely a matter of taste... > you'd probably use R2L in the same places as you use C<map>-like > chaining in Perl5. I can't begin to justify why one should be superior > to the other, and would certainly use them both. I completely agree with all of that. > So that's what it gains you. The ability to visually express pipe-like > algorithms, in either direction, using OO techniques, without a lot of > parens, without relying on global functions, and with only a couple of > extra chars. That's why I'm gung-ho on it. Even if it's named <~ or > <|. Thank you. I've read everything you've written. I understand what you're saying, and why you like this syntax. But I'm still doubtful of the benefit. Maybe I'm just too sceptical about OO in general and so -- even though I use OO in Perl -- tend not to think in those terms? > <Fine, but really -- why kill the old C<map> function?> > > Well, if we have both OO C<@a.map> and OO-based pipelines > (post-invocants and, um, pre-invocants?), then we don't need the old > C<map>. It's redundant. Fair enough. I'm certainly agreed that at least one of those syntaxes is redundant! > To most people here, C<map> is ingrained. You learned it, now you > know it. That's a fair point. Most people have a natural tendency to resist change, and I'm not sure how selfish I'm being about this. People on the Perl 6 list are likely to be biased towards Perl 5 ways of doing things. (Or: For every feature in Perl 5 that somebody wants to change, there's bound to be somebody else on this list who likes it just the way it is.) > Newbies don't, I liked C<map> very much as soon as I saw what it did. That, and the way Perl makes light work in general of processing arbitrary lists, is something I really like about Perl. And I want Perl 6 still to be Perl-ish. Some other people currently prefer other languages. Some of those people may like to move to Perl 6. Some of them may still prefer other languages. That's OK; if somebody's happy with the language he/she's using, then let them continue to happily use it. We should take inspiration from other languages so as to improve Perl -- but that's not the same as bolting bits of other languages into Perl in an attempt to bait Happy Other-Language Users and trick them into using Perl. > but even newbies seem to understand that C<map> or C<grep> is an > operation on an array -- they just can't always remember the Perl5 way > of phrasing that. That, of course, is taking the narrow viewpoint that they are ops on arrays ... > Was that an understandable explanation? :-) Yes. Thanks, again. Please don't take personally my disagreeing with so much you've written! Smylers