2013-06-24 34 views
2

背景:我是Perl的新手,我正在修改一個簡單的腳本,它循環訪問一個匿名數組的散列值。我不能循環訪問數組。我得到的是ARRAY(0x1663b78)循環訪問Perl內部的匿名數組

守則

#!/usr/bin/perl 
package Foo; 
use strict "vars"; 

sub new { 
    my $class = shift; 
    my $self = { 
     distro => "", 
     pkg_mgr => "", 
     options => ["PHP + Apache", "PHP + Lighthttpd", "PHP + Nginx", "RubyGems + Rails", "Node JS + NPM"] 
    }; 

    bless $self, $class; 

    return $self; 
} 

sub print_options { 
    my($self) = @_; 
    foreach($self->{options}) { 
     print $_ . "\n"; 
    } 
} 

my $setup = new Foo(); 
$setup->print_options(); 

另外,如果有人能好心告訴我,如果它是有用的遠程使用use strict "vars";,如果我真的沒有需要私人或公共變量。我知道我將如何在PHP中執行此操作,但是我無法用Perl將其包裹在頭。

最後,我使用Perl的原因是因爲最終我要製作一個安裝服務器軟件(包括PHP)的應用程序。該腳本將需要用戶通過命令行進行交互。

+2

你應該做'嚴格使用'; - 沒有理由使用'嚴格的'變數';''這隻會導致一些狹窄。 – friedo

+0

@弗裏多,感謝您的提示!爲清晰起見和文檔參考,請參閱 – djthoms

回答

8

一些小的Perl線索:

  • 使用Data::Dumper,只要你有這樣的問題。 Data::Dumper將幫助您瞭解結構。
  • 如果你打算全部採用面向對象的方式,那麼就要全力以赴。你有構造函數和方法。方法應該返回值,並且您對這些值進行操作。每個方法和構造函數都應儘可能獨立,並且對整體對象結構知之甚少。
  • main包中操作。你應該翻轉你的節目。最後兩條語句應該在最上面,並在下面定義你的軟件包。

如果您使用Data::Dumper和傾倒的$self數據時,你叫吧,你會意識到$self是三把鑰匙的哈希值,並且該options鍵指向一個匿名數組。

爲了做到你想要什麼,你必須解引用匿名數組:

sub print_options { 
    my($self) = @_; 
    for (@{$self->{options} }) { 
     print $_ . "\n"; 
    } 
} 

然而,讓我們清理你的程序,使它一個完整的類。首先,方法從不打印 - 它們返回值。因此,你不應該有一個print_options方法。相反,它應該返回數組(或對數組的引用)。

此外,您的構造函數不必知道您的Options是如何構造的。如果你改變它呢?讓我們來看看一個改變的程序:

#! /usr/bin/env perl 
# 
use warnings; 
use strict; 
use feature qw(say); 

my $setup = Foo->new; 
for my $option ($setup->Option) { 
    say $option; 
} 

package Foo; 

sub new { 
    my $class = shift; 
    my $self = {}; 
    bless $self, $class; 
    $self->Option("PHP + Apache"); 
    $self->Option("PHP + Lighthttpd"); 
    $self->Option("PHP + Nginx"); 
    $self->Option("RubyGems + Rails"); 
    $self->Option("Node JS + NPM"); 
    return $self; 
} 

sub Distro { 
    my $self = shift; 
    my $distro = shift; 
    if (defined $distro) { 
     $self->{DISTRO} = $distro; 
    } 
    return $self->{DISTRO}; 
} 

sub Package_Manager { 
    my $self = shift; 
    my $package = shift; 
    if (defined $package) { 
     $self->{PACKAGE} = $package; 
    } 
    return $self->{PACKAGE}; 
} 

sub Option { 
    my $self = shift; 
    my $option = shift;; 

    if (not exists $self->{OPTION}) { 
     $self->{OPTION} = []; 
    } 

    if (defined $option) { 
     push @{ $self->{OPTION} }, $option; 
    } 
    my @array = @{ $self->{OPTION} }; 
    return wantarray ? @array : \@array; 
} 

首先,與PHP,Perl的編譯執行之前的代碼。因此,您可以在程序的底部定義程序包及其子程序。以上代碼的幾行代碼在默認的主要的包中運行。如果我在我的Foo包中使用了包變量,我不會意外地在我的程序中使用它。

請注意,我的方法或構造函數都不知道Foo對象的結構。當我在我的new構造函數中設置我的選項時,我打電話給我的Option方法進行設置。這樣,如果我改變存儲我的選項的方式,我只需更改我的Option方法,而不必擔心必須更改包中的其他位置。它還簡化了我的程序並使其更易於支持。

通過使我的Option方法設置或獲取我的選項,我簡化了代碼。我可以看到,我將選項存儲在一個匿名數組中,很明顯,我需要取消引用它返回對象時。我喜歡使用wantarray並給用戶選擇他們是否需要數組或對數組的引用。

請注意,我不會簡單地返回$self->{OPTION}。它是對數組的引用,應該可以工作,但如果我返回該數組,則返回該對象的內存位置!因此,如果用戶更改該參考,他們正在更改我的對象而不通過我的方法。因此,我創建了另一個數組,並返回一個引用。 Muck用這個數組引用所有你想要的,你不會改變我的對象。

此代碼不完整。我可以設置選項,但不能取消選項。這可能是很好的方法來推動pop選項。相反,你現在所能做的就是返回整個列表,而不是修改它。

+0

+1。還有兩個問題:爲什麼要尊重數組?這是做什麼的?另外,Perl OOP比我以前使用PHP更抽象一些,所以你的意思是「完全無聊」?在PHP中,我將遵循以下過程:[http://pastebin.com/iZ1gUfAm](http://pastebin.com/iZ1gUfAm) – djthoms

+0

@djthoms引用只是對象的內存位置。例如,我的'$ self - > {OPTION}'僅僅指向我存儲陣列的內存位置。因此'ARRAY(0x1663b78)'表示你正在存儲位置爲'0x1663b78'的數組。你想要的不是內存位置,而是內存位置的數組。 _reference_接受一個數組並給你一個內存位置。一個** de **引用需要內存位置並返回數組。 –

+0

@djthoms我在我的回答中添加了如何將'Foo'包寫入_full bore_包。我的方法返回值並不打印它們。這是我的計劃要做的。我班的各個部分對我班的整個結構的瞭解有限。我的構造函數不知道如何存儲選項。我的選項方法不知道如何存儲Distro。保持每一個單獨的目的和單一的目的,使寫作課程更清潔,更容易維護。 –

0

您需要執行以下更改。

foreach(@{$self->{options}}) { 
     ^^    ^

options的關鍵是一個arrayref,你需要去引用它來使用它。

至於您的其他問題,建議更一般的一對編譯指示的,尤其是對於初學者

use strict; 
use warnings; 
3

$self->{options}不是一個數組而是參考到陣列。你需要去引用它才能夠遍歷它的值。

my @options = @{ $self=>{options} };