How to convert to array? Why so many parens?

How to convert to array? Why so many parens?

am 12.05.2011 04:25:50 von Siegfried Heintze

Darn -- I forgot to switch to plain text again. I hope this does not
appear twice -- I apologize if it does!

This works and produces the desired result (I've simplified it a bit):


$default=3D ((((`grep pat file-name`)[0])=3D~/[0-9]+/)[0]);=20


Why does it take so many parentheses?


I don't think it should work, however.


(1) Why cannot I just index the results of the sub-process directly and
say `grep pat file-name`[0]? If Perl is confused I would think I might
need to explicitly convert it like this:
@{`grep pat file-name`}[0]=20
but that does not work. I think it should.


(2) I have the same question about the =3D~ operator -- it returns an
array too. So why cannot I just type
print @{$a=3D~/([0-9]+)/}[0] ?



Instead I have to type
print (($a=3D~/([0-9]+/)[0]);


Why are the extra outer parens required?
Thanks,
Siegfried


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: How to convert to array? Why so many parens?

am 12.05.2011 05:19:50 von derykus

On May 11, 7:25=A0pm, siegfr...@heintze.com wrote:
> Darn -- I forgot to switch to plain text again. I hope this does not
> appear twice -- I apologize if it does!
>
> This works and produces the desired result (I've simplified it a bit):
>
> $default=3D ((((`grep pat file-name`)[0])=3D~/[0-9]+/)[0]);
>
> Why does it take so many parentheses?
>
> I don't think it should work, however.
>
> (1) Why cannot I just index the results of the sub-process directly and
> say `grep pat file-name`[0]? If Perl is confused I would think I might
> need to explicitly convert it like this:
> =A0 @{`grep pat file-name`}[0]
> but that does not work. I think it should.
>
> (2) I have the same question about the =3D~ operator -- it returns an
> array too. So why cannot I just type
> print @{$a=3D~/([0-9]+)/}[0] ?
>
> Instead I have to type
> =A0print (($a=3D~/([0-9]+/)[0]);
>
> Why are the extra outer parens required?

This requires a fair amount of background about
list vs array context. Here's a good introduction:

perldoc -q array

See: 'What is the difference between a list and an array?'
in the above output.

This may answer some of the questions and/or
at least give you some background for a better
understanding of the issues.

HTH,
Charles DeRykus


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: How to convert to array? Why so many parens?

am 12.05.2011 05:59:36 von Rob Dixon

On 12/05/2011 03:25, siegfried@heintze.com wrote:
>
> Darn -- I forgot to switch to plain text again. I hope this does not
> appear twice -- I apologize if it does!

Hi Siegfried.

HTML messages are fine on this forum, although it is much better to
present code in a monospaced font.

> This works and produces the desired result (I've simplified it a bit):
>
>
> $default= ((((`grep pat file-name`)[0])=~/[0-9]+/)[0]);
>
>
> Why does it take so many parentheses?

It works fine as

$default = ((`grep pat file-name`)[0] =~ /[0-9]+/)[0];

> I don't think it should work, however.

??

> (1) Why cannot I just index the results of the sub-process directly and
> say `grep pat file-name`[0]? If Perl is confused I would think I might
> need to explicitly convert it like this:
> @{`grep pat file-name`}[0]
> but that does not work. I think it should.

It is all about context. `command` in isolation imposes scalar context,
and indexing it as such makes as much sense as "command"[0]. Enclosing
it in parentheses imposes list context, which can then be indexed
successfully.

@{`command`}[0] is attempting to dereference `command` as an array
reference, when it is simply a text string. Moreover, if it was valid
syntax, you would be accessing an array slice of one element, better
wriiten as ${$array_ref}[0]

> (2) I have the same question about the =~ operator -- it returns an
> array too. So why cannot I just type
> print @{$a=~/([0-9]+)/}[0] ?

The match operator is also context-sensitive. Its return also depends on
whether the right-hand side is m//, s//, or tr//. Furthermore, nothing
returns an array - only a list or an array reference. If there are no
captures in the regex, m// returns true or false (1 or '') in scalar
context and the lists (1) or () in list context.

As above, your code is attempting to dereference a simple scalar value
as if it was an array reference. If you had 'strict refs' in place you
would have a run time error message.

> Instead I have to type
> print (($a=~/([0-9]+/)[0]);

(You have a missing closing parenthesis in the regex, but it is clear
what you mean.)

Because print is a list operator that returns true or false according to
its success status. If the print is successful, then

print($a=~/([0-9]+/)[0];

is the same as

1[0]

which throws a syntax error.

You have a fundamental misunderstanding about the distinction between a
Perl list and an array. Reading perldoc -q "list and an array" should
help you. It is here on line



Cheers,

Rob

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: How to convert to array? Why so many parens?

am 12.05.2011 11:36:08 von jwkrahn

siegfried@heintze.com wrote:
> Darn -- I forgot to switch to plain text again. I hope this does not
> appear twice -- I apologize if it does!
>
> This works and produces the desired result (I've simplified it a bit):
>
> $default= ((((`grep pat file-name`)[0])=~/[0-9]+/)[0]);

I think you mean either:

$default= ((((`grep pat file-name`)[0])=~/[0-9]+/g)[0]);

Or:

$default= ((`grep pat file-name`)[0])=~/[0-9]/;

Because the match operator /[0-9]+/ will only return true or false in
either list or scalar context

$ perl -le'print "List context: ", "5" =~ /[0-9]+/'
List context: 1
$ perl -le'print "Scalar context: ", scalar( "5" =~ /[0-9]+/ )'
Scalar context: 1


> Why does it take so many parentheses?

It doesn't, this will work as well:

$default = ( ( `grep pat file-name` )[ 0 ] =~ /[0-9]+/g )[ 0 ];

Or:

( $default ) = ( `grep pat file-name` )[ 0 ] =~ /[0-9]+/g;

Or even:

$default = ( `grep pat file-name` =~ /[0-9]+/g )[ 0 ];

Or:

( $default ) = `grep pat file-name` =~ /[0-9]+/g;



> I don't think it should work, however.
>
>
> (1) Why cannot I just index the results of the sub-process directly and
> say `grep pat file-name`[0]?

Because `grep pat file-name` is not a list (or array).


> If Perl is confused I would think I might
> need to explicitly convert it like this:
> @{`grep pat file-name`}[0]
> but that does not work. I think it should.

@{} dereferences an array reference but `grep pat file-name` is not an
array reference.

You could copy the output from `grep pat file-name` to an array or
anonymous array and index that:

[ `grep pat file-name` ]->[ 0 ]

But then you might as well just use a list slice in the first place.


> (2) I have the same question about the =~ operator -- it returns an
> array too.

The binding operators (=~ and !~) do not "return" anything, they just
bind the expression on their left hand side to the operator on the right
hand side. It is the operator on the right hand side which returns
something. The binding operators can bind to either the match operator
(m//) or the substitution operator (s///) or the transliteration
operator (tr/// or y///).


> So why cannot I just type
> print @{$a=~/([0-9]+)/}[0] ?

Again, @{} dereferences an array reference and $a=~/([0-9]+)/ is not an
array reference.


> Instead I have to type
> print (($a=~/([0-9]+/)[0]);
>
>
> Why are the extra outer parens required?

perldoc -f print

Also be careful not to follow the print keyword with a left
parenthesis unless you want the corresponding right parenthesis to
terminate the arguments to the print--interpose a "+" or put
parentheses around all the arguments.

In other words:

print ($a=~/([0-9]+/)[0];

Is just:

print($a=~/([0-9]+/);

Followed by a syntax error.



John
--
Any intelligent fool can make things bigger and
more complex... It takes a touch of genius -
and a lot of courage to move in the opposite
direction. -- Albert Einstein

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/