문제

변수와 연관 배열을 취하는 함수가 있지만 오른쪽으로 통과 할 수는 없습니다. 나는 이것이 기능 선언과 관련이 있다고 생각하지만 Perl에서 어떻게 작동하는지 알 수는 없습니다. 이것에 대한 좋은 참조가 있고 필요한 것을 어떻게 달성합니까?

참조로 전달해야한다고 덧붙여 야합니다.

sub PrintAA
{
    my $test = shift;
    my %aa   = shift;
    print $test . "\n";
    foreach (keys %aa)
    {
        print $_ . " : " . $aa{$_} . "\n";
        $aa{$_} = $aa{$_} . "+";
    }
}
도움이 되었습니까?

해결책

해시 자체 대신 참조를 전달하십시오. 에서와 같이

PrintAA("abc", \%fooHash);

sub PrintAA
{
  my $test = shift;
  my $aaRef = shift;

  print $test, "\n";
  foreach (keys %{$aaRef})
  {
    print $_, " : ", $aaRef->{$_}, "\n";
  }
}

perlfaq7 참조 : {function, filehandle, array, hash, method, regex}를 전달/반환하려면 어떻게해야합니까?

다른 팁

이 코드는 작동합니다.

#!/bin/perl -w

use strict;

sub PrintAA
{
    my($test, %aa) = @_;
    print $test . "\n";
    foreach (keys %aa)
    {
        print $_ . " : " . $aa{$_} . "\n";
    }
}

my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );

PrintAA("test", %hash);

핵심 요점은 함수의 내 () '명령문'에서 배열 컨텍스트를 사용하는 것입니다.


배열 컨텍스트 비즈니스는 실제로 무엇을합니까?

간결하게, 그것은 올바르게 작동합니다.

그것은 첫 번째 값을 의미합니다 @_ 인수 배열이 할당됩니다 $test, 및 나머지 항목은 해시에 할당됩니다. %aa. 내가 전화하는 방식이 주어지면 홀수 품목이 있습니다. @_, 일단 첫 번째 항목이 할당되면 $test, 할당 할 수있는 짝수의 품목이 있습니다. %aa, 각 쌍의 첫 번째 항목은 키 ( 'aaa', 'bbb', 'ccc')이고 두 번째는 해당 값입니다.

교체 할 수 있습니다 %aa ~와 함께 @aa,이 경우 배열에는 6 개의 항목이 있습니다. 교체하는 것도 가능합니다 %aa ~와 함께 $aa, 이 경우 변수입니다 $aa 'AAA'값과 나머지 값이 포함됩니다. @_ 과제에 의해 무시됩니다.

변수 목록 주변의 괄호를 생략하면 Perl은 코드를 컴파일하는 것을 거부합니다. 대체 답변 중 하나는 표기법을 보여주었습니다.

my $test = shift;
my(%aa) = @_;

이것은 내가 쓴 것과 거의 같습니다. 차이점은 두 사람 이후입니다 my 진술, @_ 이 변형에는 6 개의 요소 만 포함되지만 단일에는 my 버전에는 여전히 7 개의 요소가 포함되어 있습니다.

확실히 다른 질문이 있습니다 그래서 배열 컨텍스트에 대해.


사실, 나는 묻지 않았다 my($test, %aa) = @_; 나는 묻고 있었다 my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA ); ~ 대 my %hash = { 'aaa' => 1, ... };

차이점은 {...} 표기법이 해시 심판을 생성하고 (...) 표기법은 목록을 생성한다는 것입니다. 마찬가지로, [...]는 배열이 아닌 배열 심판을 생성합니다.

실제로, '메인'코드를 변경하여 읽습니다 : my (%hash) = {...}; 그리고 런타임 (컴파일 시간은 아님) 오류가 발생합니다 - 내 파일에 대체 코딩을 추가했기 때문에 라인 번호를주의해서 처리합니다.

Reference found where even-sized list expected at xx.pl line 18.
...
Use of uninitialized value in concatenation (.) or string at xx.pl line 13.

대안으로 :

sub PrintAA
{
    my $test       = shift;
    my %aa         = @_;
        print $test . "\n";
        foreach (keys %aa)
        {
                print $_ . " : " . $aa{$_} . "\n";
                $aa{$_} = $aa{$_} . "+";
        }
}

근본적으로 누락 된 것은 연관 배열이 단일 인수가 아니라는 것입니다 (Paul Tomblin의 답변에서와 같이 연관 배열 참조는).

해시를 참조 해야하는 것 같습니다.

sub PrintAA
{
   my $test = shift;
   my $aa = shift;
   if (ref($aa) != "HASH") { die "bad arg!" }
   ....
}

PrintAA($foo, \%bar);

당신이 할 수없는 이유

my %aa = shift;

Perl은 모든 인수를 서브 루틴에 한 목록으로 평평하게하기 때문입니다. @_. 모든 요소가 복사되므로 참조로 통과하면 해당 사본도 피할 수 있습니다.

