perlstarter has asked for the wisdom of the Perl Monks concerning the following question:

$a = (a,b,c);
print $a; #prints 'c' i.e last element

but same thing i do with this way
$a = (a..c);
print $a; prints '1E0' from where it comes???????

Replies are listed 'Best First'.
Re: scalar slice assignment doubt
by gone2015 (Deacon) on Feb 28, 2009 at 12:45 UTC

    The problem is "context". Perl will continue to trip you up until you understand the significance of context... see Context Tutorial.

    In this case $a = (a..c) ; you're tripping over the magical properties of '..' in scalar context. Now, you may have thought that '..' was a list constructor. Or, you may have thought that (a..c) was a list constructor. Unfortunately, only the the first is ever the case, and then only in "list context".

    The action of '..' is described in perlop. In scalar context when the arguments are constants it compares the arguments with $. (the most recent input file line number) such that: as you read the input lines, 20..25 returns false for lines 1 to 19, then 1, 2, 3, 4, 5 for lines 20 to 24, 6E0 for line 25 (the last line in the range) and false for the rest of the file.

    Now, $a = (a..c) is equivalent to $a = 'a'..'c'. Since neither argument is numeric it's not clear what Perl should do. Further, this requires $. to have a value. It appears that Perl decides you are immediately at the end of this badly defined range -- so returns '1E0'.

    Apart from context, the other take-home here is to use use strict and use warnings.

    • with use strict Perl would have thrown out (a..c) as "Bareword "a" not allowed..." which whould at least have required you to tidy up to ('a'..'c') and might have rung some alarm bells.

    • with use warnings Perl would have thrown:

        Argument "a" isn't numeric in range (or flip)...
        Use of uninitialized value in range (or flip)...
        Argument "c" isn't numeric in range (or flop)...
        Use of uninitialized value in range (or flop)...
      
      warnings at you -- which would have told you something wasn't entirely going to plan !

Re: scalar slice assignment doubt
by jettero (Monsignor) on Feb 28, 2009 at 11:54 UTC
    I don't think there's any slicing here...

    In your first example, $a is set to the last element because a list in scalar context returns the last element. In your second example, you have a really oddball truth value thing. Ranges in scalar context do things I don't easily comprehend (read perlop for further info).

    I'm really not sure what perl does with (a..c). I usually use strict which would not allow that and I usually use warnings, which would explain some other things you have working against you. I think 'a' and 'c' are strings in your example, not totally sure.

    Here are some interesting examples:

    use strict; #use warnings; my $x = (1,2,3); # $x is 3, list in scalar context my @y = (4 .. 6); # @y is (4,5,6); my $y = @y; # $y is 3, array in scalar context my $z = 0 .. 0; # $z is true my $w = 1 .. 3; # $w is false print "$x, $y, $z, $w\n";

    You will get lots of warnings with the above if you turn on warnings.

    -Paul

Re: scalar slice assignment doubt
by zwon (Abbot) on Feb 28, 2009 at 12:07 UTC

    when you use '..' operator in scalar context it returns boolean value. See description in Range Operators.

Re: scalar slice assignment doubt
by ELISHEVA (Prior) on Feb 28, 2009 at 16:34 UTC
Re: scalar slice assignment doubt
by ikegami (Patriarch) on Mar 01, 2009 at 19:40 UTC

    If you want the last element of a list, you can use a list slice.

    my $last = ( LIST )[-1];

    The parens are required.

    For example,

    my $last = ( 'a', 'b', 'c' )[-1]; my $last = ( 'a' .. 'c' )[-1]; my $last = ( split(/,/, "a,b,c") )[-1];

    Note there's no such thing as a scalar slice. You can't slice a scalar into its components.

Re: scalar slice assignment doubt
by Marshall (Canon) on Mar 01, 2009 at 19:15 UTC
    I see that there are some great posts that talk about 1E0 AND the not so well understood fine points about ".." and ..."!
    Great!

    I've never encountered 1E0. But I would like to point out that there is very common usage of 0E0!

    0E0 is used within the DBI I/F to return a "True" string value with a numeric zero value! Example:

    my $query = $db->prepare(" Update $WeatherDB Set precip=$precip, high=$high, low=$low Where state='$state' AND city='$city' "); my $rows_changed = $update->execute() || die "execute failed..blah"; # if the execute method on the $update query "succeeds", ie # the DB exists and this whole thing "makes sense", but just # didn't change any rows, you get the "TRUE" string and # Zero numeric reponse...(0E0); if ($rows_changed == 0) { print "could not update record with $state,$city! Not Found!\n"; } elsif ($rows_changed >1) { print "DB corruption! $rows_changed entries for $state,$city combo\ +n"; }

    So although this exponential string representation of a simple int looks weird (and it is), there are some uses for this within Perl. This allows essentially two parms to be passed back as one value...Did it work or not? And if it did work what is the value? "no rows changed" here is a legal thing, otherwise you would have to have two vars, one for sucess or failure and one for number of results.

    Perl vars are strings until used in a numeric context. Maybe this is not obvious, but when a string is used in a numeric context, it becomes a number. In the above code, $rows_changed is still in string context. See what happens to $b below.

    Anyway, you will see 0E0 if you write DBI code.
    You might code for a decade without seeing 1E0 again

    #!/usr/bin/perl -w use strict; my $a="0E0"; my $b ="00000035"; print "A as string=$a\n"; $a +=0; print "A as numeric=$a\n"; $b +=0; print "B=$b leading zeroes deleted\n"; # prints # A as string=0E0 # A as numeric=0 # B=35 leading zeroes deleted