2016-11-06 3 views
3

perldsc 문서의 '일반적인 실수'섹션을 이해하려고합니다. 그가 말할 때 전달하고자하는 것은 무엇입니까?perl의 데이터 구조 이해

배열 배열과 같은 것을 구성하는 데있어서 두 가지 가장 일반적인 실수는 실수로 요소의 수를 계산하거나 다른 메모리 위치를 반복적으로 참조하는 것입니다 . 여기에 단지 중첩 된 배열 대신 수를 얻는 경우입니다 : 내가 이해에서

for my $i (1..10) { 
    my @array = somefunc($i); 
    $AoA[$i] = @array;  # WRONG! 
} 

그것이 반복 때이다 (1..10)의 첫 번째 값을 것입니다 1

my @array = somefunc(1); 

이 함수는 정의되어 있지 않으므로 로직을 생성 할 것입니다.

sub somefunc { 
my $a = shift; 
print $a * $a; 
} 

이렇게 본질적 것이다 :

1 * 1 

그 결과가 '1'입니다. 내 이해하는

내 @array은 다음과 같이 표시됩니다 (

$AoA[$i] = @array; 

을 나는 $ AOA [$ 1] 익명의 배열이 있으리라 믿고있어 :

@array = ('1'); 

그리고 다음 줄이 할 것 그/그녀는 '내'로 선언하지 않았습니다.) btw) @array는이 익명 배열의 첫 번째 요소가 될 것입니다. 그리고 각 반복마다 '2'를 반복합니다. 잘못이 코드 저자의 요점은 무엇

$AoA[$i] = @array 

: '4'하고 전달됩니다

somefunc(2); 

. 무엇이 잘못 되었는가를 이해하려고 노력하고 있지만 더 중요한 것은 코드를 이해하려고하는 것입니다. 어떤 도움을 주시면 감사하겠습니다.

UPDATE

가 나는 이것이 내가 인쇄 및 덤퍼를 사용할 때, 나는 시각적으로 저자가 전달하려고하는 것을 볼 수 있기 때문에 일반적인 실수 인 이유를 이해 생각, 여기에 수정 된 코드입니다. perldoc을의 perldsc의 일반적인 실수 단락에서

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 

for my $i (1..10) { 
      my @AoA; 
      my @array = somefunc($i); 
      print "The array is Dumper(@array)\n"; 
      $AoA[$i] = @array;  # WRONG! 
      print Dumper($AoA[$i]); 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

은, 그/그녀는 여기에

를 말한다 방금 대신 중첩 된 배열의 수를 얻는 경우이다 : 아래에있는

을 Dumper의 출력.

The array is Dumper(1) 
$VAR1 = 1; 
The array is Dumper(4) 
$VAR1 = 1; 
The array is Dumper(9) 
$VAR1 = 1; 
The array is Dumper(16) 
$VAR1 = 1; 
The array is Dumper(25) 
$VAR1 = 1; 
The array is Dumper(36) 
$VAR1 = 1; 
The array is Dumper(49) 
$VAR1 = 1; 
The array is Dumper(64) 
$VAR1 = 1; 
The array is Dumper(81) 
$VAR1 = 1; 
The array is Dumper(100) 
$VAR1 = 1; 

은 그래서 반복

$VAR1 = 1; 

이 수와하지 중첩 된 배열입니다 있으리라 믿고있어.

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 

for my $i (1..10) { 
      my @count; 
      my @array = somefunc($i); 
      print "The array is Dumper(@array)\n"; 
      $count[$i] = scalar @array;  
      print Dumper($count[$i]); 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

그러나 문서가 어떻게 중첩 된 배열을 얻는 말하지 않았다

저자는 카운트가 내가 진정으로 원하는 경우 다음과 같이 코드를 다시 작성하는 것을 나타냅니다 않았다?

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 
my @count; 
my @new_array; 

for my $i (1..10) { 
      #my @count; 
      my @array = somefunc($i); 
      push @new_array, [@array]; 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

print Dumper(\@new_array); 

다음과 같은 성명에서

$VAR1 = [ 
     [ 
     1 
     ], 
     [ 
     4 
     ], 
     [ 
     9 
     ], 
     [ 
     16 
     ], 
     [ 
     25 
     ], 
     [ 
     36 
     ], 
     [ 
     49 
     ], 
     [ 
     64 
     ], 
     [ 
     81 
     ], 
     [ 
     100 
     ] 
    ]; 
+2

'print $ a * $ a'가 아닌'return $ a * $ a'라고 생각합니까? '$ AoA [$ i]'는 (@AoA)라는 정규 배열의 $ i 번째 요소를 가리킨다. 할당'$ AoA [$ i] = @ array'는 스칼라 문맥 안에 있으므로'@ array'는 배열의 길이로 평가 될 것입니다 –

+1

Re "* @ array는이 무명 배열의 첫 번째 원소가됩니다 *", No 스칼라 문맥에서'@ array'는'@ array' 안에있는 원소의 수를 계산합니다. – ikegami

+1

이 예제는'@AoA'의 요소 안에'@ array'를 어떻게 배치 하는지를 보여주기 위해 노력하고 있습니다. 그래서'sub somefunc {my $ i = shift; return ($ i * 2, $ i * 3); }'이 더 좋은 예가 될 것입니다. – ikegami

답변

6

인쇄 :

내가 잘못하지만 중첩 된 배열을 얻을 수있는 코드를 재 작성하는 경우

UPDATE

나를 정정

$AoA[$i] = @array; 

@array스칼라 컨텍스트에서 참조되며 그 요소의 수를 산출합니다. 컨텍스트는 LHS에 의해 부과됩니다. $AoA[$i]@AoA 배열의 단일 요소입니다.

Perl에는 엄격한 의미로 배열 배열이 없습니다. 이것들은 근본적으로 "평평하게 된"배열이나 참조가있는 배열에 의해 에뮬레이트됩니다. 후자의 경우에서와 같이 테이크 참조 연산자를 사용해야합니다 :

$AoA[$i] = \@array; 

를 스타터를 들어, 당신이 찾을 수 있습니다, Data::Dumper는 arrayrefs 및 hashrefs 같은 복잡한 데이터 철골 구조를 검사에 매우 편리있다.

1

Perl은 다형성입니다. 즉, 다른 데이터 유형을 투명하게 처리하고, 대개 처리하는 방법에 대해 꽤 좋은 추측을합니다. 프로그래머의 작업이 다른 언어와 마찬가지로 강하게 입력되지 않기 때문에 훨씬 쉽습니다.

print $i + 1; 

을 당신은 5 볼 - 오른쪽 꽤 논리적 :

그래서 예를 들어 $ 나는 경우 4 번, 당신은이 작업을 수행 할 수 있습니까? 당신이 할 경우

과 :

print "I am " , $i , " years old"; 

당신은 "나는 4 살"볼 -이 경우 펄에 당신이 목록 컨텍스트에서 운영하고 있습니다 "라고, 그래서 내가 문자열로 $ 처리합니다 . 필요가 다른 많은 언어는 주장으로 숫자를 문자열로 변환 없습니다. 그래서

당신이

$AoA[$i] = @array; 

는이 상황에 따라 처리 방법을 할당 할 때. 스칼라 문맥에서, 그것은 $ AOA를 설정합니다 [ $ i] 배열의 길이가됩니다.리스트 문맥 대 스칼라에 대한 자세한 내용은

,이 대답 읽어

http://perl.plover.com/context.html

+0

좋은 점, 너무 많은 시간이 자바 스크립트에서 보냈습니다. "." 연산자를 사용하지만 명시 적으로 연결을 수행하고 있습니다. – Mikkel

+1

"목록 컨텍스트에서 작업 중이므로 $ i를 문자열로 처리합니다". List 문맥은 값이 숫자 또는 문자열로 취급되는지 여부에 대해서는 아무 것도 말하지 않습니다. 모든 인자를 문자열로 변환하는 것은'print()'입니다. 쉼표를 도트로 대체했다면,'$ i'는 스칼라 문맥에서 평가 될 것이지만 여전히 문자열로 변환 될 것입니다 (이번에는'print()'에 의해서가 아니라 연결 연산자에 의해). –

1

귀하의 예를 항상 서브 루틴으로 여기에 무슨 "1"을 반환 무슨 이해에 매우 유용되지 않습니다 - print()로 전화 한 결과. print()return()으로 바꾸면 다른 값 (1, 4, 9 등)을 얻게됩니다.

그러나 코드의 다음 줄 : @Aoa의 요소에

$AoA[$i] = @array; 

항상 할당합니다 1. 이는 배열 (@array)을 스칼라 변수 ($AoA[$i])에 할당하고 스칼라 컨텍스트에서 배열을 평가할 때 배열의 요소 수를 가져 오기 때문입니다.

$AoA[$i] = $array[0]; 

을하지만 정말 배열의 배열을 구축 아니에요 : @array는 오직 하나의 요소가 당신으로 지금

, 당신은이 작업을 수행 할 수 있습니다. 당신이 정말로하고 싶은 것은 배열에 대한 참조를 얻는 것입니다.

$AoA[$i] = \@array; 

서브 루틴이 둘 이상의 값을 반환하면 더 유용합니다.

sub somefunc { 
    # Used $x instead of $a as $a has a special meaning in Perl 
    my $x = shift; 
    return ($x * $x, $x * $x * $x); 
} 

for my $i (1..10) { 
    my @array = somefunc($i); 
    $AoA[$i] = \@array; 
} 

유용한 도구는 Data::Dumper입니다. 추가하십시오 :

use Data::Dumper; 
코드의 선두에

과 :

print Dumper @AoA; 

foreach 루프 후 다시 얻을 서로 다른 데이터 구조를 볼 수 있습니다.