Skip to content

Instantly share code, notes, and snippets.

@aero
Created December 31, 2011 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aero/1542213 to your computer and use it in GitHub Desktop.
Save aero/1542213 to your computer and use it in GitHub Desktop.
Perl reference dereference
www.perlmania.or.kr에서 본인이 답변한 내용정리


차례대로 정리를 해보면 perl에서 reference를 dereference 할때는 [sigil]{}연산자를
사용합니다. 여기서 sigil은 결과로 어떤 데이터 타입을 가질것인가를 결정하는거죠.

@array = ( "one", "two", "three", "four", [10, 20, 30, 40, 50] );
$arrayref = \@array;
인 상태에서 $arrayref 안의 one을 가져오려면 해당값은 scalar이므로 sigil은 $가 되고
${$arrayref}[0] 이 됩니다.( @array의 첫번째 요소를 나타낼때 $array[0] 이렇게 하는걸 상기 )

여기서 [sigil]{} 에서 {}는 생략가능합니다. 그래서
$$arrayref[0] 가 되고
그리고 [sigil]{}은 ->로 대체가능합니다. 따라서
$arrayref->[0] 이 됩니다.

이제 더 복잡한 익명배열,혹은 레퍼런스를 포함한 자료구조로 가서 위에서
@array안의 익명배열 [10,20,30,40,50]에서 10 을 가져오려면 어떻게 해야 할까요?
일단 @array안의 5번째 요소(여기서는 익명배열레퍼런스)를 가져와야 합니다.
레퍼런스 자체는 scalar이므로 sigil로는 $을 사용해야 하겠죠? 따라서
${$arrayref}[4] 가 익명배열의 레퍼런스가 될겁니다. 이제 이것을 또 dereference해야하고
dereference후 최종적으로 가져올 10이 scalar이니깐 sigil은 $가 사용됩니다.

따라서 ${${$arrayref}[4]}[0]; 이렇게 하면 10을 가져옵니다. 이것을 처음에 말씀드린 규칙을 통해
여러형태로 변경해보면 다음것들이 모두 다 동일한 결과를 가져옵니다.

$$arrayref[4]->[0]
$$arrayref[4][0]

${$$arrayref[4]}[0]
${$arrayref->[4]}[0]
$arrayref->[4]->[0] 여기서 [],{}들사이의 ->는 편의상 생략이 가능합니다. 따라서
$arrayref->[4][0]

이렇게 여러 형태로 사용가능하지만 마지막 형태를 제일 많이쓰죠 제일 깔끔하기도 하고.

여기서 {}를 생략한 형태인 $$$arrayref[4][0] 혹은 $$arrayref->[4][0] 은 왜 안되느냐?
하는 의문이 있을 수 있습니다.

그 이유는 []가 연산자 우선순위가 가장 낮기 때문에 derefernce 대상인 $$arrayref[4] 와
$arrayref->[4] 를 dereference 하지못하고 앞의 sigil들끼리 먼저 결합해버리기 때문입니다.
앞에서 예를든 ${$arrayref}[0] 가 $$arrayref[0] 가 될 수 있는건 [0]이 제일 마지막에
해석되는건 이러나 저러나 변함이 없기 때문이죠 두가지 경우를 꼼꼼히 비교해 보시면
안되는 이유를 더 명확히 아실 수 있을겁니다.

그러면 @array의 5번째 요소인 익명배열을 @b 라는 배열에 넣을려면 어떻게 해야할까요?
지금까지 배운 규칙을 사용해서 하나하나 차근차근 해보면 일단 익명배열의 레퍼런스(scalar값)는
${$arrayref}[4] 가 됩니다. 이제 이 익명배열 레퍼런스를 dereference해서 배열로 하려면
@{}을 사용해서 @{${$arrayref}[4]} 로 하면 최종적으로 배열을 뽑아내게 됩니다. 따라서
@b = @{${$arrayref}[4]}; 이렇게 하면 되겠죠. 그리고 앞에서 배운 규칙에 따라
@b = @{$$arrayref[4]}; 혹은
@b = @{$arrayref->[4]};
이렇게도 됩니다.

