Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perlsub should be more explicit when an implicit return encounters an if(){} statement #13516

Open
p5pRT opened this issue Jan 8, 2014 · 3 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 8, 2014

Migrated from rt.perl.org#120954 (status was 'open')

Searchable as RT120954$

@p5pRT
Copy link
Author

p5pRT commented Jan 8, 2014

From daoswald@gmail.com

Created by daoswald@gmail.com

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.

Perl Info

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

@p5pRT
Copy link
Author

p5pRT commented Jan 9, 2014

From @tonycoz

On Wed Jan 08 09​:16​:36 2014, daoswald wrote​:

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\.

...

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.

For reference, the current text was set in
dbb128b and
9a98977.

It was discussed in the following threads​:

http​://www.nntp.perl.org/group/perl.perl5.porters/2005/10/msg105810.html

http​://www.nntp.perl.org/group/perl.perl5.porters/2005/10/msg105889.html

I think the current text is fine.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 9, 2014

The RT System itself - Status changed from 'new' to 'open'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants