Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

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

by perl-diddler (Chaplain)
on Mar 30, 2013 at 03:40 UTC ( #1026235=note: print w/replies, xml ) Need Help??

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

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;

Replies are listed 'Best First'.
Re^5: How to return values from a hash?
by CountZero (Bishop) on Mar 30, 2013 at 10:02 UTC
    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?


    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.

        Hello perl-diddler,

        By looking at that most perl programmers would know that it takes 3 mandatory vars, and an optional 4th;

        You could also use a runtime check. Compare the subroutines foo and bar:

        #! perl use strict; use warnings; sub foo { my @x = @_; die "Incorrect number of arguments$!" if @x < 3 || @x > 4; print "$_\n" for @x; print "\n"; } sub bar ($$$;$) { my @y = @_; print "$_\n" for @y; print "\n"; }

        Both approaches are self-documenting. The advantage of using prototypes is that violations are detected at compile time, which is more efficient. The disadvantage is that the calling syntax is much more restrictive. For example:

        my @args = (2, 3, 5, 7); foo(@args);

        works as expected, but


        results in a compilation error because the first $ prototype puts @args into scalar context, resulting in a single value of 4 (the number of elements in the array). To call bar successfully in this situation you would need something ugly like this:

        bar($args[0], $args[1], $args[2], $args[3]);

        Of course, prototypes can be useful; but when you write:

        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.

        this sounds (to me) like an attempt to convert Perl into a statically typed language. Much better to embrace Perl’s dynamic nature, use natural Perl idioms by default, and save prototypes for those (rare) situations in which they’re really useful.

        See Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen.

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re^5: How to return values from a hash?
by BrowserUk (Pope) on Mar 30, 2013 at 04:38 UTC

    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

Re^5: How to return values from a hash?
by poj (Monsignor) on Mar 30, 2013 at 08:35 UTC
      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...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1026235]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2018-07-18 22:08 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (397 votes). Check out past polls.