develooper Front page | perl.perl5.porters | Postings from January 2014

[perl #120954] perlsub should be more explicit when an implicit return encounters an if(){} statement

Thread Next
From:
David Oswald
Date:
January 9, 2014 17:42
Subject:
[perl #120954] perlsub should be more explicit when an implicit return encounters an if(){} statement
Message ID:
rt-4.0.18-13838-1389201396-901.120954-75-0@perl.org
# New Ticket Created by  David Oswald 
# Please include the string:  [perl #120954]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/Ticket/Display.html?id=120954 >


This is a bug report for perl from daoswald@gmail.com,
generated with the help of perlbug 1.39 running under perl 5.18.1.


-----------------------------------------------------------------
[Please describe your issue here]

perlsub says this about implicit returns:

    If no return is found and if the last statement is an
    expression, its value is returned. If the last statement is
    a loop control structure like a foreach or a while , the
    returned value is unspecified.

Now consider the following code:

    $x = 1;
    sub foo { if( $x ) { 0 } }
    print foo(), "\n";

The output will be 0, presumably because the last statement
is the expression, numeric '0'.

How about this:

    $x = 0;
    sub foo { if( $x ) { 1 } }
    print foo(), "\n";

The output will be 0, presumably because the last expression
to be evaluated is '$x', which has a value of 0.  But the last
statement to execute is literally "if()".  If we run this past
B::Concise we find that the construct is converted into
something similar to sub { $x and 1 }, so it is intuitive that
the return value will be $x if false, or 1 if $x is true.

Although this behavior is possibly a little confusing to
someone who doesn't read between the lines in perlsub, it seems
reasonably stable (it's been with us forever), and unlikely to
change in the future.  Therefore, perlsub should state the
following:

    If no L<return> is found and if the last statement is an
    expression, its value is returned.  If the last statement
    is an C<if( CONDITION ) { BLOCK }> construct, the value
    of the return value will come from C<BLOCK> if C<CONDITION>
    is true, or from C<CONDITION> if C<CONDITION> is false.
    Relying on this behavior is detremental to code legibility.
    If the last statement is a loop control structure like a
    C<foreach> or a C<while>, the returned value is unspecified.


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=docs
    severity=low
---
Site configuration information for perl 5.18.1:

Configured by davido at Sat Oct 26 14:56:49 MDT 2013.

Summary of my perl5 (revision 5 version 18 subversion 1) configuration:

  Platform:
    osname=linux, osvers=3.11.0-12-generic, archname=x86_64-linux
    uname='linux catalina 3.11.0-12-generic #19-ubuntu smp wed oct 9
16:20:46 utc 2013 x86_64 x86_64 x86_64 gnulinux '
    config_args='-de
-Dprefix=/home/davido/perl5/perlbrew/perls/perl-5.18.1
-Aeval:scriptdir=/home/davido/perl5/perlbrew/perls/perl-5.18.1/bin'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.8.1', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib
/usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib
-fstack-protector'

Locally applied patches:


---
@INC for perl 5.18.1:
    /home/davido/.perlbrew/libs/perl-5.18.1@5.18/lib/perl5/x86_64-linux
    /home/davido/.perlbrew/libs/perl-5.18.1@5.18/lib/perl5
    /home/davido/perl5/perlbrew/perls/perl-5.18.1/lib/site_perl/5.18.1/x86_64-linux
    /home/davido/perl5/perlbrew/perls/perl-5.18.1/lib/site_perl/5.18.1
    /home/davido/perl5/perlbrew/perls/perl-5.18.1/lib/5.18.1/x86_64-linux
    /home/davido/perl5/perlbrew/perls/perl-5.18.1/lib/5.18.1
    .

---
Environment for perl 5.18.1:
    HOME=/home/davido
    LANG=en_US.UTF-8
    LANGUAGE=en_US
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/davido/.perlbrew/libs/perl-5.18.1@5.18/bin:/home/davido/perl5/perlbrew/bin:/home/davido/perl5/perlbrew/perls/perl-5.18.1/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
    PERL5LIB=/home/davido/.perlbrew/libs/perl-5.18.1@5.18/lib/perl5
    PERLBREW_BASHRC_VERSION=0.66
    PERLBREW_HOME=/home/davido/.perlbrew
    PERLBREW_LIB=5.18
    PERLBREW_MANPATH=/home/davido/.perlbrew/libs/perl-5.18.1@5.18/man:/home/davido/perl5/perlbrew/perls/perl-5.18.1/man
    PERLBREW_PATH=/home/davido/.perlbrew/libs/perl-5.18.1@5.18/bin:/home/davido/perl5/perlbrew/bin:/home/davido/perl5/perlbrew/perls/perl-5.18.1/bin
    PERLBREW_PERL=perl-5.18.1
    PERLBREW_ROOT=/home/davido/perl5/perlbrew
    PERLBREW_VERSION=0.66
    PERL_BADLANG (unset)
    PERL_LOCAL_LIB_ROOT=/home/davido/.perlbrew/libs/perl-5.18.1@5.18
    PERL_MB_OPT=--install_base /home/davido/.perlbrew/libs/perl-5.18.1@5.18
    PERL_MM_OPT=INSTALL_BASE=/home/davido/.perlbrew/libs/perl-5.18.1@5.18
    SHELL=/bin/bash


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About