2010-01-19 3 views
4

내 응용 프로그램에 필요한 다른 설정 값을 검증하기 위해 나중에 사용되는 유형을 정의 할 (YAML에) 설정 파일을 사용하고 있습니다 :어떻게 eval을 사용하여 정의 된 Perl 서브 루틴에 매개 변수를 전달할 수 있습니까?

--- 
action: > 
     use List::MoreUtils; 
     my $value = $_; 
     any { $value eq $_ } qw(fatal keep merge non-fatal replace); 
dir : return defined $_ ? -d $_ : -1; 
file : return defined $_ ? -f $_ : -1; 
string: 1; 


--- 
config-element: 
    value: foo 
    type : file 
etc ... 

아이디어는 eval 각 유형의 정의입니다으로 던져 해시 다음 구성 데이터의 유효성을 검사 전화 (다음은 쉽게 이해도에 대한 개략도이다) :

#throw sub refs into hash 
my %type_sub; 
foreach my $key (keys %$type_def_ref) { 
    my $sub_str = "sub {$type_def_ref->{$key}}"; 
    $type_sub{$key} = eval $sub_str; 

} 

#validate (myfile is a real file in the cwd) 
print $type_sub{file}->('myfile'),"\n"; 
print $type_sub{action}->('fatal'), "\n"; 

문제는 %의 type_sub의 서브 루틴은 매개 변수를 허용하지 않는 것이다. 위의 경우, 첫 번째 인쇄 문은 -1 동안 두 번째 출력 출력 :

Use of uninitialized value $value in string eq at (eval 15) line 1. 
Use of uninitialized value $_ in string eq at (eval 15) line 1. 
Can't call method "any" without a package or object reference at 
(eval 15) line 1. 

모두 내가 기대하지, 아직 서브 루틴 호출되고있다.

내가 뭘 잘못하고 있니?

편집 : 나는 이제 엉망이되어 모든 것이 제대로 작동합니다. Friedo에게 감사드립니다.

답변

3

서브 루틴 매개 변수는 $_이 아닌 @_ 배열에 있습니다. 첫 번째 매개 변수를 가져 오려면 $_[0]을 보거나 my $foo = shift;을 입력하십시오. (shift은 기본적으로 @_에서 작동합니다.) any에 관해서는

는, 저는 믿습니다 문제는 any가 (서브 루틴의 프로토 타입 만 컴파일 타임에 호출 할 수 있습니다.) 당신이해야 할 수도 있습니다 런타임에 프로토 타입을로드 할 수 없다는 때문이다 명시 적 괄호와 명시 적 서브 루틴 참조를 사용하는 경우 :

any(sub { $value eq $_ }, qw(fatal keep merge non-fatal replace)); 
+0

와우. 필자는 항상 @_를 시프트 또는리스트 할당과 함께 사용했으며 $ _는 너무 일반적이어서 자동으로 설정되지 않는다는 것을 완전히 잊었다. – gvkv

+0

나는 'any'에 대한 해결책을 찾았지만 운이 없었습니다. eval이나 다른 방법을 사용하여 문자열로 서브 루틴을 정의하는 방법에 대한보다 일반적인 질문이 있습니다. 아마도 나중에 물어볼 것입니다. – gvkv

+0

나는 그것을 고쳤다. List :: MoreUtils는 기본적으로 아무 것도 내보내지지 않습니다. – gvkv

5

구성에 코드를 쓰지 마십시오. 코드를 사용하여 라이브러리를 만들고 사용할 서브 루틴 이름을 간단하게 구성하십시오. 이렇게하면 문자열을 코드로 변환하고 프로세스를 관리하는 엄청난 양의 작업을 줄일 수 있습니다. 또한 누군가가 구성을 조정하고 구문 오류를 도입 할 때 문제를 추적하는 데 많은 시간을 절약 할 수 있습니다.

이 글은 Mastering Perl의 "구성"장과 동적 서브 루틴에 대한 장에서 자세히 설명합니다.

코드가 구성에 속하지 않습니다. 당신이 그것을 믿을 때까지 그렇게 말하십시오.

+0

당신은 당연한 것입니다. 그러나 한 줄짜리 대단한 것이 아니라고 생각했습니다. (어쨌든 나는 그 원칙을 어겼습니다). – gvkv

+0

다른 문제는 엄격한 심판을 끄지 않고 어떻게 해야할지 모르겠다는 것입니다. – gvkv