develooper Front page | perl.perl5.porters | Postings from May 2012

[perl #112896] eval "" in package DB does not see caller's @_

Thread Previous
From:
Father Chrysostomos via RT
Date:
May 12, 2012 06:03
Subject:
[perl #112896] eval "" in package DB does not see caller's @_
Message ID:
rt-3.6.HEAD-4610-1336827806-1645.112896-15-0@perl.org
On Fri May 11 23:04:40 2012, jimav wrote:
> As it says in 'man perlfunc', eval "..." executed in package DB
> is supposed to execute in the lexical scope of the first non-DB
>    caller.
> 
> This isn't working with @_.  That is,  eval "@_"  in package DB
> returns the local (in package DB) args, not @_ as seen by the caller.
> 
> Is this a bug or a feature?   If the latter, it is an undocumented
> restriction...

@_ is not lexical.  The *_{ARRAY} slot is localised when you enter a
subroutine.  So, no, I do not think this is a bug.

> 
> I wanted to write a wrapper for Data::Dumper which lets you say
> 
>   sub foo {
>     $struct = {hairy => ['mess']};
>     print svis('Hello world, struct=$struct\nMy args are @_\n');
>   }
> 
> and have it interpolate in the stringified representation of $struct
>    and
> @_ whatever they are (also interpolating \n etc, since the string is
> q()).  This worked quite nicely on everything except for @_.
> 
> If this is an easy fix, can it be made to work?

It’s a bit fiddly, but you could use caller($num) in list context to
populate @DB::args, and then do local *_ = \@DB::args before the eval.

> #!/usr/bin/perl
> use strict; use warnings;
> 
> package DB;
> use Data::Dumper;
> sub Test {
>    my ($expr) = @_;

Right here, insert:

   () = caller 1;
   local *_ = \@DB::args;

which works for me.

>    my @values = eval "$expr";
>    die "EVAL FAILED: $@" if $@;
>    print "DB EVAL: $expr is ",Data::Dumper->new([\@values])->Terse(1)-
>    >Dump;
> }
> 
> package main;
> my @LexAry = (1,2,3);
> our @GlobalAry = ('a'..'c');
> @ARGV = ('fake', 'arguments');
> 
> sub foo  {
>    DB::Test('1234');        # works
>    DB::Test('@LexAry');     # works
>    DB::Test('@GlobalAry');  # works
>    DB::Test('@ARGV');       # works
>    DB::Test('@_',"extra");  # FAILS
> }
> &foo(5,6,7);

-- 

Father Chrysostomos


---
via perlbug:  queue: perl5 status: new
https://rt.perl.org:443/rt3/Ticket/Display.html?id=112896

Thread Previous


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