in reply to How to return values from a hash?

What you are describing is rather cryptic and doesn't make much sense w/o showing code.

Cause

return $p->{hashname}{'path'};

is perfect to return a hashref.

update

if it's returning a list¹ , put curlies around the call, to create a new ano hash.

 $hash_ref = { $obj->meth() } ;

And if it's supposed to return a list but you call it in scalar context, you are only getting the last element from that list.

Cheers Rolf

( addicted to the Perl Programming Language)

¹) a "dereferenced hash" is not an entity Perl can return, only the list of elements.

Replies are listed 'Best First'.
Re^2: How to return values from a hash?
by perl-diddler (Chaplain) on Mar 30, 2013 at 02:19 UTC
    This is what 'db' is showing:
    > perl -d snapper.pl -X x /home Loading DB routines from perl5db.pl version 1.37 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(snapper.pl:5): our $VERSION = '0.0.2'; DB<1> b Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp DB<2> c Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp(snapper.pl:832): 832: my $lvm = shift; DB<2> s Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp(snapper.pl:833): 833: my ($base_lvh, $lv_mp) = @_; DB<2> s Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp(snapper.pl:834): 834: my $diff_dev = pathcat("/dev", 835: + $base_lvh->vg_name, $base_lvh->lv_name . ".diff"); DB<2> n Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp(snapper.pl:837): ------------ #### here is where I have the problem the return from the 'by_mp' -- +you'll see $lv_mp."diff" a bit below.... 837: my $bdiff_lvh = (@_ && $lvm->by_mp($lv_mp . ". +diff")) or 838: $lvm->by_devpath( 839: pathcat("/dev", $base_lvh->vg_name, $b +ase_lvh->lv_name . ".diff")); DB<2> s Lvm::Maps::by_mp(/home/law/bin/lib/Lvm_Utils.pm:793): 793: sub by_mp(;$) { my $map = shift; my $c = ref $map || $ +map; DB<2> s Lvm::Maps::by_mp(/home/law/bin/lib/Lvm_Utils.pm:793): 793: sub by_mp(;$) { my $map = shift; my $c = ref $map || $ +map; DB<2> s Lvm::Maps::by_mp(/home/law/bin/lib/Lvm_Utils.pm:794): 794: bless $map = $map->new(), $c unless ref $map; DB<2> s Lvm::Maps::by_mp(/home/law/bin/lib/Lvm_Utils.pm:795): 795: my $arg = $_[0]; DB<2> s Lvm::Maps::by_mp(/home/law/bin/lib/Lvm_Utils.pm:796): 796: $map->_init_by_mp unless $map->{_by_mp}; DB<2> p $arg /home.diff ----- ^^Above^^ is the string I passed in... so then I 'r'eturn from the rou +tine and see: DB<3> r scalar context return from Lvm::Maps::by_mp: '_chunksize' => undef '_d_type' => undef '_fs_perms' => undef '_fs_type' => Fs::Xfs=HASH(0x2198c08) 'mount_ops' => 'nodiratime,noatime,swalloc' 'name' => 'xfs' 'snapshot_ops' => 'nouuid,norecovery,ro' '_fs_type_name' => 'xfs' 'cfg' => undef 'fs_mp' => undef 'lv_attr' => '-wc-ao---' 'lv_kernel_major' => 254 'lv_kernel_minor' => 9 'lv_name' => 'Home.diff' 'lv_path' => '/dev/HnS/Home.diff' 'lv_size' => 549755813888 'origin' => '' 'vg_extent_size' => 4194304 'vg_name' => 'HnS' Lvm::Snapshot_Ops::lvm_BaseDiff_Lvh_4_Base_opt_mp(snapper.pl:840): 840: die P "Can't find \"diff\" dir for vol %s by m +ount or device path", $lv_mp 841: unless ref $bdiff_lvh;

    Now you are right, I could just throw curlies around that and create a NEW HASH from my **reference**, but gosh darnit... I'd rather it NOT dereference it in the the first place! Isn't the fact that it "expands it", then is stuck in a new anonymous hash, even meaning that not only has it done extra work, but the new hash isn't even the same hash (in memory) as they old (i.e. if I changed something in the hash, it would change the anon-copy, as I didn't get back the pointer I wanted to the original hash.

    Does that make it more clear?

    If you can tell by the line numbers, -- that's 1 of 2 main program files, with scads of little support libs thrown in for fun. So I'm just not sure how to prevent it from "returning the expansion of the HASH pointed to by the reference...(without, as you say, creating a new anon-hash -- which isn't really returning my reference that I want, at all!)

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