For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > October 2006 > Smart assignment









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Smart assignment
Bryan R Harris

2006-10-02, 6:59 pm



**************************************
$ptypeline = "# movable ortProj ortho 0.000 0.000";

($ptype) = ($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i) ||
"(missing)";

print $ptype, "\n";
**************************************


The above code prints "1", where I want it to print "ortho". Is that
possible?

(Preferably in one line, since I'm a *big* fan of perl golf. =)

- B

usenet@DavidFilmer.com

2006-10-02, 6:59 pm

Bryan R Harris wrote:
> The above code prints "1", where I want it to print "ortho". Is that


print $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i ? $1 :
"(missing)";

> (Preferably in one line, since I'm a *big* fan of perl golf. =)


Golf is for recreation only. Production code and golf should never
mingle.

--
David Filmer (http://DavidFilmer.com)

Rob Dixon

2006-10-02, 6:59 pm

Bryan R Harris wrote:
>
> **************************************
> $ptypeline = "# movable ortProj ortho 0.000 0.000";
>
> ($ptype) = ($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i) || "(missing)";
>
> print $ptype, "\n";
> **************************************
>
>
> The above code prints "1", where I want it to print "ortho". Is that
> possible?
>
> (Preferably in one line, since I'm a *big* fan of perl golf. =)


$ptype = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i ? $1 : "(missing)";

Rob
Mumia W.

2006-10-02, 6:59 pm

On 10/02/2006 01:54 PM, Rob Dixon wrote:
> Bryan R Harris wrote:
>
> $ptype = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i ? $1 :
> "(missing)";
>
> Rob
>


Yes, and here is another way:

$ptype = (($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i)[0]) ||
'(missing)';


Jen Spinney

2006-10-02, 9:58 pm

On 10/2/06, Mumia W. <mumia.w.18.spam+nospam@earthlink.net> wrote:
>
> On 10/02/2006 01:54 PM, Rob Dixon wrote:
>
> Yes, and here is another way:
>
> $ptype = (($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i)[0]) ||
> '(missing)';




How does that way work? I was curious, so I tested it myself and it clearly
did work, but I have no idea why. Shouldn't the || operator turn the entire
right side into a condional expression that evaluates to either 1 or 0?

- Jen

John W. Krahn

2006-10-03, 4:00 am

Jen Spinney wrote:
> On 10/2/06, Mumia W. <mumia.w.18.spam+nospam@earthlink.net> wrote:
>
> How does that way work? I was curious, so I tested it myself and it
> clearly did work, but I have no idea why. Shouldn't the || operator
> turn the entire right side into a condional expression that evaluates
> to either 1 or 0?


In scalar context the expression:

$ptypeline =~ /movable.+(sine|geo|radial|ortho)/i

returns "true" or "false" (1 or '') and in list context it returns the
contents of any capturing parentheses in the pattern.

The expression:

( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i )[ 0 ]

is a list slice so the regular expression is in list context but the slice is
a single value so the expression is a scalar.

The || operator will only work with scalar values, not with lists, so this
works because the list has been converted to a scalar with the list slice.




John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
Paul Lalli

2006-10-03, 8:02 am

Jen Spinney wrote:

> How does that way work? I was curious, so I tested it myself and it clearly
> did work, but I have no idea why. Shouldn't the || operator turn the entire
> right side into a condional expression that evaluates to either 1 or 0?


It is worth pointing out that unlike in C, the logical operators do not
return 1 or 0 in Perl. Instead, they return the last value evaluated:

my $x = (0 || 5 || 3);
# $x gets the value 5, which is true.

$x = (0 || undef || "");
# $x gets the value "", which is false

my $y = (5 && undef && 3);
# $y gets the value undef, which is false.

$y = (5 && "true" && 4.03);
# $y gets the value 4.03, which is true.

Both operators work in short-circuit evaluation. That is, they
evaluate only as much as they need to in order to determine the boolean
truth of the entire operation. The || keeps evaluating until the first
true value that it sees. The && keeps evaluating until the first false
value that it sees. If either operator exhausts all possibilities
without finding a truth value it's looking for, it returns the last
item in the sequence.

Paul Lalli

P.S. parentheses in all of the above are optional, and only there for
the sake of clarity. However, replacing &&/|| with and/or does require
the parentheses to keep the same precedence.

Bryan R Harris

2006-10-03, 6:58 pm



> Jen Spinney wrote:
>
> In scalar context the expression:
>
> $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i
>
> returns "true" or "false" (1 or '') and in list context it returns the
> contents of any capturing parentheses in the pattern.
>
> The expression:
>
> ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i )[ 0 ]
>
> is a list slice so the regular expression is in list context but the slice is
> a single value so the expression is a scalar.
>
> The || operator will only work with scalar values, not with lists, so this
> works because the list has been converted to a scalar with the list slice.



Thanks, John, Rob, and Mumia. Rob's answer was fast and got me going,
Mumia's answer was more elegant (in my opinion), and John's answer helped me
understand why my code didn't work.

Much appreciated!

- Bryan




Derek B. Smith

2006-10-03, 6:58 pm


> returns "true" or "false" (1 or '') and in list
> context it returns the
> contents of any capturing parentheses in the
> pattern.
>
> The expression:
>
> ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i
> )[ 0 ]
>
> is a list slice so the regular expression is in list
> context but the slice is
> a single value so the expression is a scalar.
>
> The || operator will only work with scalar values,
> not with lists, so this
> works because the list has been converted to a
> scalar with the list slice.
>
>
>
>
> John


****************************************
****
the list context represents everything between the / /
and the slice context represents [ 0 ] which is
assigned as a scalar to $ptypeline.

Correct?

thx
derek

________________________________________
__________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Bryan R Harris

2006-10-03, 6:58 pm



>
> ****************************************
****
> the list context represents everything between the / /
> and the slice context represents [ 0 ] which is
> assigned as a scalar to $ptypeline.
>
> Correct?



Any time you surround something with parenthesis () it is considered "list
context", i.e.

Scalar context: $a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;

In scalar context, perl is trying to assign a scalar to $a. In scalar
context that expression returns a 1 or 0 depending on whether it was able to
find that regular expression inside of $ptypeline. (Or if I had a /gi at
the end it would return the number of matches it found).

List context: @a = ($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i);

This is list context, meaning that perl is trying to get a list out of that
expression. In list context, that expression returns whatever items it
found in sets of parenthesis -- in this case, if ptypeline had "ortho", @a
would be ("ortho").

I'm learning...

- B


Paul Lalli

2006-10-03, 6:58 pm

Bryan R Harris wrote:
> Any time you surround something with parenthesis () it is considered "list
> context", i.e.


Well, sort of, but your concept of "it" is wrong...

> Scalar context: $a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;
>
> In scalar context, perl is trying to assign a scalar to $a. In scalar
> context that expression returns a 1 or 0 depending on whether it was able to
> find that regular expression inside of $ptypeline. (Or if I had a /gi at
> the end it would return the number of matches it found).


No, the /g modifier does not affect the return value of a pattern match
in scalar context.

$x = $foo =~ /bar/; # returns 1 or ""
$x = $foo =~ /bar/g; # return 1 or ""
$x = $foo =~ s/bar/baz/; #returns number of times matched (which is
either 0 or 1)
$x = $foo =~ s/bar/baz/g; #returns number of times matched (which is 0
or more)

