[32544] in Perl-Users-Digest
Perl-Users Digest, Issue: 3809 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Sun Nov 4 14:09:27 2012
Date: Sun, 4 Nov 2012 11:09:10 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Sun, 4 Nov 2012 Volume: 11 Number: 3809
Today's topics:
Re: array <hjp-usenet2@hjp.at>
Re: array <rvtol+usenet@xs4all.nl>
Re: array <hjp-usenet2@hjp.at>
Re: array (Seymour J.)
Re: array <rvtol+usenet@xs4all.nl>
Re: array <hjp-usenet2@hjp.at>
Re: Clear the "Wide character in print" warning and lea jidanni@jidanni.org
Re: Clear the "Wide character in print" warning and lea jidanni@jidanni.org
Re: Clear the "Wide character in print" warning and lea <hjp-usenet2@hjp.at>
Re: Trampoline sub <rweikusat@mssgmbh.com>
Re: Trampoline sub <derykus@gmail.com>
Re: Trampoline sub <rweikusat@mssgmbh.com>
Re: Trampoline sub (Tim McDaniel)
Re: Trampoline sub (Tim McDaniel)
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Sat, 3 Nov 2012 18:55:44 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: array
Message-Id: <slrnk9aml0.c6r.hjp-usenet2@hrunkner.hjp.at>
On 2012-11-03 11:23, Dr.Ruud <rvtol+usenet@xs4all.nl> wrote:
> On 2012-11-02 13:27, Shmuel (Seymour J.) Metz wrote:
>> Bill:
>
>>> Higher level too. Much easier to use. Here I don't think arrays
>>> have to be iterated over like with C. I can't even remember right
>>> off how to do that.
>>
>> There's a for statement with C-like syntax, but I don't believe that
>> I've ever used it; I find foreach more convenient. If you're iterating
>> over steps rather than over elements of an array, you can still use
>> foreach, in conjunction with a range operator:
>>
>> foreach (1..10)
>
> In Perl, 'for' and 'foreach' are the same.
Yes. But this style of loop is still commonly called the "foreach loop",
even though almost everybody writes “for (1..10)”.
> Be careful with long ranges
> like for ( 1 .. 1_000_000_000 ),
> since they are not lazy:
Yes, they are. See below.
> time perl -wle '
> my $i;
> for ( 1 .. 100_000_000 ) {
> ++$i;
> }
> print $i;
> '
> 100000000
>
> real 0m10.005s
> user 0m9.966s
> sys 0m0.016s
>
>
> time perl -wle '
> my $i;
> foreach ( $i= 0; $i < 100_000_000; $i++ ) {
> ++$i;
> }
> print $i;
> '
> 100000000
>
> real 0m6.321s
> user 0m6.291s
> sys 0m0.012s
This increments $i twice per iteration, so the loop runs only 50 million
times. Do it right and it is slower than the “foreach loop”:
time perl -wle '
my $j;
foreach ( $i= 0; $i < 100_000_000; $i++ ) {
++$j;
}
print $j;
'
13.63s vs. 9.10s on one system,
7.43s vs. 5.47s on another.
Just for laughs, here is the non-lazy version:
time perl -wle '
my $i;
my @a = ( 1 .. 100_000_000 );
for (@a) {
++$i;
}
print $i;
'
100000000
perl -wle 22.57s user 23.30s system 99% cpu 45.938 total
So this is about 45.94 / 5.47 == 8.4 times slower than the foreach loop
with the range operator and it uses about 7.5 GB of virtual memory (so
it doesn't even run on a 32 bit system).
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
------------------------------
Date: Sat, 03 Nov 2012 20:50:12 +0100
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: array
Message-Id: <50957574$0$6948$e4fe514c@news2.news.xs4all.nl>
On 2012-11-03 18:55, Peter J. Holzer wrote:
> On 2012-11-03 11:23, Dr.Ruud <rvtol+usenet@xs4all.nl> wrote:
>> On 2012-11-02 13:27, Shmuel (Seymour J.) Metz wrote:
>>> Bill:
>>>> Higher level too. Much easier to use. Here I don't think arrays
>>>> have to be iterated over like with C. I can't even remember right
>>>> off how to do that.
>>>
>>> There's a for statement with C-like syntax, but I don't believe that
>>> I've ever used it; I find foreach more convenient. If you're iterating
>>> over steps rather than over elements of an array, you can still use
>>> foreach, in conjunction with a range operator:
>>>
>>> foreach (1..10)
>>
>> In Perl, 'for' and 'foreach' are the same.
>
> Yes. But this style of loop is still commonly called the "foreach loop",
> even though almost everybody writes “for (1..10)”.
>> Be careful with long ranges
>> like for ( 1 .. 1_000_000_000 ),
>> since they are not lazy:
>
> Yes, they are. See below.
>
>
>> time perl -wle '
>> my $i;
>> for ( 1 .. 100_000_000 ) {
>> ++$i;
>> }
>> print $i;
>> '
>> 100000000
>>
>> real 0m10.005s
>> user 0m9.966s
>> sys 0m0.016s
>>
>>
>> time perl -wle '
>> my $i;
>> foreach ( $i= 0; $i < 100_000_000; $i++ ) {
>> ++$i;
>> }
>> print $i;
>> '
>> 100000000
>>
>> real 0m6.321s
>> user 0m6.291s
>> sys 0m0.012s
>
> This increments $i twice per iteration, so the loop runs only 50 million
> times. Do it right and it is slower than the “foreach loop”:
>
> time perl -wle '
> my $j;
> foreach ( $i= 0; $i < 100_000_000; $i++ ) {
> ++$j;
> }
> print $j;
> '
>
> 13.63s vs. 9.10s on one system,
> 7.43s vs. 5.47s on another.
>
> Just for laughs, here is the non-lazy version:
>
> time perl -wle '
> my $i;
> my @a = ( 1 .. 100_000_000 );
> for (@a) {
> ++$i;
> }
> print $i;
> '
> 100000000
> perl -wle 22.57s user 23.30s system 99% cpu 45.938 total
>
> So this is about 45.94 / 5.47 == 8.4 times slower than the foreach loop
> with the range operator and it uses about 7.5 GB of virtual memory (so
> it doesn't even run on a 32 bit system).
Ah, thanks for the correction, and sorry for spreading FUD.
I had been bitten by this once,
but that must then have been that array version.
--
Ruud
------------------------------
Date: Sat, 3 Nov 2012 22:07:02 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: array
Message-Id: <slrnk9b1rn.c5g.hjp-usenet2@hrunkner.hjp.at>
On 2012-11-03 19:50, Dr.Ruud <rvtol+usenet@xs4all.nl> wrote:
> On 2012-11-03 18:55, Peter J. Holzer wrote:
>> On 2012-11-03 11:23, Dr.Ruud <rvtol+usenet@xs4all.nl> wrote:
>>> Be careful with long ranges
>>> like for ( 1 .. 1_000_000_000 ),
>>> since they are not lazy:
>>
>> Yes, they are. See below.
[big snip]
> Ah, thanks for the correction, and sorry for spreading FUD.
> I had been bitten by this once,
> but that must then have been that array version.
for (1 .. $n) { ... } did indeed build a temporary list once upon time.
That was long ago (I don't remember when it was changed. 5.6?), but as a
long-time perl programmer it is quite likely that were bitten by this.
One of the reasons why I hang out in this newsgroup is that the
discussions here constantly cause me to test the validity of my old
prejudices by re-running old benchmarks or to writing new ones.
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpat. -- Ralph Babel
------------------------------
Date: Sun, 04 Nov 2012 01:18:35 -0400
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: array
Message-Id: <5095faab$17$fuzhry+tra$mr2ice@news.patriot.net>
In <5094feb7$0$6916$e4fe514c@news2.news.xs4all.nl>, on 11/03/2012
at 12:23 PM, "Dr.Ruud" <rvtol+usenet@xs4all.nl> said:
>In Perl, 'for' and 'foreach' are the same.
"for loops" in perlsyn documents the C-style for loop as distint from
foreach..
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Sun, 04 Nov 2012 17:12:16 +0100
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: array
Message-Id: <509693e0$0$6871$e4fe514c@news2.news.xs4all.nl>
On 2012-11-04 06:18, Shmuel (Seymour J.) Metz wrote:
> In <5094feb7$0$6916$e4fe514c@news2.news.xs4all.nl>, on 11/03/2012
> at 12:23 PM, "Dr.Ruud" <rvtol+usenet@xs4all.nl> said:
>> In Perl, 'for' and 'foreach' are the same.
>
> "for loops" in perlsyn documents the C-style for loop as distint from
> foreach..
From perlsyn:
The "foreach" keyword is actually a synonym for the "for" keyword, so
you can use "foreach" for readability or "for" for brevity.
(I just never use foreach)
--
Ruud
------------------------------
Date: Sun, 4 Nov 2012 18:16:43 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: array
Message-Id: <slrnk9d8nr.g7j.hjp-usenet2@hrunkner.hjp.at>
On 2012-11-04 16:12, Dr.Ruud <rvtol+usenet@xs4all.nl> wrote:
> On 2012-11-04 06:18, Shmuel (Seymour J.) Metz wrote:
>> In <5094feb7$0$6916$e4fe514c@news2.news.xs4all.nl>, on 11/03/2012
>> at 12:23 PM, "Dr.Ruud" <rvtol+usenet@xs4all.nl> said:
>
>>> In Perl, 'for' and 'foreach' are the same.
>>
>> "for loops" in perlsyn documents the C-style for loop as distint from
>> foreach..
>
> From perlsyn:
>
> The "foreach" keyword is actually a synonym for the "for" keyword, so
> you can use "foreach" for readability or "for" for brevity.
I very much suspect that Shmuel knows this.
But the documentation still calls this style of loops "Foreach Loops"
and the C-style loops "For loops".
> (I just never use foreach)
Neither do I. I don't think I've ever seen the foreach keyword outside
of the documentation. But if you talk about different loop styles you
need a name for this style. Perldoc perlsyn calls it a "foreach loop".
So why should we not stick with that name? (Yes, I know, it's ambiguous:
You could also write "foreach ($i = 0; $i < 10; $i++)" and call that a
"foreach loop", but who would?)
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpat. -- Ralph Babel
------------------------------
Date: Sun, 04 Nov 2012 12:28:17 +0800
From: jidanni@jidanni.org
Subject: Re: Clear the "Wide character in print" warning and leave the output unmangled
Message-Id: <87k3u2j8ke.fsf@jidanni.org>
No you don't need a Youtube account.
Yes I tried all you said but it doesn't work.
Even on http://ahinea.com/en/tech/perl-unicode-struggle.html
#!/usr/bin/perl
my $ustring1 = "Hello \x{263A}!\n";
binmode DATA, ":utf8";
my $ustring2 = <DATA>;
print "$ustring1$ustring2";
__DATA__
Hello ☺!
This should print two equal lines and make no annoying warning.
But nowadays it DOES make the annoying warning.
In my program no matter if I do
# $entry->title;
utf8::is_utf8( $entry->title )
? $entry->title
: encode( "utf8", $entry->title );
with encode or decode etc. etc. it doesn't work.
It all just doesn't work.
------------------------------
Date: Sun, 04 Nov 2012 12:29:17 +0800
From: jidanni@jidanni.org
Subject: Re: Clear the "Wide character in print" warning and leave the output unmangled
Message-Id: <87k3u2j8keAZ.fsf@jidanni.org>
Here's my stupid program again.
#!/usr/bin/perl
# How to test this program:
# $ export restriction=TW; PERLLIB=$HOME/perl5/lib/perl5 ./ytpl jidanni2 > /tmp/o
# $ cat /tmp/o
# That will show you any problems it has.
# No you don't need a youtube account.
# Print out YouTube playlists. Usage:
# Example: $0 YouTubeUserID
# Example: restriction=TW $0 jidanni2
# Copyright : http://www.fsf.org/copyleft/gpl.html
# Author : Dan Jacobson -- http://jidanni.org/
# Created On : Wed Mar 2 08:35:33 2011
# Last Modified On: Sun Nov 4 12:38:33 2012
# Update Count : 851
use strict;
use Encode;
#use warnings FATAL => 'all';
binmode STDERR, ":utf8";
#binmode STDOUT, ":utf8";
binmode STDIN, ":utf8";
#use utf8;
#use open qw/:std :encoding(utf8)/;
##use diagnostics;
#use Data::Dumper;
use WebService::GData::Constants qw(:all);
use WebService::GData::YouTube;
die 'Specify a user please.' unless my $user = shift;
my ( %checklist, %vids, $playlists, );
my $yt = new WebService::GData::YouTube();
$yt->connection->env_proxy;
##$yt->connection->enable_compression(TRUE); #disaster
$yt->query->max_results(50);
#if the number of your playlist is superior to 50, you will need to
#loop via the result like you used to do before with the video results
#(start_index+items_per_page). there is no other easy way to do this
#yet.
eval { $playlists = $yt->get_user_playlists($user) } or die $@->content;
@$playlists = sort { $a->title cmp $b->title } @$playlists;
for ( $ENV{restriction} ) { $yt->query()->restriction($_) if $_ }
for my $playlist (@$playlists) {
my @missing = (undef) x $playlist->count_hint;
my $entries;
while (
eval {
## can't use compression starting here:
$entries = $yt->get_user_playlist_by_id( $playlist->playlist_id );
}
)
{
die $@->content if $@;
for my $entry (@$entries) {
my $IDP = ( split( /:/, $entry->id ) )[-1] or die;
if ( $entry->appcontrol_state
&& $entry->appcontrol_state eq "requesterRegion" )
{
# print "yy$IDP ", $entry->id, "\n";
next;
}
## http://code.google.com/intl/en/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state
## Also one day could use
## my $string = $entry->denied_countries;
## my @matches = $string=~m/(TW|US)/g;
delete $missing[ $entry->position - 1 ];
my $v = sprintf "%03d|%s|%s|%s", $entry->position, $entry->video_id,
$IDP,
# $entry->title;
utf8::is_utf8( $entry->title )
? $entry->title
: encode( "utf8", $entry->title );
# dumpstr($entry->title);
if ( $entry->media_player ) {
# use Data::Dumper;
push @{ $vids{1}{ $playlist->playlist_id } }, $v;
# print STDERR Dumper("紅",$playlist->title), "紅", $playlist->title;
# die;
unless ( $playlist->title eq '英文歌詞 English lyrics' ) {
push @{ $checklist{ $entry->video_id } }, join "|",
utf8::is_utf8( $playlist->title )
? $playlist->title
: encode( "utf8", $playlist->title ),
# $playlist->title,
$v;
}
}
else {
push @{ $vids{0}{ $playlist->playlist_id } },
"# $v|" . $entry->appcontrol_state;
# print STDERR "xx$IDP\n";
}
}
}
for ( 0 .. $playlist->count_hint - 1 ) {
if ( exists $missing[$_] ) {
push @{ $vids{0}{ $playlist->playlist_id } },
sprintf "# %03d|Problem!", $_ + 1;
## try watching it in a browser when logged out to find out what was wrong
}
}
}
{
my ( $total, $list ) = ( 0, 'Duplicates' );
printf "\n%d playlists, %d videos.\n:::: $list:\n", scalar @$playlists,
scalar keys %checklist;
for ( keys %checklist ) {
if ( $#{ $checklist{$_} } ) {
for ( @{ $checklist{$_} } ) { print "$_\n"; $total++ }
}
}
print "Total $list: $total\n";
}
for my $playlist (@$playlists) {
push @{ $vids{0}{ $playlist->playlist_id } }, "Empty playlist!"
unless $vids{1}{ $playlist->playlist_id };
}
{
my @list = qw/Unavailable Available/;
for ( 0, 1 ) {
print "\n:::: $list[$_]:\n";
my $total = 0;
for my $playlist (@$playlists) {
next unless $vids{$_}{ $playlist->playlist_id };
## print '==== http://www.youtube.com/my_playlists?p=',
## print '==== http://www.youtube.com/playlist?action_edit=1&list=PL',
## print '==== http://www.youtube.com/playlist?list=PL',
print '==== http://www.youtube.com/playlist?list=',
$playlist->playlist_id, ' |', $playlist->title, "\n";
for ( sort @{ $vids{$_}{ $playlist->playlist_id } } ) {
# print decode_utf8( $_ ), "\n";
# Encode::_utf8_on($_);
# Encode::from_to($_, "utf8", "utf8");
# dumpstr($_);
print $_, "\n";
$total++;
}
}
print "Total $list[$_]: $total\n";
}
}
sub dumpstr {
my ($s) = @_;
# print utf8::is_utf8($s) ? "char" : "byte";
print ":";
for ( split //, $s ) {
printf " %#02x", ord($_);
}
print "\n";
}
------------------------------
Date: Sat, 3 Nov 2012 19:33:03 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: Clear the "Wide character in print" warning and leave the output unmangled
Message-Id: <slrnk9aor0.c6r.hjp-usenet2@hrunkner.hjp.at>
On 2012-11-03 12:08, Peter J. Holzer <hjp-usenet2@hjp.at> wrote:
> On 2012-11-02 05:23, jidanni@jidanni.org <jidanni@jidanni.org> wrote:
>> None of the advice on perlunifaq or elsewhere can both
>> * Clear the "Wide character in print" warning, and
>> * Leave the output non doubly encoded.
>>
>> #!/usr/bin/perl
>>
>> # How to test this program:
>> # $ export restriction=TW; PERLLIB=$HOME/perl5/lib/perl5 ./ytpl jidanni2 > /tmp/o
>> # $ cat /tmp/o
>> # That will show you any problems it has.
>
> Thanks for providing a complete script which demonstrates the problem.
> This makes finding the problem simpler. However:
>
> [...]
>> use WebService::GData::Constants qw(:all);
>> use WebService::GData::YouTube;
>> die 'Specify a user please.' unless my $user = shift;
>
> I'm not going to create a youtube account just to test this script.
> So I cannot test it.
I spoke too soon. It turns out that the script can retrieve other
people's playlists, so I can run it with "jidanni2" as a parameter and
don't need an account and playlist of my own.
> Unfortunately, you didn't report where the "Wide character in print"
> warning occurs, either, and it is not obvious to me from the source
> code. I am guessing that it happens in the last loop, because you tried
> to use decode_utf8 there.
Yes, the guess was correct.
> My guess is that you get some byte encoded data from the
> WebService::GData module. You should decode() this, and you should do
> this as early as possible so that the rest of your code doesn't have
> to care about the encoding. This is especially necessary if you
> combine strings from several sources which might use different
> encodings.
This guess was also correct. $entry->title returns what looks like an
UTF-8 encoded string. So what I guess should be "台灣軍機 Taiwan
Aircrafts found in Google Earth" (char: 0x53f0 0x7063 0x8ecd 0x6a5f 0x20
0x20 0x20 0x54 0x61 ...) is returned as (char: 0xe5 0x8f 0xb0 0xe7 0x81
0xa3 0xe8 0xbb 0x8d 0xe6 0xa9 0x9f 0x20 0x20 0x20 0x54 0x61 ...).
To make it even more confusing, the string is marked as a character
string (the UTF8 bit is on) instead of a byte string. This is definitely
a bug in WebService::GData.
And even worse, it isn't even reliably wrong: "Rob 'N' Raz Featuring
Leila K - Got To Get" has an U+200E character just before the -. This is
probably where the "wide character" warning came from. After I put in an
appropriate “decode("UTF-8" $entry->title)”, it dies now. So I would
have to wrap that in an eval {} block or possibly use some heuristics to
check whether decoding is necessary or not. This is where I stop
and let you take over.
So, to summarize:
1) Put in “binmode STDOUT, ":encoding(UTF8)";”
2) Put in “use utf8;”
3) decode() the return value of $entry->title (and possibly some other
calls) but be aware that this doesn't always work, so you need a
fall-back strategy.
4) Report the bug.
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
------------------------------
Date: Sat, 03 Nov 2012 18:53:42 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Trampoline sub
Message-Id: <87pq3ubjrd.fsf@sapphire.mobileactivedefense.com>
"C.DeRykus" <derykus@gmail.com> writes:
> On Friday, November 2, 2012 2:51:01 PM UTC-7, Tim McDaniel wrote:
>> I'm moving some subs from one module to another. I'm thinking of
>>
>> leaving old names in to give more time to change all the callers.
>>
>> I think the best way to have "trampoline" code is
>>
>> sub OldName { goto &NewModule::NewName; }
>>
>> and it's reasonably clear. Just out of curiosity, are there other
>>
>> ways?
[...]
>> I tried
>>
>> *old = *real;
>>
>> and it works. Does it have any bad effects, like creating $MAIN::old
>> or something?
>>
>
> One downside would be that all the glob slots of
> *old would be aliased to those of *real. Selective
> aliasing over a local scope seems preferable:
>
> no warnings 'redefine';
> local *old = \ℜ
If this is supposed to enable calling a subroutine by two different
names, it basically needs to be done in the top-level lexical
scope and can thus as well be done at file scope. And you usage of
'aliasing' is - at best - confusing (I'm tempted to call it 'outright
wrong'). The perl symbol table of some module is a hash named
%module_name:: and creating a 'module scoped' named objects implies
creating a glob, putting that into the symbol table hash indexed by
the name and assigning the object itself to one of the slots of this
glob, cf (the $n = 4 causes the SV slot to become populated and the
later *n = .... the CV slot):
,----
| [rw@sapphire]~ $perl -de 0
|
| Loading DB routines from perl5db.pl version 1.32
| Editor support available.
|
| Enter h or `h h' for help, or `man perldebug' for more help.
|
| main::(-e:1): 0
| DB<1> $n = 4
|
| DB<2> use Devel::Peek
|
| DB<3> Dump($::{n})
| SV = PVGV(0x70aa70) at 0xa28df8
| REFCNT = 1
| FLAGS = (MULTI,IN_PAD)
| NAME = "n"
| NAMELEN = 1
| GvSTASH = 0x605bb0 "main"
| GP = 0x70e360
| SV = 0xa28db0
| REFCNT = 1
| IO = 0x0
| FORM = 0x0
| AV = 0x0
| HV = 0x0
| CV = 0x0
| CVGEN = 0x0
| LINE = 2
| FILE = "(eval 5)[/usr/share/perl/5.10/perl5db.pl:638]"
| FLAGS = 0xa
| EGV = 0xa28df8 "n"
|
| DB<4> *n = sub { return 'n'; }
|
| DB<5> Dump($::{n})
| SV = PVGV(0x70aa70) at 0xa28df8
| REFCNT = 1
| FLAGS = (MULTI,ASSUMECV,IN_PAD)
| NAME = "n"
| NAMELEN = 1
| GvSTASH = 0x605bb0 "main"
| GP = 0x70e360
| SV = 0xa28db0
| REFCNT = 1
| IO = 0x0
| FORM = 0x0
| AV = 0x0
| HV = 0x0
| CV = 0xa290b0
| CVGEN = 0x0
| LINE = 2
| FILE = "(eval 5)[/usr/share/perl/5.10/perl5db.pl:638]"
| FLAGS = 0xe
| EGV = 0xa28df8 "n"
|
| DB<6>
`----
In contrast to this, a 'glob to glob' assignment puts the glob
referenced by the name on the RHS into the glob slot of the LHS name:
,----
| [rw@sapphire]~ $perl -de 0
|
| Loading DB routines from perl5db.pl version 1.32
| Editor support available.
|
| Enter h or `h h' for help, or `man perldebug' for more help.
|
| main::(-e:1): 0
| DB<1> use Devel::Peek
|
| DB<2> $n = 3;
|
| DB<3> $nn = 33
|
| DB<4> Dump($::{nn})
| SV = PVGV(0x70b400) at 0xa8dd58
| REFCNT = 1
| FLAGS = (MULTI,IN_PAD)
| NAME = "nn"
| NAMELEN = 2
| GvSTASH = 0x605bb0 "main"
| GP = 0xa28580
| SV = 0xa28bd0
| REFCNT = 1
| IO = 0x0
| FORM = 0x0
| AV = 0x0
| HV = 0x0
| CV = 0x0
| CVGEN = 0x0
| LINE = 2
| FILE = "(eval 8)[/usr/share/perl/5.10/perl5db.pl:638]"
| FLAGS = 0xa
| EGV = 0xa8dd58 "nn"
|
| DB<5> *nn = *n
|
| DB<6> Dump($::{nn})
| SV = PVGV(0x70b400) at 0xa8dd58
| REFCNT = 1
| FLAGS = (MULTI,IN_PAD)
| NAME = "nn"
| NAMELEN = 2
| GvSTASH = 0x605bb0 "main"
| GP = 0x70de70
| SV = 0xa026a0
| REFCNT = 2
| IO = 0x0
| FORM = 0x0
| AV = 0x0
| HV = 0x0
| CV = 0x0
| CVGEN = 0x0
| LINE = 2
| FILE = "(eval 7)[/usr/share/perl/5.10/perl5db.pl:638]"
| FLAGS = 0xa
| EGV = 0xa026b8 "n"
`----
------------------------------
Date: Sun, 4 Nov 2012 07:27:10 -0800 (PST)
From: "C.DeRykus" <derykus@gmail.com>
Subject: Re: Trampoline sub
Message-Id: <5ce42a9f-9d0c-4e48-91ba-b96d0287b152@googlegroups.com>
On Saturday, November 3, 2012 11:53:44 AM UTC-7, Rainer Weikusat wrote:
> "C.DeRykus" <derykus@gmail.com> writes:
>
> > On Friday, November 2, 2012 2:51:01 PM UTC-7, Tim McDaniel wrote:
>
> >> I'm moving some subs from one module to another. I'm thinking of
>
> >>
>
> >> leaving old names in to give more time to change all the callers.
>
> >>
>
> >> I think the best way to have "trampoline" code is
>
> >>
>
> >> sub OldName { goto &NewModule::NewName; }
>
> >>
>
> >> and it's reasonably clear. Just out of curiosity, are there other
>
> >>
>
> >> ways?
>
>
>
> [...]
>
>
>
> >> I tried
>
> >>
>
> >> *old = *real;
>
> >>
>
> >> and it works. Does it have any bad effects, like creating $MAIN::old
>
> >> or something?
>
> >>
>
> >
>
> > One downside would be that all the glob slots of
>
> > *old would be aliased to those of *real. Selective
>
> > aliasing over a local scope seems preferable:
>
> >
>
> > no warnings 'redefine';
>
> > local *old = \ℜ
>
>
>
> If this is supposed to enable calling a subroutine by two different
>
> names, it basically needs to be done in the top-level lexical
>
> scope and can thus as well be done at file scope.
Hm, I'm not following your point. I was just
bringing up that something like:
perl -MMymod=somesub -E
'sub somesub{ say "old"; };
somesub();
{ local *somesub=\&Mymod::somesub; somesub(); };
somesub()'
--> old
new
old
would limit the scope of the new sub to prevent it
from permanently hijacking the original. Even if
this scenario doesn't require it, the narrowest
scope is generally a good idea of course.
>
> 'aliasing' is - at best - confusing (I'm tempted to call it 'outright
>
> wrong').
> ...
A demo from perlmod actually uses the term 'aliasing'
as a cheap, fast way of referencing:
$bar = 1;
*foo = \$bar; # Make $foo an alias for $bar
{
local $bar = 2; # Restrict changes to block
print $foo; # Prints '1'!
}
... Because variables are accessed through the
typeglob, you can use "*foo = *bar" to create
an alias which can be localized...
--
Charles DeRykus
------------------------------
Date: Sun, 04 Nov 2012 16:58:13 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Trampoline sub
Message-Id: <878vahnw4a.fsf@sapphire.mobileactivedefense.com>
"C.DeRykus" <derykus@gmail.com> writes:
> On Saturday, November 3, 2012 11:53:44 AM UTC-7, Rainer Weikusat wrote:
>> > On Friday, November 2, 2012 2:51:01 PM UTC-7, Tim McDaniel wrote:
>> >> I'm moving some subs from one module to another. I'm thinking of
>> >> leaving old names in to give more time to change all the callers.
[...]
>> Selective aliasing over a local scope seems preferable:
[...]
>> If this is supposed to enable calling a subroutine by two different
>> names, it basically needs to be done in the top-level lexical
>> scope and can thus as well be done at file scope.
>
> Hm, I'm not following your point. I was just
> bringing up that something like:
>
> perl -MMymod=somesub -E
> 'sub somesub{ say "old"; };
> somesub();
> { local *somesub=\&Mymod::somesub; somesub(); };
> somesub()'
>
> --> old
> new
> old
>
> would limit the scope of the new sub to prevent it
> from permanently hijacking the original.
If, as quoted above, the general idea is to make a 'globally callable
and called' subroutine available via two names for some time, exactly
this 'permanent hijacking' aka 'make the subroutine available via
either name' is intended.
[...]
>> 'aliasing' is - at best - confusing (I'm tempted to call it 'outright
>> wrong').
>> ...
>
> A demo from perlmod actually uses the term 'aliasing'
> as a cheap, fast way of referencing:
>
> $bar = 1;
> *foo = \$bar; # Make $foo an alias for $bar
And the examples I gave apply equally well to that: And assignment of
the form
*name = reference
with 'name' being some identifier and reference being a refrence to
some Perl object cause the corresponding slot of the glob referred to
by name to point to the reference. A *glob = *some_other_glob
assignment causes glob and some_other_glob to share the subobject
Devel::Peek::Dump refers to a 'GP'. For as long as this happens to be
the case, $bar and $foo and @bar and @foo and &bar and &foo and will
result in the same object. But it doesn't really create a 'special
relationship' between the names bar and foo, cf
perl -e '$bar = 55; *foo = *bar; *bar = *baz; $bar = 66; print "$foo, $bar\n"'
or
perl -e '$bar = 66; *foo = *bar; undef(*bar); print "$foo, $bar\n"'
------------------------------
Date: Sun, 4 Nov 2012 18:59:08 +0000 (UTC)
From: tmcd@panix.com (Tim McDaniel)
Subject: Re: Trampoline sub
Message-Id: <k76dts$pu9$1@reader1.panix.com>
Rainer, thank you for the extra explanation.
Indeed, the requirement is that the trampoline/aliasing/name change is
globally visible, to help in changing code that used to call
OldModule::OldSub to NewModule::NewSub anywhere in the code base. So
"local" is not appropriate: if I were going to edit a source file to
add that, I might as well go all the way and do the substitutions in
that source file.
I think all the possibilities are
*OldModule::OldSub = \&NewModule::NewSub;
sub OldModule::OldSub { goto &NewModule::NewSub; }
sub OldModule::OldSub { &NewModule::NewSub; }
sub OldModule::OldSub { NewModule::NewSub(@_); }
On the whole, I think I'll go with Rainer's suggestion of
sub OldSub { &NewModule::NewSub; }
We do get occasional stack dumps that can be exposed to developers.
If I do either of
*OldSub = \&NewModule::NewSub;
or
sub OldSub { goto &NewModule::NewSub; }
then the stack dump would not match the source.
I can imagine someone seeing a stack dump that says that
SomePackage::SomeSub called NewModule::NewSub, looking in
SomePackage.pm for NewSub and not finding it, and getting thoroughly
confused. There are few enough calls to these subs that efficiency
isn't that much of a concern, and I should be able to grep the source
and replace all the existing OldModule::OldSub calls anyway.
--
Tim McDaniel, tmcd@panix.com
------------------------------
Date: Sun, 4 Nov 2012 19:05:58 +0000 (UTC)
From: tmcd@panix.com (Tim McDaniel)
Subject: Re: Trampoline sub
Message-Id: <k76eam$19g$1@reader1.panix.com>
In article <k76dts$pu9$1@reader1.panix.com>,
Tim McDaniel <tmcd@panix.com> wrote:
>I think all the possibilities are
> *OldModule::OldSub = \&NewModule::NewSub;
> sub OldModule::OldSub { goto &NewModule::NewSub; }
> sub OldModule::OldSub { &NewModule::NewSub; }
> sub OldModule::OldSub { NewModule::NewSub(@_); }
and of course
*OldModule::OldSub = *NewModule::NewSub;
--
Tim McDaniel, tmcd@panix.com
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 3809
***************************************