in reply to Some Insights from a Traveler Between Languages

in Perl, you use () to construct an array

() does not construct an array.

In an array assignment, my @array = (1, 2, 3);, the right hand side is a list, not an array. The parentheses in this case are needed only because if you wrote my @array = 1, 2, 3;, precedence would cause that to be interpreted as (my @array = 1), 2, 3;, thus not storing the 2 and 3 in @array. Contrast this to [] that always create a new array and return a reference to it. The thing inside [] is also a list, not an array. Only here you don't need the parens, because there is no difference in precedence with or without. But if you want, you can of course write [ (1, 2, 3) ]. Also note how my @array = (1, 2, (3, 4)); and my $arrayref = [ 1, 2, [ 3, 4 ] ]; are different in that in the former, the four elements are flattened and in the latter, you have a nested data structure.

The difference between the constructors [] and {} on one hand and the grouping () on the other, is reason enough for me to write them differently. That is why I put extra whitespace inside the constructors.

In the third case, you end up with a variable that holds the length of the array on the RHS.

Firstly, the RHS is not an array. In scalar context, it is not even a list, because a list can only exist in list context. Because it's not an array and not a list, it is impossible to get the number of its elements. Instead, you get the last value supplied. Your mistake here was to use 1, 2, 3. If you then get 3, you can't immediately know how to interpret it. In this kind of example or experimental code, always use values that do not naturally occur. Do not begin with 1 and do not end with the number of items you provide. Along those lines you should also not use something like 0, 1, 2. Instead, try a set like 42, 15, 69.

why is length(@foo) perfectly acceptable syntax?

Because there's nothing that says you shouldn't use an array in scalar context. In scalar context, an array evaluates to its number of elements. That may not be a useful value to provide to length, but it is to many other functions. And to get a consistent language, it shouldn't be made invalid to determine the number of digits of a number of elements.

ince in Python you do len(lst) to calculate the length of the list variable lst

Python does not have context, which is the fundamental difference. It cannot see the list variable as anything else than a list variable, and a function can not be smart about what it returns depending on the context in which it is used. Note, by the way, that Python's list is like Perl's array. In Perl, we have both arrays and lists and they are not the same thing!

Why can't Perl's "length" function be reasonable?

It is perfectly reasonable, it just doesn't do what you expected. And that is because your expectations are based on a Python world of physical laws, while Perl functions do not live in that world. They live in a Perl world, where Perl's laws and principles are used. Of course, to a traveler, a new world and its culture may at first seem very weird. But as a traveler, you should know better than to judge so quickly!

Learn our culture, including context and the difference between arrays and lists, and eventually you will feel right at home. Here is an incomplete list of things, copied from http://juerd.nl/perladvice, that you will need to understand:

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

  • Comment on Re: Some Insights from a Traveler Between Languages

