본문 바로가기

Common Gateway Interface/Perl

[옛 강좌] 42. Subroutine References and Closures

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

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

Subroutine References and Closures

Description

이번에는 서브루틴의 레퍼런스와 Closures (영어가 짧아서... 뭐라 불러야 할지 몰겠어여... ^^;) 에 대한 이야기 입니다.


Subroutine References


Closures

 음.. 이거 한국말로 뭐라고 하져.... ^^; 개념이 쩜 그렇네요... 다음 예제를 보겠습니다.

 예제 1:

sub generate_greeting
{
	my ($greeting) = @_;
	
	return sub
	{
		my ($subject) = @_;
		print "$greeting $subject \n";
	};
}

$rs1 = generate_greeting("hello");
$rs2 = generate_greeting("my fair");

&$rs1("world");
&$rs2("lady");
				

출력결과 :

hello world
my fair lady
				

이렇게 됩니다.

 $greeting 이란 변수를 볼게요.. 처음 서브루틴이 호출되면, 익명의 서브루틴이 호출되게 됩니다. 이 때, 처음받은 $greeting이란 변수는 hold 상태가 되요. 그런 상태에서 두 번째 파라메터인 $subject을 받고, 다음 두 개의 변수를 출력하게 됩니다.

 $rs1이 불려진 상태에서 또 $rs1이 불려진 형태라고 볼 수 있는데요... 처음 인자는 'hello', 두 번째 인자는 'world'....

$rs1 = sub
{
	my ($subject) = @_;
	my ($greeting) = "hello";
	
	print "$greeting $subject \n";
}
				

 위의 서브루틴을 이렇게 표현할 수 있습니다. 위의 형태를 가진 서브루틴을 Closure 라고 한답니다. 이것에 흥미가 없으면.. 그냥 넘어가라고 하네요... :-)

Using Closures

 Closure 사용되는 곳은 "smart" callbacks와 "iterator (순환문)"이라고 합니다. 이건 그냥 예제만 보겠습니다. 관심이 더 가시는 분들은.... 참고 서적을 보세요...

"smart callbacks"

 이 예제는 Tk를 이용한 예제에요.. 그냥 간단히 박스 띄우는건데.. 윈도 사용자들은 어떻게 Tk를 이용하냐 하겠지만요.. ActivePerl에 가시면 윈도용 Tk와 모듈이 있답니다. 다운받으신 후 설치하시면 Tk를 이용하실 수 있습니다.

use Tk;

$topwindow = MainWindow->new();

CreateButton($topwindow, "hellow");
CreateButton($topwindow, "world");

TK::MainLoop();

sub CreateButton
{
	my ($parent, $title) = @_;
	my ($b);
	
	$callback_proc = sub
	{
		print "Button $title pressed \n";
	};
	
	$b = $parents->Button(
				'-text'         => "$title",
				'-fg'           => 'red',
				'-command'      => $callback_proc
			);
	$b->pack();
}
						

Iteratiors and Streams

 이 예제는 그냥 홀수와 짝수를 만드는 프로그램이에요.

sub even_odd_print_gen
{
	my ($rs1, $rs2);
	my ($last) = shift;
	
	$rs1 = sub
	{
		if ($last % 2) { $last++; }
		else { $last += 2; }
		print "$last \n";
	};
	
	$rs2 = sub
	{
		if ($last % 2) { $last += 2; }
		else { $last++; }
		print "$last \n";
	};
	
	return ($rs1, $rs2);
}

($even_iter, $odd_inter) = even_odd_print_gen(10);

&$even_iter();
&$odd_iter();
&$odd_iter();
&$even_iter();
&$odd_iter();
						

 위 예제는 조금 신기해요... even_odd_print_gen()이라는 서브루틴 안에 $rs1, $rs2 이렇게 2개의 또 다른 루틴이 있구요. 이걸 $rs1 또는 $rs2 만 따로 뽑을 수 있자나요... :)


NOTE

 음... 서브루틴이 레퍼런스와 Closure에 대해서 알아봤는데요.... 서브루틴의 레퍼런스는 잘 쓰일 수 있구요... 근데.. Closure... 저도 그렇게 쓸 기회는 많지 않을듯 싶어요... ^^;

 참고로 알아두시구요... 더 자세한 걸 알고 싶으시면... 관련 책을 참고하세요.


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