in reply to Re: Control Structure problem, mistake can't be found
in thread Control Structure problem, mistake can't be found

...not only is it possible to pick up some truely disgusting habits, you need a grounding in something more formal if you are to really understand what Perl is doing.

++, oshalla, for your other helpful advice, but not without taking exception to the quoted observation!

I have no real quibble with your "possible" re "truly disgusting habits" (NB: in English there's no 'e' in 'truly.') except to note that's pretty much also "possible" to write effectively - if inelegantly - despite misspellings -- whether writing narrative or text. Conversly "proofs" of almost any proposition can be so badly conceived or structured as to be worthless despite having the appearance of proper form or even superficial plausibility.

However, IMO, to suggest that it's not possible to understand "what Perl is doing" without formal study of another language for "grounding" is extreme, to say nothing of "unproven!"

  • Comment on Re^2: Control Structure problem, mistake can't be found

Replies are listed 'Best First'.
Re^3: Control Structure problem, mistake can't be found
by gone2015 (Deacon) on Aug 23, 2008 at 14:02 UTC

    Yes, I can never correctly spell 'truly' (correction: I can seldom spell it). I am ashamed. What can I say: without the 'e' it just looks to me as if it's had an unfortunate accident with something sharp -- an object lesson in what happens when you run with scissors, perhaps ? It also looks almost as if it should be pronounced with a short 'u', but for that, I have to admit, two 'l's would be required -- as in 'cully'.

    Of course many other words that end in 'e' don't drop it when the adverb is formed -- 'insanely', 'obscenely', 'approximately', 'effectively'. But that may be because they don't end in two vowels. So there's 'brusquely' and 'opaquely', but I guess the 'u' isn't really a vowel in this context. What about 'eerily', and of course 'duly' -- the later is clearly of a piece with 'truly'. But, lest we conclude there's a simple rule here, there's 'vaguely' and 'freely' -- admittedly the sound of the 'ue' in 'vague' is quite different from that in 'true', which may (or may not) be significant. Similarly, in the case of 'free' it may be that the 'ee' is effectively a compound vowel ?

    English: what can I say ? Gosh, what a glorious mess !


    Anyway, returning to what I suppose is the real matter: I think that to "really understand what Perl is doing" you do need some more formal grounding -- highlighting the stress I intended on the "really".

    For instance, consider the following:

    my @rows = () ; while (my $line = <SHEET>) { chomp($line) ; my @columns = split /\s+/, $line ; push @rows, \@columns ; } ;
    What do we think is going on here ?
    1. declare the (one dimensional) array @rows and ensure it is initialised empty.
    2. run a while loop using various pieces of commonly used Perl magic to step line by line through the file referred to by SHEET, declaring the working variable $line for the duration of the while loop
    3. chomp($line) removes the line ending from the input line (unless you're running on a *nix type system and the file came from winders, in which case it tends to remove half the line ending, SO STAY AWAKE)
    4. declare the (one dimensional) array @columns for the remaining duration of the loop, and assign to it the result of splitting up the input line.
    5. push a reference to the array @columns onto the array @rows (we understand that in Perl arrays and lists are strongly related)
    The result is intended to be a two-dimensional array (or what passes for one in Perl) of cells. And, indeed that's what happens.

    Now, references are sophisticated, but just taking the code at face value, one might worry:

    • if @columns only exists for the duration of the enclosing block, what does the @rows array contain after the block ?
    • why does this work at all, given that it appears to push the same thing, \@columns, on to @rows each time around the loop ?
    So, we all know that this works because my @columns doesn't declare an array, it declares something that contains a pointer to a data structure which contains the actual array and which lives on a heap. The \@columns doesn't really return a reference to @columns, it returns a copy of the pointer it contains. What's more, each time around the while loop @columns is reset before the new split /\s+/, $line is assigned to it, so each \@columns is different and refers to a different data structure on the heap -- each of which persists after the block (leaving reference counting and garbage collection to one side, for the time being).

    Scanning back over the above, I observe it's hard to describe what's really going on, without using some fairly heavy computer science concepts. IMO, the study of more formal language(s) is the way to gain understanding of these and how they work.

    This is only one example, but I believe it illustrates a general point.

      I disagree with you re Perl as a first language. Perl has one thing that is missing in many other languages: a friendly and helpful community.

      You are right that in Perl, grokking references can be hard. I struggled for a while with building data structures. Different bracketing, and -> syntax and added to the confusion. Map was pretty hard to get as well. The Schwartzian transform just about caused a brain hemorrhage the first time I saw it.

      BASIC is easyish, but which version? Most modern basics are pretty OO in structure. Save the beginner from objects!

      Java? OO hell + verbosity that is puzzling to the newb, and frustrating to the experienced.

      C++? OO again. And...look at the size of that language! Back in the day, C++ was big and unwieldy and confusing enough, but I was still reasonable. I stopped watching it for a few years and the new standards made it more unreadable, and 20 times bigger and harder to tell what's going on. Do go in, it's a TRAP!!!!

      C? As a newb I got hung up on * vs & for the longest time because you use * to declare a pointer, but you use & to get one, and then you use * to dereference it! It is a very small language--hooray--but as a result you either have to memorize an API to do anything interesting or write your own libraries.

      Pascal might work out ok. But who uses it these days? One might as well suggest Logo. Also, array indexes start at 1--which will cause pain when switching to almost any other language.

      Any "serious" language will have it's good and bad bits for a new learner. (Befunge and BF are ALL BAD, thankfully one is not expected to use them for work.) But Perl shines for the simple fact that there is a large, craft-oriented community that is ready to provide friendly, prompt help. The help I got around here was worth way more to me than the "help" I got from a variety of professors and teaching assistants. The funny thing is, hacking Perl and reading Perlmonks straightened out lingering errors in comprehension that my formal education left behind.


      TGI says moo

      Your comment seems funny to me (in a good way, really!) because I would normally code your example as
      my @lines = map { chomp; [split] } <SHEET>;
      or, if I suspected that the "SHEET" could point to a very big file,
      my @lines; chomp, push @lines, [split] for <SHEET>;
      both of which do need a _lot_ of perl knowledge to be read, aside from the CS knowledge you mentioned...
      Update: obviously, blazar is right. and I should've written my examples as:
      my @lines = map [split], <$sheet>;
      and
      my @lines; push @lines, [split] while <$sheet>;
      because for was just wrong and because split already chomped the string...
      []s, HTH, Massa (κς,πμ,πλ)
        or, if I suspected that the "SHEET" could point to a very big file,
        my @lines; chomp, push @lines, [split] for <SHEET>;

        I personally believe that it wouldn't make a difference, unless you're already running Perl 6 since it has lazy evaluation by default; but in that case the syntax for the iterator would be completely different. Under Perl 5 you probably mean:

        my @lines; chomp, push @lines, [split] while <$sheet>;

        (This reply is intended mostly for the benefit of the OP which is also the reason why I incidentally changed the filehandle to a lexical variable which is what one should use in most cases nowadays.)

        --
        If you can't understand the incipit, then please check the IPB Campaign.