[Groningen-pm] Precedence verschil '||' en 'or'

Arnoud Warmerdam aw at warpnet.nl
Tue Aug 29 07:09:25 PDT 2006


Johan Vromans wrote:
> De vraag is wat je met dit statement wilt. Je bedoelt (neem ik aan):
> 
>     my ($newsecond) = m|^.*?\[\d+/\w+/\d+:(\d\d:\d\d:\d\d) \+\d+\]|
>        || warn "...";

Klopt.

> Omdat je in dit soort gevallen eigenlijk nooit echt de waarde van de
> warn (of die, of print)  wilt toekennen is het dus beter om de
> lager-prioriteit "or" te gebruiken:
>
>     my ($newsecond) = m|^.*?\[\d+/\w+/\d+:(\d\d:\d\d:\d\d) \+\d+\]|
>         or warn "...";

Agreed.

> Nu krijgt $newsecond de waarde undefined (die hij al had, maar okee)
> als de match faalt.

Klopt, en bij gebruik van '||' krijgt $newsecond de waarde 1.

Maar het probleem is niet zozeer wat er gebeurt als de match faalt, maar 
juist wat er gebeurt als hij succesvol is. Mijn bedoeling is dat het 
eerste element van het resultaat van de regex ($1) geassigned wordt aan 
$newsecond ($ns for short), dus:

	( ($ns) = regex ) || die;   # purpose: $ns = $1;

Omdat de '||' operator precedence heeft over de assignment operator is
dit echter wat er gebeurt:

	($ns) = ( regex || die );   # effect: $ns = 1;

In dit geval is het dus beter om 'or' te gebruiken. Echter, in dit geval:

	my $treshold = shift(@ARGV) || 10;

wil je juist '||' hebben, anders staat er:

	( my $treshold = shift(@ARGV) ) || 10;

waardoor $treshold niet de default waarde 10 krijgt als er geen argument 
wordt meegegeven. Dus zowel '||' als 'or' zijn nuttig, of zoals 
http://perl.plover.com/FAQs/Precedence.html het zegt: "use || for 
selecting values, and use or for controlling the flow of statements".

Voor de echte liefhebber: onderaan dit mailtje staat een testscriptje. 
Probeer maar eens te voorspellen welke waardes uit de diverse tests 
komen en welke warnings Perl genereert ...

Groeten,

Arnoud

==================== testscriptje ============================
#!/usr/bin/perl

use warnings;
use strict;

$_ = 'example';
my @testarray = (10, 20);
my %test;

   # Tests with '||':
   $test{'1a'}   = /^exam$/          ||  warn "Warning for test 1a.\n";
   $test{'2a'}   = /^example$/       ||  warn "Warning for test 2a.\n";
   $test{'3a'}   = /^(example)$/     ||  warn "Warning for test 3a.\n";
   $test{'4a'}   = /^(ex)(ample)$/   ||  warn "Warning for test 4a.\n";
  ($test{'5a'})  = /^(example)$/     ||  warn "Warning for test 5a.\n";
  ($test{'6a'})  = /^(ex)(ample)$/   ||  warn "Warning for test 6a.\n";
  ($test{'7a'})  = (/^(ex)(ample)$/) ||  warn "Warning for test 7a.\n";
   $test{'8a'}   = 10 || 20;
   $test{'9a'}   = 0 || 20;
   $test{'aa'}   = (10, 20) || 30;
   $test{'ba'}   = @testarray || 30;

   # Tests with 'or':
   $test{'1b'}   = /^exam$/          or  warn "Warning for test 1b.\n";
   $test{'2b'}   = /^example$/       or  warn "Warning for test 2b.\n";
   $test{'3b'}   = /^(example)$/     or  warn "Warning for test 3b.\n";
   $test{'4b'}   = /^(ex)(ample)$/   or  warn "Warning for test 4b.\n";
  ($test{'5b'})  = /^(example)$/     or  warn "Warning for test 5b.\n";
  ($test{'6b'})  = /^(ex)(ample)$/   or  warn "Warning for test 6b.\n";
  ($test{'7b'})  = (/^(ex)(ample)$/) or  warn "Warning for test 7b.\n";
   $test{'8b'}   = 10 or 20;
   $test{'9b'}   = 0 or 20;
   $test{'ab'}   = (10, 20) or 30;
   $test{'bb'}   = @testarray || 30;

foreach(sort(keys(%test)))
{
   printf("Test %2s: '%s'.\n", $_, $test{$_});
}
=================== /testscriptje ============================


More information about the Groningen-pm mailing list