簡體   English   中英

如何將哈希的一部分傳遞給子例程?

[英]How do I pass part of a hash to a subroutine?

如何將哈希的一部分傳遞給子例程?

%list = ( 1 => {name => 'first', quantity => 2},
  2 => {name => 'second', quantity => 3});
$i = 2;

#doesn't work....
check_something ( \%{list}{$i} );
sub check_something {
   %local = @_;
}

#doesn't work....
check_something ( \%list, $i );
sub check_something {
   my ($ref, $item) = @_
   %local = %{$ref}{$item};
}

$list{$i}傳遞給子例程,

use strict;

check_something ( $list{$i} );

sub check_something {
   my ($href) = @_;

   # $href->{name}, $href->{quantity}

   my %hash = %$href;
   # $hash{name}, $hash{quantity}
}

這有效:

use strict;
use warnings;


my %list = ( 
    1 => {name => 'first', quantity => 2},
    2 => {name => 'second', quantity => 3}
);
my $i = 2;

check_something ( $list{$i} );

sub check_something {
   my $item = shift;
   #...
}

每當將比標量數據更多的東西存儲到Perl變量中時,就應該開始考慮面向對象的Perl。

看一下Perl面向對象的教程

我將在這里使用所有面向對象的方法:

#! /usr/bin/env perl

use strict;
use warnings;

my %list;

my $list{1} = Widget->new("first", 2);
my $list{2} = Widget->new("second", 3);
my $i = "2";
check_something( $list{$i} );

哇! 很明顯我在做什么。 我有一個名為%list的哈希,其中包含小部件的對象! 我的check_somthing子例程正在使用Widget對象。 它應該以$list{$i}作為參數。

但是小部件是什么樣的:

package Widget;
sub new {
    my $class    = shift;
    my $self     = shift;
    my $name     = shift;
    my $quantity = shift;

    my $self = {};
    bless $self, $class;
    $self->Name($name) if defined $name;
    $self->Quantity($quantity) if defined $quantity;
    return $self;
}

sub name {
    my $self = shift;
    my $name = shift;

    if ( defined $name ) {
       $self->{name} = $name;
    }
    return $self->{name};
}

sub Quantity {
    my $self    = shift;
    my $quanity = shift;

    if ( defined $quanity ) {
       $self->{quantity} = $quantity;
    }
    return $self->{quantity};
}

那很簡單。 通過使用對象而不是哈希,我簡化了邏輯。 很容易看出,我想傳遞給子例程的是Widget對象。 實際上, check_somthing子例程可以是另一種方法:

sub check_something {
    my $widget = shift;

    my $name = $widget->Name;
    my $quanity = $widget->Quantity;

    # Here be dragons...

    return ???
}

現在,我的代碼如下所示:

#! /usr/bin/env perl

use strict;
use warnings;

my %list;

my $list{1} = Widget->new("first", 2);
my $list{2} = Widget->new("second", 3);
my $i = "2";

$list{$i}->check_something;

請注意,這可以做很多事情來改善您的代碼:

  • 首先,它清理了您的邏輯。 您沒有傳遞列表的哈希值或哈希值,也沒有傳遞一些可能很難理解的結構,這些結構可能在您放棄並在此處提出問題之前浪費了兩到三個小時試圖弄清楚。 (沒有犯罪。我去過那里,自己做過)。 相反,您傳遞的是一個易於理解的對象
  • 其次,確保您的check_something子例程只能由Widget使用。 如果嘗試將非Widget對象傳遞給check_something ,它將失敗。 甚至更好的是,我可以擁有另一個名為Wooble對象,該對象帶有自己的check_something子例程,Perl會弄清楚我真正在檢查什么。

例如:

my $widget = Widget->new("first", 2);
my $wooble = Wooble->new(1, "slam");

$widget->check_something;
$wooble->check_something;

小部件和Woobles有自己的check_something方法和Perl,因為它知道哪個對象是Widget ,哪個對象是Wooble知道我應該運行哪個check_something

  • 最后, use strict; 不再破碎。 use strict; 編譯指示捕獲了90%的錯誤。 但是,當您通過從原始代碼中剔除它們來創建這些復雜的結構時,最終可能會同時產生use strict;的錯誤use strict; 會抓到但不能:

例如:

%list = (
    1 => {name => 'first', quantity => 2},
    2 => {name => 'second', quanity => 3}
);

看到錯誤了嗎? 我使用quantity在一,但隨后拼錯quanity在其他。 編譯器不會捕獲此類錯誤。 然而:

$list{1} = Widget->new;
$list{1}->name('first');
$list{1}->quantity(2);

$list{2} = Widget->new;
$list{2}->name('second');
$list{2}->quanity(3);    #Compiler Error!

現在,因為Perl編譯器會趕上我的錯誤quanity不僅是一個散列引用的關鍵,但一個不存在的子程序。

其他人已經為您提供了技術上正確的答案,但是,如果您經常使用復雜的數據結構(例如哈希值的哈希值或列表的哈希值或哈希值列表),就該開始使用對象了。 一旦使用了它們,您會發現可以更快地編寫代碼,而減少挫敗感和邏輯問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM