3

初心者として、私はここで入手可能な atlanta perl mongers のこの資料を使用して perl データ構造を探索しようとしていますPerl Data Structures

これは私が書いたサンプルコードです。これ01.plは と同じですが、追加の 2 つのプラグマ02.plが含まれています。01.pluse strict; use warnings;

#!/usr/bin/perl

my %name = (name=>"Linus", forename=>"Torvalds");
my @system = qw(Linux FreeBSD Solaris NetBSD);

sub passStructure{
  my ($arg1,$arg2)=@_;

  if (ref($arg1) eq "HASH"){
    &printHash($arg1);
  }
  elsif (ref($arg1) eq "ARRAY"){
    &printArray($arg1);
  }

  if (ref($arg2) eq "HASH"){
    &printHash($arg2);
  }
  elsif (ref($arg2) eq "ARRAY"){
    &printArray($arg2);
  }
}

sub printArray{
  my $aref = $_[0];

  print "@{$aref}\n";
  print "@{$aref}->[0]\n";
  print "$$aref[0]\n";          
  print "$aref->[0]\n";
}

sub printHash{
  my $href = $_[0];

  print "%{$href}\n";
  print "%{$href}->{'name'}\n";
  print "$$href{'name'}\n";
  print "$href->{'name'}\n";
}

&passStructure(\@system,\%name);

上記のドキュメントには、私が誤解した点がいくつかあります。

最初 のページ 44 は、これらの 2 つの構文構造について述べてい"$$href{'name'}"ます"$$aref[0]"。なんで ?私のコードでは正常に動作しているようです (以下を参照)。さらに、perl は@{$aref}->[0]非推奨として使用することについて不平を言っています。どちらが正しいですか?

2 ページ 45 では、使用する必要がある場合にwithout"use strict"および using を使用すると、暗黙のうちに作成されることが言及されています。したがって、私がそれをよく理解していれば、次のスクリプトは両方とも「存在します」と出力するはずです"$href{'SomeKey'}""$href->{'SomeKey'}"%href

    [pista@HP-PC temp]$ perl -ale 'my %ref=(SomeKey=>'SomeVal'); print $ref{'SomeKey'}; print "Exists\n" if exists $ref{'SomeKey'};'
    SomeVal
    Exists

    [pista@HP-PC temp]$ perl -ale '                              print $ref{'SomeKey'}; print "Exists\n" if exists $ref{'SomeKey'};'

しかし、2番目はなぜですか?

最初に言及した 2 つのスクリプトの出力:

[pista@HP-PC temp]$ perl 01.pl 
Using an array as a reference is deprecated at 01.pl line 32.
Linux FreeBSD Solaris NetBSD
Linux
Linux
Linux
%{HASH(0x1c33ec0)}
%{HASH(0x1c33ec0)}->{'name'}
Linus
Linus
[pista@HP-PC temp]$ perl 02.pl 
Using an array as a reference is deprecated at 02.pl line 32.
Linux FreeBSD Solaris NetBSD
Linux
Linux
Linux
%{HASH(0x774e60)}
%{HASH(0x774e60)}->{'name'}
Linus
Linus
4

4 に答える 4

5

多くの人$$aref[0]は、醜くて醜く$aref->[0]ないと思っています。他の人は同意しません。前の形で問題ありません。

@{$aref}->[0]一方、 はたまたま機能する間違いですが、推奨されておらず、機能しなくなる可能性があります。

http://perlmonks.org/?node=References+quick+referenceをお読みください。

パッケージ変数%hrefuse strict "vars"、たとえば->out of $href->{'SomeKey'}. これは、特定のキーが作成されるという意味ではありません。

更新: Perl のベスト プラクティス リファレンス (著者が意図したよりもはるかに奴隷的な採用と実際の考えが少ない本) を見ると、シジルを外す->可能性を回避するためにフォームを特に推奨しており、言及されている問題につながります。 p45.

于 2013-01-13T23:35:38.447 に答える
3