평소와 같이 몇 가지 방법이 있습니다. 여기에 무엇이 있습니다 Perl 모범 사례, 스타일 포인터가 가장 존경받는 것은 매개 변수를 함수로 전달하는 것에 대해 말해야합니다.

3 개 이상의 매개 변수가있는 서브 루틴에 대한 이름의 인수 해시를 사용하십시오.

그러나 당신은 두 개만 가지고 있기 때문에, 당신은 도망 갈 수 있습니다;) 이것들을 직접 전달하면서 :

my $scalar = 5;
my %hash = (a => 1, b => 2, c => 3);

func($scalar, %hash)

기능은 다음과 같이 정의됩니다.

sub func {
    my $scalar_var = shift;
    my %hash_var = @_;

    ... Do something ...
}

코드를 표시 할 수 있다면 더 유용 할 수 있습니다.

위의 모든 방법은 작동하지만 이것은 항상 다음과 같은 일을 선호하는 방식이었습니다.

sub PrintAA ($\%)
{
    my $test       = shift;
    my %aa         = ${shift()};
    print "$test\n";
    foreach (keys %aa)
    {
        print "$_ : $aa{$_}\n";
        $aa{$_} = "$aa{$_}+";
    }
}

참고 : 코드도 약간 변경했습니다. Perl의 이중 인용 문자열이 해석됩니다 "$test" 가치가되기 위해 $test 실제 문자열보다는 '$test', 그래서 당신은 그렇게 많이 필요하지 않습니다 .에스.

또한 프로토 타입의 작동 방식에 대해 잘못되었습니다. 해시를 통과하려면 다음을 사용하십시오.

PrintAA("test", %hash);

해시 참조를 인쇄하려면 다음을 사용하십시오.

PrintAA("test", %$ref_to_hash);

물론, 이제 당신은 $ref_to_hash 사본을 보내고 있지만 원시를 수정할 수 있습니다. %hash 참조로 전달하기 때문입니다.

함수에 대한 인수는 단일 배열 (@_)으로 평평 해집니다. 따라서 일반적으로 참조로 작동하도록 해시를 전달하는 것이 가장 쉽습니다.

해시를 만들려면 :

my %myhash = ( key1 => "val1", key2 => "val2" );

해시에 대한 참조를 만들려면 :

my $href = \%myhash

참조로 해시에 액세스하기 위해;

%$href

그래서 당신의 서브에서 :

my $myhref = shift;

keys %$myhref;

지금까지 여기에서 다른 모든 대답은 나에게 다소 복잡해 보입니다. Perl 함수를 작성하면 일반적으로 기능의 첫 번째 줄에서 전달 된 모든 인수를 "확장"합니다.

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

이것은 기능을 선언하는 다른 언어와 유사합니다.

... someFunction ( arg1, arg2, arg3 )

그리고 그렇게하면 해시를 마지막 논쟁으로 통과하면 트릭이나 특별한 마술 없이는 괜찮을 것입니다. 예 :

sub testFunc {
    my ( $string, %hash ) = @_;
    print "$string $hash{'abc'} $hash{'efg'} $string\n";
}

my %testHash = (
    'abc' => "Hello",
    'efg' => "World"
);
testFunc('!!!', %testHash);

출력은 예상대로 다음과 같습니다.

!!! Hello World !!!

Perl 인수 에서이 작품은 항상 스칼라 값 배열로 전달되며 해시를 통과하면 주요 값/쌍이 해당 배열에 추가됩니다. 위의 샘플에서 인수는 기능으로 배열로 전달되었습니다 (@_) 실제로 :

'!!!', 'abc', 'Hello', 'efg', 'World'

그리고 '!!!' 간단합니다 %string, 동안 %hash 다른 모든 인수를 "제비"하는데, 항상 하나는 키로, 다음 요소를 값으로 해석합니다 (모든 요소가 소비 될 때까지).

당신은 그런 식으로 여러 해시를 통과 할 수 없으며 해시는 첫 번째 인수가 될 수 없습니다. 그렇지 않으면 모든 것을 삼키고 다른 모든 논쟁을 할당되지 않은 것으로 남겨두기 때문입니다.

물론 마지막 인수와 배열에 대한 정확히 동일한 작품입니다. 여기서 유일한 차이점은 어레이가 키와 값을 구별하지 않는다는 것입니다. 왜냐하면 남은 모든 인수는 값이며 배열로 밀려 나기 때문입니다.

폴링 서브를 사용하여 해시 또는 해시 프르프를 얻으십시오.

sub get_args { ref( $_[0] ) ? shift() : ( @_ % 2 ) ? {} : {@_}; }
sub PrintAA
{
  my $test = shift;
  my $aa = get_args(@_);;
  #then
  $aa->{somearg} #do something
  $aa->{anotherearg} #do something

}

다음과 같이 기능을 호출하십시오.

printAA($firstarg,somearg=>1, anotherarg=>2)

또는 이렇게 (상관없이) :

printAA($firstarg,{somearg=>1, anotherarg=>2})

또는 심지어 이것도 (상관없이) :

my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA );

PrintAA("test", %hash);

건배!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top