As an example: in Javascript, the binary + operator means either addtion or concatenation, depending on the type of the left-hand side. In Perl there are different operators for that, + for addition and . for concatenation.
That means that you have more operators, but you need less type conversions, because they happen implicitly.
This now follows the same philosophy: different operations have different names. List reversal is not the same as string reversal. Neither is hash inversion.
Within this context it's the most logical thing you can do.
Sir, I have a frivolous data point for you. It's from a blog post I wrote shortly after the change from 'reverse' to 'flip' for strings (<http://use.perl.org/~masak/journal/38800 >):
"Strangely enough, nothing happened when clicking the 'flip!' link... a moment's reflection gave the cause of this: a few days ago, [Larry Wall] has syntactically separated reversal of List (.reverse) from the reversal of Str (.flip); my code was like three weeks old and was still using .reverse for strings, which in the newest Rakudo got interpreted as one-elem lists, and list-reversed with no visible effect whatsoever. I fixed that, and found the fact that the link in the Lobster app was already called 'flip' an indication of the appropriateness of the name change. Perl 6 just keeps getting nicer and nicer."
The relevant piece of background is that I was porting the example application (Lobster) from the Rack framework, where the link was already called 'flip'. So, suddenly both the link and the method were called 'flip'.
If I may try to briefly explain/defend the naming as well as expand on the need for it...
In Perl 5, 'reverse' did all of the three things: it reversed strings (in scalar context), or lists/hashes (in list context). The latter two weren't really distinguished, since a hash in Perl 5 is just an (even-element) list that you assign to a hash variable.
In Perl 6, 'wantarray' http://perldoc.perl.org/functions/wantarray.html is gone, and not even built-in methods rely on figuring out the void/scalar/list context of the caller. Which means that we don't do the trick described in the blog post to make 'reverse' do either string or list reversal.
Very well, no problem. What we lack in 'wantarray' we make up with a type system. We just stick the string-reversing 'reverse' method on the type Str, and the list-reversing one on the type List. All good and well. (In fact, we put the string-reversing one on Any, and let it coerce to Str when needed.)
But wait. There are some corner cases where this causes problems. Sometimes a scalar variable contains a list of things, and sometimes a list contains but one element. In either case, we try to magically guess between the two uses, and get it wrong. So maybe making those two behaviours homonyms wasn't too good an idea after all.
Hence the need for distinguishing 'flip' and 'reverse'. By distinguishing 'invert', we can make it a bit smarter in case of hash key collisions. The 'magical guessing' dilemma goes away, because it's clear you mean a list when you say 'reverse' and a string when you say 'flip'.
The names are fairly well-chosen, considering what they do. You flip a single thing (string), reverse the order of a sequence of elements (list), and invert a mathematical mapping (hash).
There is actually a class in Perl 6, called Buf, for when you want to talk about a sequence of bytes rather than a sequence of characters/graphemes. Buf is array-indexable; in fact it works a little like a string a little like an array. It's there to make it harder to screw encodings up. See http://use.perl.org/~masak/journal/39236 for how.
"Instead, reverse responds to its surroundings and figure out what they expect. $string = reverse $string is a scalar assignment, and expects a scalar. print reverse $string, as integral explains, puts reverse in list context, so it reverses the list of one thing ($string), i.e. doing nothing."
It's funny. I just registered on HN, and on my way in I took the time to read http://ycombinator.com/newswelcome.html where the expectations on comments are outlined:
"What we especially discourage are comments that are empty and negative—comments that are mere name-calling."
Do you wish to make your negative comment about 'flip' less empty? Or have you expended your fount of criticism already?
His comment is not negative in the name-calling sense of the page you reference. However, it could seem that Or have you expended your fount of criticism already? is, don't you think?
I think you're right. My comment would probably have been better served without that last sentence. Allow me to apologise for that one, rather than stand by it.
But even regardless of the HN guidelines, I am curious: why does tptacek consider 'flip' to be a dumb name? And why does he consider the sentence he quotes to be 'even worse'? Opinions are easy to produce en masse; what's interesting to me is the reasoning or motivation behind them.
Because every language from Javascript to Haskell calls this operation "reverse", because "flip" is a more ambiguous term than "reverse", and because the only reason the word "flip" is used is as a result of a bizarre perl idiosyncracy about context-based evaluation.
No, the reason for the word 'flip' being used is not due to a bizzarre Perl idiosyncrasy about context-based evaluation -- quite the opposite. Note that the change to using 'flip' is in Perl 6 only (this is not one of those changes that newer versions of Perl 5 has adapted; nor, I suspect, will it ever). Perl 6 does not do the context-base idiosyncrasy thing, and the resulting consistency quite naturally led to the two concepts being separated.
Sure, we could still call both the list operation and the string operation the same thing ('reverse', say), but that would lead to unfavourable corner cases and breakage of the rule of Least Surprise. ("Hey, why does it write my list of one string backwards?")
So, after Perl 6 has removed a function being polymorphic based on list/scalar context, and then removed nasty corner cases, your objection that this is not how "every language from Javascript to Haskell" does it might still be valid, but it might not weigh as heavily against the gain in consistency.
In C, parentheses mean expression grouping, function invocation and cast... depending on context.
In English, many words have different meanings depending on context: e.g. not to be mean, but you know what I mean, right? Ordinary human speakers have no problem with this, even without theoretical linguistic training.
I'm not convinced that Larry Wall (a formally trained linguist) has chosen meanings and contexts that really do fit in with what human speakers intuitively expect. But it could well be that it is just that I am personally familiar with C-style grammar, and not with Perl's. If I "grew up" with Perl, perhaps it would seem natural?
Perhaps it's exactly the same as with human languages: that languages with very different grammars are not so easy to learn for most people. And... perhaps there is a linguistic window for learning programming languages, as there is for human languages (which is up to about 7yo)?
Oh, believe me, constructs in Perl (both Perl 5 and Perl 6) mean different things depending on context, too. :)
As a simple example, which you'll find in various languages, not just Perl: brackets ('[ ]') construct list objects when standing alone, but when they occur after something, they do array indexing into that thing. This all falls out naturally, and humans are very well equipped at switching between this type of contexts.
The Perl 5 behaviour of overloading 'reverse' with double meaning could be said to be context-dependent in this way. But the flip/reverse/invert distinction goes in the other direction, saying "hey, maybe we do want to keep these three concepts separate rather than crowding them all into the same method".
A similar thing has happened with 'length'. In Perl 5, 'length' always meant 'number of characters in the supplied string', but newbies kept expecting the function to work for lists too. It doesn't. In Perl 6, there's a method '.elems' for lists and '.chars' for strings. Neither of them are accessible as 'length'.
In a lot of places where Perl 5 overloads words and depends on context for the right semantics, Perl 6 strives to make things consistent and eliminate mental lists of things you have to remember.
I was picturing an AST, with the parentheses in the context of that. However, you're quite right that context seems to have a specific technical meaning here, and not the general one I was using.
Interesting post about perl, but the end is most interesting about Life In General:
"But I guess there's also a moral to it all. We all start somewhere, and in a way it's reassuring to find five-year old proof of this fact. A newbie is just on a part of the learning curve you've already visited; they haven't had a chance to tweak their keyboard and developing environment to maximum efficiency yet, and they sometimes forget that the manual is there, or misread it in some way. So, don't hesitate to be be kind to them, and help them connect to the goodness that is perldoc, PerlMonks and Planet Iron Man so that they can grow and bloom into experienced wielders of Perl.
But don't hesitate to call them insane, either, when the situation calls for it."
The only thing missing from Life In General is The Fine Manual.
Perl 5 has many other sides apart from the context-dependence. To mention a few, the regex sublanguage is deeply integrated into the rest of the language, there's an active and versatile testing culture, and CPAN hosts 17k modules for countless of fields and applications.
Some of those (such as testing culture) are mirrored in other languages' cultures, others (such as CPAN) are unparalleled in scope. Ignoring Perl 5 based on a single feature causes you to miss out on all the truly good parts.
26 comments
[ 1072 ms ] story [ 207 ms ] threadThat seems utterly insane.
the sole reason perl is used.
As an example: in Javascript, the binary + operator means either addtion or concatenation, depending on the type of the left-hand side. In Perl there are different operators for that, + for addition and . for concatenation.
That means that you have more operators, but you need less type conversions, because they happen implicitly.
This now follows the same philosophy: different operations have different names. List reversal is not the same as string reversal. Neither is hash inversion.
Within this context it's the most logical thing you can do.
"Strangely enough, nothing happened when clicking the 'flip!' link... a moment's reflection gave the cause of this: a few days ago, [Larry Wall] has syntactically separated reversal of List (.reverse) from the reversal of Str (.flip); my code was like three weeks old and was still using .reverse for strings, which in the newest Rakudo got interpreted as one-elem lists, and list-reversed with no visible effect whatsoever. I fixed that, and found the fact that the link in the Lobster app was already called 'flip' an indication of the appropriateness of the name change. Perl 6 just keeps getting nicer and nicer."
The relevant piece of background is that I was porting the example application (Lobster) from the Rack framework, where the link was already called 'flip'. So, suddenly both the link and the method were called 'flip'.
In Perl 5, 'reverse' did all of the three things: it reversed strings (in scalar context), or lists/hashes (in list context). The latter two weren't really distinguished, since a hash in Perl 5 is just an (even-element) list that you assign to a hash variable.
In Perl 6, 'wantarray' http://perldoc.perl.org/functions/wantarray.html is gone, and not even built-in methods rely on figuring out the void/scalar/list context of the caller. Which means that we don't do the trick described in the blog post to make 'reverse' do either string or list reversal.
Very well, no problem. What we lack in 'wantarray' we make up with a type system. We just stick the string-reversing 'reverse' method on the type Str, and the list-reversing one on the type List. All good and well. (In fact, we put the string-reversing one on Any, and let it coerce to Str when needed.)
But wait. There are some corner cases where this causes problems. Sometimes a scalar variable contains a list of things, and sometimes a list contains but one element. In either case, we try to magically guess between the two uses, and get it wrong. So maybe making those two behaviours homonyms wasn't too good an idea after all.
Hence the need for distinguishing 'flip' and 'reverse'. By distinguishing 'invert', we can make it a bit smarter in case of hash key collisions. The 'magical guessing' dilemma goes away, because it's clear you mean a list when you say 'reverse' and a string when you say 'flip'.
The names are fairly well-chosen, considering what they do. You flip a single thing (string), reverse the order of a sequence of elements (list), and invert a mathematical mapping (hash).
There is actually a class in Perl 6, called Buf, for when you want to talk about a sequence of bytes rather than a sequence of characters/graphemes. Buf is array-indexable; in fact it works a little like a string a little like an array. It's there to make it harder to screw encodings up. See http://use.perl.org/~masak/journal/39236 for how.
"Instead, reverse responds to its surroundings and figure out what they expect. $string = reverse $string is a scalar assignment, and expects a scalar. print reverse $string, as integral explains, puts reverse in list context, so it reverses the list of one thing ($string), i.e. doing nothing."
At least "flip" is just a very dumb name.
It's funny. I just registered on HN, and on my way in I took the time to read http://ycombinator.com/newswelcome.html where the expectations on comments are outlined:
"What we especially discourage are comments that are empty and negative—comments that are mere name-calling."
Do you wish to make your negative comment about 'flip' less empty? Or have you expended your fount of criticism already?
But even regardless of the HN guidelines, I am curious: why does tptacek consider 'flip' to be a dumb name? And why does he consider the sentence he quotes to be 'even worse'? Opinions are easy to produce en masse; what's interesting to me is the reasoning or motivation behind them.
No, the reason for the word 'flip' being used is not due to a bizzarre Perl idiosyncrasy about context-based evaluation -- quite the opposite. Note that the change to using 'flip' is in Perl 6 only (this is not one of those changes that newer versions of Perl 5 has adapted; nor, I suspect, will it ever). Perl 6 does not do the context-base idiosyncrasy thing, and the resulting consistency quite naturally led to the two concepts being separated.
Sure, we could still call both the list operation and the string operation the same thing ('reverse', say), but that would lead to unfavourable corner cases and breakage of the rule of Least Surprise. ("Hey, why does it write my list of one string backwards?")
So, after Perl 6 has removed a function being polymorphic based on list/scalar context, and then removed nasty corner cases, your objection that this is not how "every language from Javascript to Haskell" does it might still be valid, but it might not weigh as heavily against the gain in consistency.
In English, many words have different meanings depending on context: e.g. not to be mean, but you know what I mean, right? Ordinary human speakers have no problem with this, even without theoretical linguistic training.
I'm not convinced that Larry Wall (a formally trained linguist) has chosen meanings and contexts that really do fit in with what human speakers intuitively expect. But it could well be that it is just that I am personally familiar with C-style grammar, and not with Perl's. If I "grew up" with Perl, perhaps it would seem natural?
Perhaps it's exactly the same as with human languages: that languages with very different grammars are not so easy to learn for most people. And... perhaps there is a linguistic window for learning programming languages, as there is for human languages (which is up to about 7yo)?
As a simple example, which you'll find in various languages, not just Perl: brackets ('[ ]') construct list objects when standing alone, but when they occur after something, they do array indexing into that thing. This all falls out naturally, and humans are very well equipped at switching between this type of contexts.
The Perl 5 behaviour of overloading 'reverse' with double meaning could be said to be context-dependent in this way. But the flip/reverse/invert distinction goes in the other direction, saying "hey, maybe we do want to keep these three concepts separate rather than crowding them all into the same method".
A similar thing has happened with 'length'. In Perl 5, 'length' always meant 'number of characters in the supplied string', but newbies kept expecting the function to work for lists too. It doesn't. In Perl 6, there's a method '.elems' for lists and '.chars' for strings. Neither of them are accessible as 'length'.
In a lot of places where Perl 5 overloads words and depends on context for the right semantics, Perl 6 strives to make things consistent and eliminate mental lists of things you have to remember.
"But I guess there's also a moral to it all. We all start somewhere, and in a way it's reassuring to find five-year old proof of this fact. A newbie is just on a part of the learning curve you've already visited; they haven't had a chance to tweak their keyboard and developing environment to maximum efficiency yet, and they sometimes forget that the manual is there, or misread it in some way. So, don't hesitate to be be kind to them, and help them connect to the goodness that is perldoc, PerlMonks and Planet Iron Man so that they can grow and bloom into experienced wielders of Perl.
But don't hesitate to call them insane, either, when the situation calls for it."
The only thing missing from Life In General is The Fine Manual.
"Everybody's got to start somewhere"
I'm not good at anything, but I'm better at everything.
Some of those (such as testing culture) are mirrored in other languages' cultures, others (such as CPAN) are unparalleled in scope. Ignoring Perl 5 based on a single feature causes you to miss out on all the truly good parts.