Perl には、通常のデータ型と、データ型への参照があります。意味と構文の両方の違いを認識することが重要です。

Type   |Normal Access | Reference Access | Debatable Reference Access
=======+==============+==================+===========================
Scalar | $scalar      | $$scalar_ref     |
Array  | $array[0]    | $arrayref->[0]   | $$arrayref[0]
Hash   | $hash{key}   | $hashref->{key}  | $$hashref{key}
Code   | code()       | $coderef->()     | &$coderef()

この構文を使用して hashrefs または arrayrefs にアクセスすることが悪いと見なされる理由$$foo[0]は、(1) ダブル シジルがスカラー ref アクセスのように紛らわしく見え、(2) この構文が参照が使用されているという事実を隠しているためです。逆参照矢印の->意図は明らかです。&シジルの使用が悪い理由については、この回答で説明しました。

@{$aref}->[0]配列への参照を逆参照し(定義上、参照自体にすることはできません)、その配列の最初の要素を矢印で逆参照しているため、これは非常に間違っています。正しい構文については、上の表を参照してください。

ハッシュを文字列に補間することはほとんど意味がありません。ハッシュの文字列化は、満たされた使用可能なバケットの数を示しているため、負荷について知ることができます。これはほとんどの場合役に立ちません。%また、文字列内でその文字を特別なものとして扱わないことで、printf…</p>

Perl のデータ構造に関するもう 1 つの興味深い点は、ハッシュまたは配列の新しいエントリがいつ作成されるかを知ることです。一般に、値にアクセスしても、その値を参照として使用している場合を除き、そのハッシュまたは配列にスロットは作成されません。

my %foo;
$foo{bar}; # access, nothing happens
say "created at access" if exists $foo{bar};
$foo{bar}[0]; # usage as arrayref
say "created at ref usage" if exists $foo{bar};

出力: created at ref usage.

undef実際には、場合によっては値を参照として使用できるため、配列参照は所定の位置にスピンします。次に、この arrayref がハッシュのスロットに入力されます。

グローバル変数は名前空間を表すハッシュの単なるエントリであるため、 がなければuse strict 'refs'、変数 (ただし、その変数のスロットではない) が適切な位置に配置されます。は と同じです と同じです。$foo{bar}$main::foo{bar}$main::{foo}{bar}

于 2013-01-13T23:58:19.297 に答える
1

$arg->[0]フォームに対するフォームの主な利点は、$$arg[0]何が起こっているかについて最初のタイプの方がはるかに明確であることです... $argARRAYREF であり、それが参照する配列の 0 番目の要素にアクセスしています。

最初の読み取りでは、2 番目の形式は${$arg}[0](ARRAYREF の逆参照) または${$arg[0]}(の最初の要素が何であれ逆参照) として解釈できます@arg

当然のことながら、正しい解釈は 1 つだけですが、コードを見ている日 (または夜) は誰にでもありますが、演算子やその他の構文デバイスがどの順序で機能するかをまったく思い出せません。参照解除の追加レベルでした。

防御的なプログラマーは、自分の意図を明確にしようとする傾向がありますが$arg->[0]、それはそのコードの意図をより明確に表現したものであると私は主張します。

ハッシュの自動作成に関しては...作成されるのはハッシュだけです(Perlインタープリターがキーが存在するかどうかを確認するため)。キー自体は作成されません (当然... チェックしているキーを作成したくないでしょう... しかし、バケットが存在しない場合は、そのキーを保持するバケットを作成する必要があるかもしれませんこのプロセスは autovivification と呼ばれ、詳細についてはこちらを参照してください

于 2013-01-13T23:48:21.673 に答える
0

@ {$aref}[0]または$aref->[0]として配列にアクセスする必要があると思います。

printステートメントはオブジェクトをインスタンス化しません。暗黙的な作成とは、変数を割り当てる前に変数を事前に定義する必要がないことを意味します。printを割り当てないため、変数は作成されません。

于 2013-01-13T23:04:35.377 に答える