senőr_biggles has asked for the wisdom of the Perl Monks concerning the following question:

I recently wrote a program that at one point got content from an external file and just printed it out to STDOUT. Being new to this I forgot that input is split into arrays at newlines so I put it in a scalar. I realized the mistake, but thought it was odd because when I assigned what should have been a list to a scalar I got not what I had believed to be correct, the number of list elements, but just the first element of the list. Is it a mistake in my code? Or is it just how Perl works? I was just wondering because it seems like it would be troublesome if I ever needed to actually know the number of list elements. Thanks for any replies you might be compelled to make. ~senőr biggles~

Retitled by davido from 'Just curious.'.

  • Comment on Reading files in scalar context with <> operator

Replies are listed 'Best First'.
Re: Reading files in scalar context with <> operator
by holli (Abbot) on Aug 06, 2005 at 05:42 UTC
    When you read from a filehandle like so
    $line = <IN>;
    You get the actual line, if you use an array,
    @lines = <IN>;
    you will end up with the whole file in the array, one line per array element.

    btw, the probably shortest way (ahem), to open a file and print it is simply
    open IN, "file"; print <IN>;
    or
    use File::Slurp; print read_file("file");


    holli, /regexed monk/
Re: Reading files in scalar context with <> operator
by davido (Cardinal) on Aug 06, 2005 at 05:51 UTC

    Evaluating an array in scalar context yields a count of how many elements exist in the array. Lists are different. People will jump in now and say there's no such thing as a list in scalar context. There isn't. So consider this code:

    perl -e "print scalar( 'a', 'b', 'c', 'd' );"

    The output is 'd'. perlop explains why:

    Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. This is just like C's comma operator.

    In list context, it's just the list argument separator, and inserts both its arguments into the list.

    The same is true for slices of an array, and lists generated with the qw// operator or through other basic means.

    List functions can be defined to do all manner of different things in scalar context. split tells you the number of elements created, and splits into @_. Other functions do other things. That's dependant entirely on the function's code.

    The diamond operator is defined to slurp a file in list context, or to return the next line (starting with the first) in scalar context.

    So I guess that the answer is, if you got the last element you got documented behavior for some operators. If you're reading a single line from a filehandle, you'll get the first line the first time you read from the filehandle. That too is expected, and documented in perlop. If you got something else, we'll need to see more information to explain where that behavior is documented.


    Dave

Re: Reading files in scalar context with <> operator
by sk (Curate) on Aug 06, 2005 at 05:38 UTC
    Well depends on how you assigned the scalar to the array

    my @array = qw (hi there); my $len = @array; my ($fstel) = @array; # Note the paren () around $fstel print ("Len = $len First element = $fstel\n"); __END__ Len = 2 First element = hi

    update: If you have a list, it is not possible for you to get the length of it without putting it into an arrary

    For explanation on reading files onto a scalar/list please see holli's post below.

    I think you will find this link useful to understand more about lists and arrays

    What is the difference between a list and an array?

Re: Reading files in scalar context with <> operator
by BaldPenguin (Friar) on Aug 06, 2005 at 18:08 UTC
    Unfortunately not all functions will send back the contectula meaning you think it implied. Different list returning functions will return different things when returning scalars. localtime will return a join of it's array; readline ( and likewise <> ) will return the 'next' value in the series ( mainly I think, because it's designed to be iterative ); Others may return the array and default to the scalar value as you had thought about the <> statement

    I believe the important thing would be to not make assumptions. Once you get to know which returns which, you might be tempted to make accomodate each. I myself would stick to what I know would work, in this case return an array, then use scalar to get the count
    .... my @lines = <$fh>; my $count = scalar @lines; ....
    That also tends to allow others reading your code to understand your code, especially if they still do not know the ins and outs of contextual returns.

    As far as reading the file, slurp works well and I won't dispute it's usefulness, but I am still old school.
    # Unstested my strict; my warnings; my $content = ''; my $filename = 'myfile.txt'; { local $\; open $fh, '<', $filename or die "Cannot open $filename: $!\n"; $content = <$fh>; close $fh; } print $content;
    Here we localize the input record seperator, or enable 'slurp' mode, and the call using <> will pull in the whole file.

    Don
    WHITEPAGES.COM | INC
    Everything I've learned in life can be summed up in a small perl script!
      OK. I see. Thank you very much for your answers.