여기서 {}을 생략하는 형태인 이것들은 왜 안될까? 하는건
@b = @$$arrayref[4];
@b = @$arrayref->[4];
이미 위에서 예를 들어 얘기했기 때문에 알 수 있을겁니다.


제가 말씀드린 규칙
1. reference를 dereference 할때는 [sigil]{}연산자를 사용
( sigil은 최종적으로 만들어질 타입, reference는 scalar값이다. )

2. [sigil]{} 에서 {}는 생략가능
( 단 생략할때는 연산자 우선순위에 따른 해석 순서에 문제가 없어야 함 )

3. [sigil]{}은 ->로 대체가능
( 여러개일때 [],{}들사이의 ->는 편의상 생략이 가능 )

이것만 잘 기억하고 이해하시면 reference/derefrence는 헷갈릴 일이 전혀 없습니다.

 

추가 답변

 

@array = ( "one", "two", "three", "four", [10, 20, 30, 40, 50] );

 

$array[4][4]는 실제로 다음과 같은 절차를 거친 형태입니다.
1. ${$array[4]}[4]
2. $array[4]->[4]
3. $array[4][4]

$arrayref->[4][4] 는 다음과 같은 절차를 거친 형태이고요.
1. ${${$arrayref}[4]}[4]
2. ${$arrayref->[4]}[4]
3. $arrayref->[4]->[4]
4. $arrayref->[4][4]

다음은 Perl Cookbook에 있는 내용을 발췌 한것입니다.
이 내용에 입각해서 원초적 형태로 돌려 놓고 보면 혼돈의 여지가 없을겁니다.
--------------------------------------------------------------
<원문>
Confusion About Precedence
The expressions involving key lookups might cause some confusion. Do you read $$rarray[1] as ${$rarray[1]} or {$$rarray}[1] or ${$rarray}[1]?

(Pause here to give your eyes time to refocus!)

As it happens, the last one is the correct answer. Perl follows these two simple rules while parsing such expressions: (1) Key or index lookups are done at the end, and (2) the prefix closest to a variable name binds most closely. When Perl sees something like $$rarray[1] or $$rhash{"browns"}, it leaves index lookups ([1] and {"browns"}) to the very end. That leaves $$rarray and $$rhash. It gives preference to the `$' closest to the variable name. So the precedence works out like this: ${$rarray} and ${$rhash}. Another way of visualizing the second rule is that the preference is given to the symbols from right to left (the variable is always to the right of a series of symbols).

<해석>
우선순위에 대한 혼돈
key를 찾는것을 포함하는 표현은 약간의 혼돈을 줄 수 있다. $$rarray[1]을
${$rarray[1]} 또는 {$$rarray}[1] 또는 ${$rarray}[1] 어떤것으로 읽겠는가?

마지막이 맞는답이다. Perl은 그러한 표현을 파싱하는데 있어 다음의 간단한 두 법칙을 따른다:
(1) Key또는 index 찾는건 맨 마지막에 일어난다.
(2) 변수명에 가장 가까운 prefix는 가장 가까이서 결합된다.
Perl이 $$rarray[1] 또는 $$rhash{"browns"}를 볼때 [1]과 {"browns"}같은 index는 맨 마지막으로 제껴두면 $$rarray와 $$rhash가 남는다.
이것은 변수명에 가장가까운 $에 우선순위를 둔다.
그래서 우선순위는 ${$rarray}와 ${$rhash} 와 같이 동작한다.
두번째 법칙을 가시화하는 또 다른 방법은 우선순위는 symbol들에서 오른쪽에서 왼쪽으로 주어진다는것이다.
(변수는 항상 심볼들의 집합에서 항상 오른쪽에 위치한다.)
--------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment