Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implicit-conversion in perl

I am new to Perl, can anyone explain the following scripts for me please:

#!/usr/bin/env perl
use strict;
use warnings;
sub f1($) { my ($v) = @_; print "f1 $v\n"; }
sub f2(@) { my ($v) = @_; print "f2 $v\n"; }
my $s = "ww";
my @a = ("xx", "yy", "zz");
f1 $s; f1 @a; f2 $s; f2 @a;

The output in my computer is :

f1 ww
f1 3
f2 ww
f2 xx     # why!!

Can anyone explain why the fourth output is xx? I thought it should be zz, since when array converts to scalar, it should be the last element of array.

like image 875
alaska Avatar asked Jun 22 '12 06:06

alaska


People also ask

What is @_ and $_ in Perl?

$_ - The default input and pattern-searching space. @_ - Within a subroutine the array @_ contains the parameters passed to that subroutine. $" - When an array or an array slice is interpolated into a double-quoted string or a similar context such as /.../ , its elements are separated by this value.

What does ~~ mean in Perl?

Just as with the =~ regex match operator, the left side is the "subject" of the match, and the right side is the "pattern" to match against -- whether that be a plain scalar, a regex, an array or hash reference, a code reference, or whatever.

What is $@ in Perl?

$@ The Perl syntax error or routine error message from the last eval, do-FILE, or require command. If set, either the compilation failed, or the die function was executed within the code of the eval.


2 Answers

No, with a statement such as:

my ($v, $foo, $bar) = @_;

$v will be assigned the first value in the @_ array, $foo the second, and so on. This is because the parentheses impose a list context. Any excess values will be ignored, unless one of your variables is an array, in which case it will slurp all remaining values.

my ($v, @foo, $bar) = @_;   # wrong! $bar will never get any value

$v will get the first value, @foo all the rest. $bar will be undefined.

You may be thinking of assignment using a list:

my $v = qw(a b c);

But this is wrong, and will cause an error:

Useless use of a constant (a) in void context at -e line 1.
Useless use of a constant (b) in void context at -e line 1.

This is because the LHS using scalar context, it will (more or less) be similar to:

'a';
'b';
my $v = 'c';

You may notice that if we impose list context by putting $v inside parentheses, we get a different result:

my ($v) = qw(a b c);  # $v is now 'a'

ETA: Regarding prototypes:

In f1, what you see is that the array is forced into scalar context because the subroutine expects a scalar argument. That is why f1 with an array prints 3 (the size). When the prototype looks for an array, the array remains in default list context, and the assignment is done as per normal (as described above).

As an extra note: prototypes have a very specific use, to make subroutines behave more like certain built-ins with regard to argument handling. Such as sort { code here } or push @array, $foo.

If this is not what you are after, you should skip prototypes all together and simply write:

sub f1 {
...
}

Documentation here

like image 196
TLP Avatar answered Oct 12 '22 08:10

TLP


Perl array behaves in 2 differents flavours, regarding context:
Scalar context:

my $a = @tab; # get the array length
Array context:
my @newTab = @tab; # newTab is a copy of tab
Which can be reworded like this:
# 3 scalars in an array context (see parens) gets the contents of the tab
my ($a,$b,$c) = @tab; 
Here, since @tab can be wider than the number of scalars, these scalars are populated from the beginning of the tab (and not from the end). So your code:
my ($a) = @tab;
will echo the first element of the tab
like image 32
Tusc Avatar answered Oct 12 '22 07:10

Tusc