develooper Front page | perl.perl5.porters | Postings from September 2013

[perl #120047] perl should enable "$_" for use before calling subs

Thread Previous | Thread Next
From:
Linda Walsh
Date:
September 29, 2013 09:26
Subject:
[perl #120047] perl should enable "$_" for use before calling subs
Message ID:
rt-3.6.HEAD-31239-1380446788-353.120047-75-0@perl.org
# New Ticket Created by  Linda Walsh 
# Please include the string:  [perl #120047]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=120047 >



This is a bug report for perl from perl-diddler@tlinx.org,
generated with the help of perlbug 1.39 running under perl 5.16.2.


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

I wasn't sure if this should be filed as a bug but the more
I think about it, perl without "$_" would be like making 
hardware registers read-only then calling subroutines and expecting
them to work without their main registers.

While it is usually possible to program without using "$_", it
is considered efficient and a sign of language mastery to make full
use of perl's idiom and not try to use it as a general purpose 
programming language.  using $_ in for loops/ grep, map, and
an implied operand for many perl builtins is considered an effective
use of the language.  It is counter productive to disable the usage
of ideomatic perl by making $_ "read-only" in called-subs.  

Instead, when $_ is aliased to a constant, when code control exits the
lexical scope of the for loop by calling funcs outside of the loop, 
the readonly status of $_ needs to be "noted" and saved as part of the
current context.  In subroutines, though they need to be able to use
$_ "normally", or it places an undo and unnecessary constraing on
those developing libraries.  They don't know where they will be called
from, thus, one could argue that any code that is "called" cannot use
"$_".  This places a large handicap on all "called code".  Any modifications
done to "$_" in sub functions would be ignored upon return to the lexical
scope where $_ was read-only.  

It is the case that various "builtin"s already do this.  So one would be
hard pressed to find a case where builtin's can do it (can in turn call
other subs where now "$_" is no longer R/O), but not allow
user-level code that that tries to use $_ ideomatically, but magically
fails due to $_ being protected.  

Regardless of documenation that may justify this behavior, I would like to
see the design reasons for this behavior if such is to be found.  
I see no logic in disabling $_, **randomly*** (based on callstack) in
a sub-function or library call but allowing it for built-ins.  There
are things that can't be done without extraneous declarations without
using the $_ register (like a postfix for-loop).

Can this oversite be fixed?  Can people not make stuff up
as to why it can't or shouldn't be done as was done when I suggested
allowing  explicitly declared local vars to be retained over a goto and
not popped until the call-stack is popped, as in my mind, the 
target of the &goto was effectively becoming part of the initially
called procedure, with the &goto allowing for a common back end for
multiple front-end functions.  In that sense not popping local until
the common back end is done makes sense.  But I was given a special
case example that would have been better coded in a loop than trying
to do tail recursion, which it turns out is not really that optimized
at all.

The way I see that one, BTW, is that the local decl remains in 
effect if the goto happens before exiting context that would 
pop-the local, but if the context where local was used is left
before the goto, it would be popped as normal.  Anyway, I'm getting
off topic.  This was about readonly $_ and how it shouldn't be 
imposed on out-of-scope subs as, truthfully, having routines that
work for months to years fail because your code usually uses vars 
to iterate over in a for-loop, but having it fail in rare cases where
a $_ pops up as read-only, is really an obscure design case that
library writers shouldn't need to work about.

It's just too quirky to have things like a "for" loop work but not 
similar while loop that may be better form to avoid list overhead.

Short prog that determines iterations of rand picking a-c to match
one of them -- iterated through for each a, b, c).

Case 1 works fine,
Case 2 fails


perl -MP -we'use strict;

#iterations of rand to match 1 of 3 items

sub mysub { my $val=$_[0];
	my $cnt=0; my $__=$_;
	do {
		$_=(qw(x y z))[int(3*rand)];
		++$cnt;
	} while $_ ne $val;
	$_=$__;
	return $cnt
}

our ($x, $y, $z);
P "case1";

our @vars=qw(x y z);
for (@vars) {
	no strict qw(refs);
	$$_=mysub($_);
	P "%s", [$x,$y,$z];
}

P "case2";
for (qw(x y z)) { 
	no strict qw(refs);
	$$_=mysub($_);
	P "%s", [$x,$y,$z];
}

'
=====
output: 
 /tmp/t1
case1
[1, ∄, ∄]
[1, 3, ∄]
[1, 3, 1]
case2
Modification of a read-only value attempted at -e line 7.
====

It's not hard to see how this could increase unreliability
of code and how fixing it would make code more reliable.



[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=medium
---
This perlbug was built using Perl 5.16.2 - Fri Feb 15 01:17:37 UTC 2013
It is being executed now by  Perl 5.16.2 - Fri Feb 15 01:12:05 UTC 2013.

Site configuration information for perl 5.16.2:

Configured by abuild at Fri Feb 15 01:12:05 UTC 2013.

Summary of my perl5 (revision 5 version 16 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=3.4.6-2.10-default, archname=x86_64-linux-thread-multi
    uname='linux build34 3.4.6-2.10-default #1 smp thu jul 26 09:36:26 utc 2012 (641c197) x86_64 x86_64 x86_64 gnulinux '
    config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Dd_dbm_open -Duseshrplib=true -Doptimize=-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe -Accflags=-DPERL_USE_SAFE_PUTENV -Dotherlibdirs=/usr/lib/perl5/site_perl'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -pipe -fstack-protector'
    ccversion='', gccversion='4.7.2 20130108 [gcc-4_7-branch revision 195012]', 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 =' -L/usr/local/lib64 -fstack-protector'
    libpth=/lib64 /usr/lib64 /usr/local/lib64
    libs=-lm -ldl -lcrypt -lpthread
    perllibs=-lm -ldl -lcrypt -lpthread
    libc=/lib64/libc-2.17.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.16.2/x86_64-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib64 -fstack-protector'

Locally applied patches:
    

---
@INC for perl 5.16.2:
    /home/law/bin/lib
    /usr/lib/perl5/site_perl/5.16.2/x86_64-linux-thread-multi
    /usr/lib/perl5/site_perl/5.16.2
    /usr/lib/perl5/vendor_perl/5.16.2/x86_64-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.16.2
    /usr/lib/perl5/5.16.2/x86_64-linux-thread-multi
    /usr/lib/perl5/5.16.2
    /usr/lib/perl5/site_perl/5.16.2/x86_64-linux-thread-multi
    /usr/lib/perl5/site_perl/5.16.2
    /usr/lib/perl5/site_perl
    .

---
Environment for perl 5.16.2:
    HOME=/home/law
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=C
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH=/usr/lib64/mpi/gcc/openmpi/lib64
    LOGDIR (unset)
    PATH=/home/law/bin/lib:/sbin:/usr/local/sbin:/usr/lib64/mpi/gcc/openmpi/bin:/home/law/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/opt/kde3/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:.:/usr/lib/qt3/bin:/opt/dell/srvadmin/bin:/usr/sbin:/etc/local/func_lib:/home/law/lib
    PERL5OPT=-Mutf8 -CSA -I/home/law/bin/lib
    PERL_BADLANG (unset)
    SHELL=/bin/bash


Thread Previous | 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