서브루틴을 선언하지 않고 사용한다

전종필

서브루틴은 항상 스크립트 혹은 require나 use로 호출한 스크립트 파일내에 선언되어 있어야 사용할 수 있는 것이 정상입니다.
그러나, 명시적으로 서브루틴을 선언하지 않고도 사용할 수 있는 방법이 있습니다.
바로 AUTOLOAD라는 특수 서브루틴을 선언하는 것입니다. 서브루틴이 너무 간단해서 하나로 몰아넣고 싶거나, 동적으로 서브루틴을 만드는 경우 등에 사용할 수 있습니다. 다음 프로그램을 보십시오.

@arr = ( 1..10 );
nosub();
print sum(@arr), "\n";
print avg(@arr), "\n";

sub longsub {
	# 긴 서브루틴은 그냥 만들고...
	# 생략....
	1;
}


sub AUTOLOAD {
        if( $AUTOLOAD =~ /::sum$/ ) {
                my $sum = shift;
                foreach (@_) { $sum += $_; }
                return $sum;
        }
        elsif( $AUTOLOAD =~ /::avg$/ ) {
                my $count = @_;
                sum(@_) / $count;
        }
        else {
                my $line = (caller)[2]; # caller에 대해서는 다른 팁에..
                warn "subroutine $AUTOLOAD is not defined but called at line $line.\n";
        }
}
이 스크립트가 출력하는 내용은 다음과 같습니다.

subroutine main::nosum is not defined but called at line 3.
55
5.5
AUTOLOAD 서브루틴은 정의되지 않은 모든 서브루틴 호출에 대해 응답해 줄 수 있습니다. AUTOLOAD 서브루틴 안에서, 호출된 서브루틴 이름은 $AUTOLOAD 변수안에서 찾을 수 있습니다. 형식은 ``package_name::subroutine_name''입니다.
위 출력내용에서 main 이라는 패키지 이름이 표시된 것은 Perl 스크립트에 별도로 package 표시를 하지 않으면 main 패키지가 되기 때문입니다.

AUTOLOAD 내에서는 위와 같이 서브루틴 이름에 따라 서로 다른 처리를 해 주고, 그 외의 알 수 없는 이름에 대해서는 위와 같이 else {} 로 별도 처리해 주는 것이 좋습니다. 그렇지 않으면 아무런 오류없이 프로그램이 진행되기 때문입니다.

Comments