Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Clarifying smart match behaviour in when( ... && ... )

15 views
Skip to first unread message

Brian D Foy

unread,
Jan 29, 2008, 10:20:31 PM1/29/08
to perl5-...@perl.org
#!/usr/local/bin/perl5.10.0

=pod

I'm trying to figure out when() using smart-matching combined
with logical operators for the next edition of Learning Perl.

For a little background: perlsyn notes that there are exceptions
to smart matching in when():


* a subroutine call
* a regex using $_ by default (which is a smart match, btw)
* a regex expliclty bound to a variable (negated, even)
* an explicit comparison
* defined(), exists(), or eof()
* a negated expression (!, not)
* an xor

Right after that bit in perlsyn, it talks about &&.

If EXPR is ... && ... or ... and ... , the test is applied
recursively to both arguments. If both arguments pass the
test, then the argument is treated as boolean.

That last sentence is weird. If both arguments pass the test,
it's treated as boolean. What does that imply if one or both
don't pass the test? And, is "test" just "one of the previously
listed exceptions".

So, the example I was playing with wanted to check if a value was
in an array and also the key of a hash:

given( $foo ) {
when( @n && %n ) { ... }
}

Since neither of the arguments are one of the exceptions, I
expected both arguments to be treated as a smart match:

given( $foo ) {
when( $_ ~~ @n && $_ ~~ %n ) { ... }
}

Now, nothing in the docs say that should be the case, so before I
do too much work in going through the other odd situations I
found, I figure I'll check if it's a doc problem first or if I'm
being a lunkhead.

Here's what I think the docs are trying to say, and once we get
this right (which might mean correcting my thinking and
documenting it better) I can think about the rest of it:

If EXPR is ... && ... or ... and ..., and both of the
arguments are one of the listed exceptions, Perl treats both
arguments as booleans and performs no smart matching. If only
one of the arguments is one of the exceptions, Perl treats
that argument as a boolean and performs a smart match with
the other argument. If neither argument is one of the
exceptions, Perl performs a separate smart match with each
argument.

However, I don't know how to square the statement with a test in
t/op/switch.t. I think the test comment might be wrong. Should
there be a smart match that fails in the first when(), which is
why it moves onto the second? If so, the comment should say
something like "((1 == 1) && \"bar\") used smart match and fails
like it should".

# t/op/switch.t
{
my $ok = 1;
given("foo") {
when((1 == 1) && "bar") {
$ok = 0;
}
when((1 == 1) && $_ eq "foo") {
$ok = 2;
}
}
is($ok, 2, "((1 == 1) && \"bar\") not smartmatched");
}

I'll happily add some more tests once I know what the answers should
be. :)

Here's a program I was playing with, and the output I got that led me
to all of this.

=cut

use 5.010;

my @n = qw(0 Barney Wilma);
my %n = map { $_, 1 } @n;


$\ = "\n\t";

for( '', qw(0 1 Barney) )
{
my $n = $_;

say "\nProcessing [$n]...";

when( %n )
{ say "1. In \%n"; continue } # $_ ~~ %n
when( @n )
{ say "2. In \@n"; continue } # $_ ~~ @n
when( @n && %n )
{ say "3. @n && %n" } # $_ ~~ @n && $_ ~~ %n ???
}

__DATA__

Processing []...

Processing [0]...
1. In %n
2. In @n

Processing [1]...

Processing [Barney]...
1. In %n
2. In @n

--------

macbookpro_brian[2845]$ perl5.10.0 -V
Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
Platform:
osname=darwin, osvers=8.10.1, archname=darwin-2level
uname='darwin alexandria2-10.nyc.access.net 8.10.1 darwin kernel
version 8.10.1: wed may 23 16:33:00 pdt 2007;
root:xnu-792.22.5~1release_i386 i386 i386 '
config_args=''
hint=recommended, useposix=true, d_sigaction=define
useithreads=undef, usemultiplicity=undef
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp
-fno-strict-aliasing -pipe -I/usr/local/include -I/opt/local/include',
optimize='-O3',
cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp
-fno-strict-aliasing -pipe -I/usr/local/include -I/opt/local/include'
ccversion='', gccversion='4.0.1 (Apple Computer, Inc. build 5363)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags ='
-L/usr/local/lib -L/opt/local/lib'
libpth=/usr/local/lib /opt/local/lib /usr/lib
libs=-ldbm -ldl -lm -lc
perllibs=-ldl -lm -lc
libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false,
libperl=libperl.a
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup
-L/usr/local/lib -L/opt/local/lib'


Characteristics of this binary (from libperl):
Compile-time options: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP
USE_LARGE_FILES USE_PERLIO
Locally applied patches:
RC2
Built under darwin
Compiled at Dec 2 2007 12:18:58
@INC:
/usr/local/perls/perl-5.10.0-rc2/lib/5.10.0/darwin-2level
/usr/local/perls/perl-5.10.0-rc2/lib/5.10.0
/usr/local/perls/perl-5.10.0-rc2/lib/site_perl/5.10.0/darwin-2level
/usr/local/perls/perl-5.10.0-rc2/lib/site_perl/5.10.0
.

Joshua ben Jore

unread,
Feb 18, 2008, 3:58:46 PM2/18/08
to brian d foy, perl5-...@perl.org
On Jan 29, 2008 7:20 PM, brian d foy <brian...@gmail.com> wrote:
> #!/usr/local/bin/perl5.10.0

I responded to your use.perl post but here's it for p5p too. You are
experiencing a bug. I doubt the implementation is what anyone
intended. Here's what's actually happening:

given( 'Barney' ) { when( @n and %n ) }
=> ( scalar( @n ) and scalar( %n ) ) ~~ 'Barney'
=> ( 3 and '2/8' ) ~~ 'Barney'
=> '2/8' ~~ 'Barney'
=> '2/8' eq 'Barney'
=> false

Josh

Brian D Foy

unread,
Feb 18, 2008, 5:26:20 PM2/18/08
to perl5-...@perl.org
In article
<dc5c751d0802181258g6c6...@mail.gmail.com>, Joshua
ben Jore <twi...@gmail.com> wrote:

> On Jan 29, 2008 7:20 PM, brian d foy <brian...@gmail.com> wrote:
> > #!/usr/local/bin/perl5.10.0
>
> I responded to your use.perl post but here's it for p5p too. You are
> experiencing a bug. I doubt the implementation is what anyone
> intended. Here's what's actually happening:

As you pointed out in private email, Perl 5's version shouldl do what
Perl 6's will do. I've asked on perl6.langauge and I'll wait for Larry
to make the ruling. I didn't see the answer in S04.

Once I have confirmation that I'm thinking about his right, I'll make a
doc patch and add more tests (although I don't think my patch in
#50538
was applied yet).

Thanks,

Joshua ben Jore

unread,
Feb 18, 2008, 5:40:00 PM2/18/08
to brian d foy, perl5-...@perl.org

To the extent that any parts of this behavior are likely to change in
Perl 6, I would like Perl 5 to have undefined behavior. If having more
than one element as a target to ~~ or in a when() clause isn't fully
settled, Perl 5 should bail and throw a syntax error.

Josh

0 new messages