Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re^3: How to return values from a hash?

by BrowserUk (Pope)
on Mar 30, 2013 at 02:32 UTC ( #1026224=note: print w/ replies, xml ) Need Help??


in reply to Re^2: How to return values from a hash?
in thread How to return values from a hash?

Does that make it more clear?

Nope. Just a big mess of unintelligible console output.

Returning a hashref from a subroutine is simple and straightforward:

%hash = ( subhash1 => { a=>1, b=>2 }, subhash2 => { c=>3, d=>4 } );; sub getSubhash { return $hash{ $_[0] } };; pp getSubhash( 'subhash1' );; { a => 1, b => 2 } pp getSubhash( 'subhash2' );; { c => 3, d => 4 }

Which means you must be doing something wrong.

So, how about you post:

  • The source code of the subroutine or method that is (meant) to be returning the reference.
  • The (actual) line of code that is calling it.

Then we'll be able to point out what you are doing wrong.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.


Comment on Re^3: How to return values from a hash?
Download Code
Re^4: How to return values from a hash?
by perl-diddler (Hermit) on Mar 30, 2013 at 03:40 UTC
    At the bottom of the call stack, is a 'Vars' routine to wrap fields in a hash. The relevant parts:
    sub _Var ($$$;$) { # Wrkhorse code for manu +fctrd Vars #note $p->obj, $vn=varname, $wa=wantarray val my ($__, $p, $vn, $wa)=@$_; $_=$__; '$_' my $v = $p->{$vn}; # value my $rfv = ref $v; # type(ref) of var ...... } elsif ($rfv == 'HASH') { my $subvar=$arg; ## 1 var w/hash is is a key $p->{$vn}{$subvar}=$_[0] if @_; ## another? =>assign va +lue return $p->{$vn}{$subvar}; <- returns has here.
    That is called in sub 'by_mp' that takes care of init stuff and handles accessing the field: _by_mp in this case:
    sub by_mp(;$) { my $map = shift; my $c = ref $map || $map; ...init... my $arg_lvh = $map->_by_mp($arg); if (ref $arg_lvh) { $arg_lvh->fs_mp($arg); return $arg_lvh; #<----seems to return from here } my $devno = (stat $arg)[0]; $arg_lvh = $map->by_devno($devno); return undef unless $arg_lvh; die P "by_mp: by_devno(%s) returned %s, of type \"%s\", not a ref\ +n", $devno, $arg_lvh, ref $arg_lvh unless ref $arg_lvh; $map->_by_mp($arg, $arg_lvh); $arg_lvh->fs_mp($arg); return $arg_lvh; }
    That is called in the level of code where I detect the problem:
    sub lvm_BaseDiff_Lvh_4_Base_opt_mp ($;$) { my $lvm = shift; my ($base_lvh, $lv_mp) = @_; my $diff_dev = pathcat("/dev", $base_lvh->vg_name, $base_lvh->lv_name . ".diff"); #TPe "diff_dev=%s", $diff_dev; # next is call to by_mp -- here is where I don't seem to be #getting a reference back. my $bdiff_lvh = $lvm->by_mp($lv_mp.".diff") if @_; $bdiff_lvh = $lvm->by_devpath($diff_dev) unless ref $bdiff_lvh; ## commented version below was orig -- trying above -- ## seems to work better, but seems a bit random... #my $bdiff_lvh = (@_ && $lvm->by_mp($lv_mp . ".diff") or # $lvm->by_devpath($diff_dev)); die P "Can't find \"diff\" dir for vol %s by mount or device path" +, $lv_mp unless ref $bdiff_lvh; $bdiff_lvh->fs_mp($lv_mp) unless $bdiff_lvh->fs_mp; $bdiff_lvh->fs_type_name($base_lvh->fs_type_name) unless $bdiff_lvh->fs_type_name;

      Unless I am getting very short-sighted, _Var() is never called by either by_mp() or lvm_BaseDiff_Lvh_4_Base_opt_mp(), so why are you attributing the error to the return from that subroutine?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Um...._Var is the generic that is called for all of the 'named' vars...

        I have a sub '_access_maker' that defines subs for each name in the field, those access routines all push on context and call Var.

        If you wish to see it, it's fairly old code and probably could be optimized a bit...but it works...

        sub varname ($) { substr $_[0], (1+rindex $_[0],':') } sub _access_maker { #{{xo{2 my $pkg = shift; #var in $_ { #TPe "(Dvam: %s::%s() )\xc2\x83",$pkg,$_; my $proc = '# line ' . __LINE__ . ' "' . __FILE__ . "\"\n" . ' { use warnings;use strict; package '.$pkg.'; sub '.$_.' (;$) { # create access routine for packa +ge::var $_=[$_,shift, Data::Vars::varname((caller 0)[3]), wantarray] +; goto &Data::Vars::_Var}; 1}'; eval $proc; $@ and die "Fatal error in $pkg\::Vars\::_access_maker?: $@\n"; } } ## end sub _access_maker }}}2

        So _access_maker is called at compile time to define 'sub's for each of the the 'field' vars. So the code during execution is not _access_maker, but the sub...#create access routine for package::var You can see why I didn't bother including it... It's just a push of context and then a goto _Var

        Sorry, that was a last minute change. In order to simplify the code for inclusion here, I left out a trivial optimization where I convert HASH to an integer:
        use constant Array => 1; use constant Hash => Array << 1; our %_typemap=(ARRAY=>Array, HASH=>Hash); sub _Var ($$$;$) { # Wrkhorse code for manu +fctrd Vars my ($__, $p, $vn, $wa)=@$_; $_=$__; # must not trash '$_' my $v = $p->{$vn}; # value my $rfv = ref $v; # type(ref) of var my $rfvi = $_typemap{$rfv} || 0; my ($arg, $addrof); if ($wa && $wa eq '&#945;') { $wa=undef, $addrof=1 } if (@_ && !$addrof) { # arg for "setter" $arg = shift; my $refarg = ref $arg; # ref of the arg unless ( defined($p->{$vn}) && defined $arg ){ # unless both de +fined $p->{$vn} = $arg; } elsif ($rfvi == Array) { ## if type(var)==ARRAY, +1 param if ($refarg ne "ARRAY" || (@$arg || @$v)) { push @{$p->{$vn}}, $_[0]; ## convert to "push" } } elsif ($rfvi == Hash) {
        I tried to cut down the amount of code included by cutting out the integer thing...sorry. I didn't want to get dinged for not trying to cut things down...
      I have some doubts about the following code:
      sub _Var ($$$;$) { # Wrkhorse code for manufctrd Vars #note $p->obj, $vn=varname, $wa=wantarray val my ($__, $p, $vn, $wa)=@$_;
      1. Why are you using prototypes in the subroutine definition? Unless you have a very very good reason to use prototypes, you should not use prototypes. And using prototypes to check the type and number of arguments is not a good reason.
      2. What do you think @$_ does? You are dereferencing the global default variable $_ into an array. Didn't you rather want to use the @_ variable which contains the parameters of the subroutine call?
      3. Are you using strict and warnings?

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      My blog: Imperial Deltronics
        I always use prototypes -- even on methods where they don't matter -- for no other reason than, minimally, documentation. It's a self-imposed discipline.

        By looking at that most perl programmers would know that it takes 3 mandatory vars, and an optional 4th; I don't ascribe to the 'no prototypes propaganda', but then I also know their limitations.

        2. answered above where someone asked how _var got called. I needed a way to pass params, from the 'goto' to this... $_ is the only way I know.

        3. always. (else prototypes are even more worthless).

        -----
        the Data::Var module defines fields with optional default definitions -- so if you access them through the access routines (which I don't on more speed sensitive areas), you will get a compile time error for trying to access a field that doesn't exist.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1026224]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (12)
As of 2014-09-18 11:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (113 votes), past polls