Replies are listed 'Best First'.
Re^2: Some Insights from a Traveler Between Languages
by TimToady (Parson) on Apr 23, 2005 at 19:55 UTC
    Nevertheless, skynight is correct that Perl 5 contains some fundamental semantic traps. But it is also the case that we have not hesitated to break any existing surface feature of Perl 5 in order to target those deep traps. Perl 6 is simultaneously a better Perl and a completely new language, because it still depends critically on context, but completely revamps how (and when) context works, hopefully in a way that will seem even more Perlish in the long run.

    Many of the traps in Perl arise because of colliding contexts, and we've tried very hard to arrange contexts in Perl 6 so they don't collide so often, and when they do, they prioritize in the expected fashion. That's why there really aren't very many keywords to speak of anymore, so you can override print if you want to, because any lexical or package scope takes precedence over the global scope in which print is defined. That's why we now distinguish modules and classes from packages, and methods from subroutines, so the compiler can know the intent of the programmer better. That's why we revamped the precedence tables to get rid of longstanding traps inherited from C. That's why patterns are now considered a real language, and not just interpolated strings. That's why scalar context no longer forces premature evaluation. It all comes down to linguistics, and more specifically, tagmemics. Every utterance has multiple contexts, and it's really important to keep track of which context is "working" at any particular spot.

      skynight is correct that Perl 5 contains some fundamental semantic traps.

      It does, but only when you're used to different semantics. Perl was my second programming language, but different enough from BASIC to assume no rule would be the same. I never fell into any of its well known traps. (I tend to get bitten by the more obscure semantics.)

      In the same way, HOP says it changes the way you code Perl because it assumes you learned Perl after learning C, or you learned Perl from someone who was familiar with C. For me, this was never true. I'm trained by the logic provided in perldocs, which means that I don't code like a C coder. In fact, I'm almost halway through HOP and although it's a terrific book that I am glad I bought, I still hope to find new ways of coding, because to me, the Perlish way of things feels most natural already.

      length(@foo) returning 2 for a 13 element @foo has never surprised me. It was through contact with many beginners (here and in EFnet #perlhelp) that I discovered that this really is a trap for many.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        skynight is correct that Perl 5 contains some fundamental semantic traps.
        It does, but only when you're used to different semantics. Perl was my second programming language, but different enough from BASIC to assume no rule would be the same. I never fell into any of its well known traps. (I tend to get bitten by the more obscure semantics.)
        Well, that's certainly an interesting point -- sometimes it's better for different things to look different so you won't get them confused -- but it's actually fundamentally different from the way perl was originally conceived. It was supposed to look a lot like things that programmers were already familiar with, so it would make them feel like they knew what was going on.

        And I think the larger point here is that it's really okay to criticize the way something was done in perl. You can be totally committed to perl culture and still think that type globs were a mess.

        (Or course, these days it's a little late to bother criticizing perl 5, since the design of perl 6 is pretty well fixed.)

        My experience is similar. There are some things I have misunderstood in Perl and confused myself, but they are not the typical things, because my language background is atypical. I too started in BASIC, then later Inform (hence most of my ideas about OO) and subsequently elisp. (Ironically, I did not get my ideas about FP from elisp; I never understood FP in elisp but have picked it up (err, some of it) since I learned Perl.)

        This is an important point in this thread, because it illustrates that what constitutes a "trap" utterly depends on what language you think in, what semantics you are used to. The first time I saw someone posting on here about the print($a+$b)*$c; trap, I thought he was out of his mind. I had no idea why he was multiplying the result of the print by a scalar in void context, or what it was he intended to accomplish by doing so, because I don't think in C. (I figured it out eventually, partly by looking at some of the answers to his question, but it was quite a surreal moment when I first looked at his code.) Is that a trap? It sure as death and taxes wasn't a trap for me. It's only a trap if you are accustomed to thinking in a certain fashion, which is not universal and happens not to be the least bit Perlish. It's a common trap *mostly* because so many people come to Perl from a C or C-like language background; otherwise, it would not be a trap at all.

        I don't think it's possible to eliminate all the traps for people coming from other languages, because each other language will have its own set of traps. When you move from one language to another, you should expect to get caught by a few of these misunderstandings until you learn to think in the new language. As long as you're still thinking in another language and translating, you're going to get confused sometimes. That's unavoidable.


        "In adjectives, with the addition of inflectional endings, a changeable long vowel (Qamets or Tsere) in an open, propretonic syllable will reduce to Vocal Shewa. This type of change occurs when the open, pretonic syllable of the masculine singular adjective becomes propretonic with the addition of inflectional endings."  — Pratico & Van Pelt, BBHG, p68
Re^2: Some Insights from a Traveler Between Languages
by skyknight (Hermit) on Apr 23, 2005 at 20:29 UTC

    It might be worth mentioning that I've been writing Perl in various capacities for about nine years now. I'm not new to this. In fact, I was writing Perl long before I was writing Python. I consider this relevant because if someone who has been using the language as long as I have can bump up against such issues, then I shudder to consider the degree of perplexity under which the newbie frequently labors. There is a very good reason that in many circles Perl is derisively cast as a "write only language". There are some things that it just makes needlessly complicated or unpredictable.

Re^2: Some Insights from a Traveler Between Languages
by Cap'n Steve (Friar) on Apr 29, 2005 at 23:13 UTC
    The problem with that length() statement is that people have gotten used to the "Do What I Mean" principle of Perl. The array is doing what it thinks you mean by returning the number of its elements. The length() function, however, is selfish and doesn't really care what you mean. :p