2009-08-05 6 views
4

필자는 Perl에서 함수 목록을 가지고 있습니다. 예 :어떻게 Perl의 함수 목록을 반복 할 수 있습니까?

my @funcs = qw (a b c) 

이제는 모두이 모듈 Foo :: Bar :: Stix에 속합니다. 나는 루프에서 반복적으로 그들에게 전화하고 싶은 :

foreach $func (@funcs) { 
    Foo::Bar::Stix::$func->(%args) 
} 

인수는 인수의 해시입니다. 그러나 나는이 오류를 계속 : Foo :: Bar :: Stix :: $ func -> (% args)가 포함 된 줄에 "Bad name after :: ..."이 오류를 어떻게 수정합니까?

A B와 C

는 함수 객체하지만 문자열

하지

답변

9

을 오히려, 저장 참조 그들에게 상징적 참조를 사용 당신이 이름으로 그들을 참조 할 수 있도록 해시로. 당신이 어떤 이유로 이름을 저장 붙어있는 경우

#!/usr/bin/perl 

use strict; 
use warnings; 

my %func_refs = (
    'a' => \&Foo::Bar::Stix::a, 
    'b' => \&Foo::Bar::Stix::b, 
    'c' => \&Foo::Bar::Stix::c 
); 

foreach my $func_ref (values %func_refs) { 
    print $func_ref->("woohoo: "), "\n"; 
} 

{ 
    package Foo::Bar::Stix; 

    sub a { 
    my $arg = shift; 
    return $arg . "a"; 
    } 

    sub b { 
    my $arg = shift; 
    return $arg . "b"; 
    } 

    sub c { 
    my $arg = shift; 
    return $arg . "c"; 
    } 
} 

,이 시도 :

my $package = "Foo::Bar::Stix"; 
my @func_names = qw/ a b c /; 
foreach my $func_name (@func_names) { 
    my $str = &{ "$package\::$func_name" }("woohoo: "); 
    print $str, "\n"; 
} 

그러나, 이것은 이것 때문에 use strict에서 작동하지 않습니다 다음은 간단한 코드 예제 나는 첫번째 해결책을 선호한다. 무엇을 하든지 eval 사용을 피하십시오. 불필요하며 문제가 발생할 가능성이 큽니다.

또한 Perl을 사용하는 대부분의 사람들은 PERL 대신 PERL로 대문자로 표기합니다. 여기에 주제에 유래 질문입니다 : 당신은 특별한 %Foo::Bar::Stix:: 변수를 통해 액세스 할 수

How should I capitalize Perl?

+3

대문자 질문에 연결하는 경우 +1. 운명이 너무 나빠서 PERL로 Perl을 생각하면 아무 것도 작동하지 않습니다. – innaM

+1

'$ Foo :: Bar :: Stix :: {$ func} -> (% args);'도 작동 할 것이므로 엄격한 설정을 해제 할 필요가 없습니다. –

1
구문의

약간의 변경이 비록

Foo::Bar::Stix->$func(%args) 

는 첫 번째 매개 변수로 패키지 이름을 전달합니다 원하는 걸 줄 것이다.

3

나쁜 답 :

for $func (@funcs) { 
    &{"Foo::Bar::Stix::$func"}(\%args); 
} 

좋은 답 : 디스패치 테이블을 사용하여 배열의 함수의 이름을 저장하지

my %call_func = (
    'a' => \&Foo::Bar::Stix::a, 
    'b' => \&Foo::Bar::Stix::b, 
    'c' => \&Foo::Bar::Stix::c, 
); 
... 
for $func (@funcs) { 
    $call_func{$func}->(\%args); 
} 
+0

사용할 수 있습니다, 나는 내 대답에 동일했다 . –

0

. 이렇게하면 심볼 테이블에 직접 액세스 할 수 있습니다. 엄격 모드에서도 작동한다는 것을 알 수 있습니다.

#! /usr/bin/env perl 
use strict; 
use warnings; 

{ 
    package Foo::Bar::Stix; 
    sub a{ print "sub a\n" } 
    sub b{ print "sub b\n" } 
    sub c{ print "sub c\n" } 
} 

my @funcs = qw' a b c '; 
my %args; 

for my $func (@funcs) { 
    $Foo::Bar::Stix::{$func}->(%args); # <==== 
} 

또 다른 옵션은 :

my $symbol_table = $::{'Foo::'}{'Bar::'}{'Stix::'}; 

my %funcs = (
    # we only want the CODE references 
    'a' => *{ $symbol_table->{'a'} }{'CODE'}, 
    'b' => *{ $symbol_table->{'b'} }{'CODE'}, 
    'c' => *{ $symbol_table->{'c'} }{'CODE'}, 
); 

for my $func (@funcs) { 
    $funcs{$func}->(%args); # <==== 
} 

당신이 서브 루틴의 많은 수의 그 일을 할려고하는 경우에,이 내가 %funcs 변수를로드 할 방법이다.

서브 루틴에 정규화 된 이름과 해시 변수를 통한 액세스가 필요한 경우가 아니면이 작업을 수행하지 않습니다.

해시 변수를 통해 서브 루틴에만 액세스해야하는 경우이를 설정하는 것이 좋습니다.

my %funcs = (
    'a' => sub{ print "sub a\n" }, 
    'b' => sub{ print "sub b\n" }, 
    'c' => sub{ print "sub c\n" }, 
); 

참고 : 당신이 "my %funcs"를 대체 할 수있는 "our %funcs"

1

당신은 나는 완전히 당신과 동의 can

my @funcs = qw (a b c) 
foreach $func (@funcs) { 
    Foo::Bar::Stix->can($func)->(%args) 
} 
+0

Stack Overflow에서'qw 'a b c''또는'qw "a b c"'를 사용하는 것이 더 좋으므로 강조 표시가 더 합리적입니다. –

관련 문제