본문 바로가기

Common Gateway Interface/Perl

[옛 강좌] 41. Advanced_Perl - Typeglobs and Symbol Tables

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 이 게시물은 지금은 폐쇄되어 접속되지 않는 Kim Young Soo(http://hours.interpia98.net/~unisoo/)님의 웹 사이트에 2001년경 게시된 내용을 바탕으로 오늘날 웹 환경에 맞게 내용을 덧붙였습니다.

Advanced_Perl - Typeglobs and Symbol Tables

Description

Perl 에서 사용하는 Typeglobs 와 Symbol Tables 에 대한 이야기입니다.


Typeglobs and Symbol Tables

Perl에서만 사용하는 (다른 언어에선 볼 수 없는..), Typeglobs에 대해서, 그리고, local과 my의 차이점을 알아봅니다.

Perl Variable, Symbol Table

 my와 local에 관해선, 이전의 이채광님의 글에 잘 표현되어 있습니다. 조금만 더 살펴보겠습니다.

 우선, Symbol Tables 라는 것은, 펄에서 어떤 변수를 선언하였을 때, 이 변수들을 기록해 놓은 일종의 표라고 생각하시면 됩니다. 심볼 테이블과 타입 글로브의 관계를 간단히 말씀드리면...

 $foo라는 변수를 선언하였다면... 심볼 테이블에 'foo' 가 기록이 되게 됩니다. 또, $foo, @foo, %foo, &foo, foo (filehandles), foo (format)이라는 값들은 Typeglob (*foo)에 기록이 됩니다.

 이들 변수들은 - 스칼라, 해쉬 등 - 펄에선 모두 다른 변수가 됩니다. 이름은 같지만, $foo@foo는 엄연히 다른 변수들의 값입니다. my로 선언된 변수들은 이 심볼 테이블에 기록이 되지 않는 변수들입니다. 그 블록 내에서만 유효하게 사용할 수 있는 변수들입니다.

local과 my

$a = 20;

{
	local ($a);
	my (@b);
	
	$a = 10;
	@b = ("wallace", "grommit");
	
	print "$a\n";
	print "@b\n";
}

print $a;
print @b;
					

위의 예제를 실행해 보시면, '10, wallace grommit, 20'이라고 출력되는 걸 보실 수 있습니다. 마지막의 print "@b\n"; 는 출력할 값이 없죠.

 처음 $a로 선언이 된 변수는, 블록 내에서 local로 선언을 했다고 해서 값이 없어지는 건 아닙니다. 단지, 심볼 테이블에 있는 $a의 값을 잠시... 잠시 다른 값으로 대체를 시키고, 블록을 빠져 나가면, 원래의 값으로 다시 돌려 놓습니다. 그래서.. 블록 내에선 '10'이, 블록 바깥으로 나가면 원래의 값인 '20'을 출력하게 됩니다.

 하지만, my 로 선언된 값은, 심볼 테이블에 기록은 되지 않으며, 그냥 그 블록 내에서만 잠시 선언되서 쓰이고, 블록 바깥으로 나가면, 없어지게 됩니다.

 지역변수로 선언시 local, my 중, 특별한 경우가 아니라면 (typeglob 사용시), my 를 사용하시는 게 빠르고 안전합니다.

Typeglobs

 변수를 쓰게 되면, 심볼 테이블에 기록이 되고, 타입 글로브에 기록이 된다는 말씀을 드렸죠. 이런 이유로 '*'를 사용할 시는 반드시 local로 선언하셔야 합니다.

$spud = "Wow!";
@spud = ("idaho", "russet");

*potato = *spud;

print "$potato\n";
print "@spud\n";
					

 위의 예제 실행 결과는 어떻게 될까요?

Wow!
idaho russet
					

이렇게 됩니다.

*potato = *spud;
					

 우리는 위에서 'spud'라는 변수명과 'potato'라는 변수명을 동일시 하겠다고 선언했습니다. 이렇게 선언이 되면, $potato - $spud, &potato - &spud등... spud로 선언된 어떤 변수명이든지 간에, $potato로 대치해서 사용할 수 있게 됩니다. 아래의 예제는 재미있습니다.

$b = 10;
{
	local *b;
	
	*b = *a;
	$b = 20;
}

print $a;
print $b;
					

 위 예제의 출력 결과는?

20
10
					

이렇게 됩니다.

 처음 $b를 '10'으로 선언했습니다. 그 다음, *b = *a라고 선언했구요. 여기서... 우리는 $b의 값을 '20'으로 만들었습니다. 그렇다면... 당연.. $a의 값도 20이 되겠죠? 하지만.. 블록을 벗어 나면서, *b의 값은 원래의 값으로 복원됩니다. 그래서.. $b = 10;이 되는 거구요.. 하지만 $a의 값은 위에서 선언된 대로.. '20'의 값이 저장됩니다.

 *b = *a;로 선언을 하였다면... 둘 중에 어떤 값이 변화를 하든지 간에.. aliasing된 다른 변수들의 값도, 같이 변경됩니다.

Typeglobs and References

 레퍼런스의 값도 타입 글로브로 선언하여 사용할 수 있습니다.

*b = \$a;

 하지만 위의 경우는 조금 다릅니다. $b$a만 같습니다. @b@a는 서로 다른 변수가 됩니다.

$PI = \3.1415927;

라고 선언 하였다면.. 위의 $PI 변수는 다른 값으로 대치될 수 없습니다.

$PI = 10;

하게 되면, "Modification of a read-only value attempted at test.pl line 4"라며 에러를 내게 됩니다.

 이런식으로 우리는 변경이 불가능한 변수또한 선언할 수 있습니다.

Filehandles, Directory Handles..

 우리는 파일을 열 때,

open (F, "...");

 라고 사용을 하지요... 이 때의 파일 핸들인 'F' 또한 alias 시켜서 사용할 수 있습니다. 다음의 예제를 보겠습니다.

open (F, 'test.txt') || die print "$!";
read_and_print(*F);

sub read_and_print
{
	local (*G) = @_;
	while (<G>) { print; }
}
					

 'test.txt'에 어떤 내용을 넣어 놓고, 위의 예제를 실행해 보세요. 파일 핸들로 열렸던 모든 내용 'F' 를 'G' 에서 사용할 수 있게 됩니다.


NOTES

 타입글로브를 가지고 우리는 굉장히 유용한 작업을 할수 있습니다. 하지만, 잘못 사용하였을 경우.. 우리는 예상치 못한 값들을 가지게 될 수도 있어요. 하지만.. 좋은 건 분명한거 같아요. 다른 언어에선 볼 수 없는 펄만의 특징 중 하나죠. 지금까지 symbol table, local, my, typeglob 에 대해서 짧게 이야기 하였습니다. 좀 더 깊이 있는 내용은 관련 서적을 참고하세요.


이 문서는 Perl 패키지내의 pod2html를 이용하여 만들었습니다. - Kim Young Soo