[英]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.