> List context: @a = ($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i);
>
> This is list context,


Yes, but it's list context because you assigned to an array, not
because you surrounded the right-side in parentheses. The parens there
are completely optional. The only purpose they serve is for
precedence, and =~ already has a higher precedence than =

> meaning that perl is trying to get a list out of that
> expression. In list context, that expression returns whatever items it
> found in sets of parenthesis -- in this case, if ptypeline had "ortho", @a
> would be ("ortho").


Yes. But you can also create list context for the expression by
assigning to a list of scalars - even a list containing only one
scalar.

($x) = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;

Here, $x will be assigned to whichever of sine, geo, radial, or ortho
was found. Note that in this case, if there were any other parentheses
in the pattern match, their contents would simply be discarded (because
we only have one item on our left).

my $x = "foo bar baz" =~ /\w+\s\w+\s\w+/;
my @y = "foo bar baz" =~ /\w+\s\w+\s\w+/;
my @z = "foo bar baz" =~ /(\w+)\s(\w+)\s(\w+)/;

$x is 1
@y is (1)
@z is ('foo', 'bar', 'baz');

my ($x) = "foo bar baz" =~ /\w+\s\w+\s\w+/;
my ($y) = "foo bar baz" =~ /(\w+)\s(\w+)\s(\w+)/;
my ($a, $b, $c) = "foo bar baz" =~ /(\w+)\s(\w+)\s(\w+)/;

$x is 1
$y is 'foo'
$a is 'foo', $b is 'bar', $c is 'baz'

Hope this helps clarify...

Paul Lalli

John W. Krahn

2006-10-03, 6:58 pm

Bryan R Harris wrote:
>
>
>
> Any time you surround something with parenthesis () it is considered "list
> context", i.e.
>
> Scalar context: $a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;
>
> In scalar context, perl is trying to assign a scalar to $a. In scalar
> context that expression returns a 1 or 0 depending on whether it was able to
> find that regular expression inside of $ptypeline. (Or if I had a /gi at
> the end it would return the number of matches it found).
>
> List context: @a = ($ptypeline =~ /movable.+(sine|geo|radial|ortho)/i);
>
> This is list context, meaning that perl is trying to get a list out of that
> expression. In list context, that expression returns whatever items it
> found in sets of parenthesis -- in this case, if ptypeline had "ortho", @a
> would be ("ortho").


No. It is list context because "@a =" forces list context. In other words:

@a = ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i );

and:

@a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;

are both in list context, the parentheses are superfluous. However in:

$a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;

the expression is in scalar context because "$a =" forces scalar context.
Even if you add parentheses:

$a = ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i );

it is still in scalar context, while:

( $a ) = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;

is in list context because $a is now part of a list.




John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
Bryan R Harris

2006-10-03, 6:58 pm


> Bryan R Harris wrote:
>
> No. It is list context because "@a =" forces list context. In other words:
>
> @a = ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i );
>
> and:
>
> @a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;
>
> are both in list context, the parentheses are superfluous. However in:
>
> $a = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;
>
> the expression is in scalar context because "$a =" forces scalar context.
> Even if you add parentheses:
>
> $a = ( $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i );
>
> it is still in scalar context, while:
>
> ( $a ) = $ptypeline =~ /movable.+(sine|geo|radial|ortho)/i;
>
> is in list context because $a is now part of a list.



Umm... So would this do what I want also?

($ptype)=($projection =~ /movable.+(sine|geo|radial|ortho)/i)
or $ptype="(missing)";

It seems to...

- B



Igor Sutton

2006-10-03, 6:58 pm

>
> Umm... So would this do what I want also?
>
> ($ptype)=($projection =~ /movable.+(sine|geo|radial|ortho)/i)
> or $ptype="(missing)";
>
>

I think the correct is:

$ptype = ($projection =~ /movable.+(sine|geo|radial|ortho)/i) ||
"(missing)";

'||' will be tight with ( $projection =~ ... ) because it has higher
precedence than 'or'. The way you wrote it will assign "(missing)" to
$ptype, then $ptype's value to $ptype again. It works but not the way you
think.

Maybe someone could correct me :-) ?

--
Igor Sutton Lopes <igor.sutton@gmail.com>

Paul Lalli

2006-10-03, 6:58 pm

Igor Sutton wrote:
> I think the correct is:
>
> $ptype = ($projection =~ /movable.+(sine|geo|radial|ortho)/i) ||
> "(missing)";
>
> '||' will be tight with ( $projection =~ ... ) because it has higher
> precedence than 'or'. The way you wrote it will assign "(missing)" to
> $ptype, then $ptype's value to $ptype again. It works but not the way you
> think.
>
> Maybe someone could correct me :-) ?


It's easy enough to check for yourself:

$ perl -le'
my $projection = "movable stuff ortho stuff";
$ptype = ($projection =~ /movable.+(sine|geo|radial|ortho)/i) ||
"(missing)";
print $ptype;
'
1

Please review this entire thread to see why that doesn't work. In
short, || imposes scalar context on its arguments. A pattern match in
scalar context returns 1 or "", not the contents of parenthesized
sub-matches.

Paul Lalli

Mumia W.

2006-10-03, 6:58 pm

On 10/03/2006 11:37 AM, Derek B. Smith wrote:
>
> ****************************************
****
> the list context represents everything between the / /
> and the slice context represents [ 0 ] which is
> assigned as a scalar to $ptypeline.
>
> Correct?
> [...]


No, $ptypeline is the string that is being searched.



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com