1

ばかげた質問で申し訳ありませんが、私は Perl プログラミングに夢中になっており、Perl プログラマーのように考えるのが本当に難しいと感じています。

今日のばかげた質問: id フィールドをキーとして使用して、パイプで区切られたファイルをハッシュにロードします。

#open file

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$id} = {
        "path" => $path,
        "date" => $date
    };
}

ただし、何らかの理由で(そして変更できないため)IDが一意ではないため、実際にキーをパスにする必要がある場合が数回あります。それをすべてサブルーチンに入れ、キーとして使用する変数の名前を渡します。

load_hash("path");

sub load_hash {
    my $key = shift;

    #do stuff, and then in while loop
    $hash{${$key}} = #and so on
}

しかし perldb では x ${$key} は常に undef ですが、 x ${path} は $path に値を出力します。

私がやろうとしていることをする方法はありますか?

ティア

4

2 に答える 2

10

「シンボリック参照」を使用しようとしています。問題があり、「シンボリック参照でこれを解決しよう」と思う場合は、2 つの問題があります。

まず、グローバルでのみ機能します。レキシカルとして宣言$pathしたため(宣言されたブロックでのみ表示されます)、load_path はそれを見ることができません。$pathいいえ、グローバルにしないでください。

次に、シンボリック参照はスパゲッティ コードを作成します。グローバルは十分に悪いです。いつでもどこでも、何からでもアクセスできます。グローバルへのシンボリック参照では、どのグローバルがアクセスされているかさえわかりません。これにより、何が何を変更するかを追跡することができなくなります。strictこれが、それらをオフにする理由です。オンにして、オフstrictにするタイミングがわかるまでオンのままにします。

何を達成しようとしているのか完全にはわかりませんが、これで問題ないようです。

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$path} = {
        "path" => $path,
        "date" => $date
    };
}

しかし、おそらく行の解析を関数に移し、ハッシュの割り当てをメイン ループに残します。行の解析はロジックの明確なチャンクであり、行をファイル ハッシュに割り当てることから完全に分離できます。良い兆候は、%hashグローバルである必要がないことです。

my %hash;
while (<MY_FILE>) {
    my $line = parse_line($_);

    my $id = $line->{path};
    $hash{$id} = $line;
}


my @fields = qw(id path date);
sub parse_line {
    my $line = shift;
    chomp $line;

    my %data;
    # This is assigning to a hash slice.  Look it up, its handy.
    @data{@fields} = split m{\|}, $line;

    return \%data;
}
于 2009-11-13T00:51:58.780 に答える
2

このようなもの?

use Carp 'confess';

sub load_hash {
    my $key = shift;

    # ...

    while (...) {
        # ...
        my %line;  # important that this is *inside* the loop
        @line{qw (id path date)} = split /\|/;
        confess "BUG: unknown key '$key'"  unless exists $line{$key};  # error checking
        $hash{$line{$key}} = \%line;
        delete $line{$key};  # assuming you don't want the key value duplicated
    }
}
于 2009-11-13T00:30:01.000 に答える