요즘 트위터에서 맞팔로우율을 계산해주는 서비스가 있길래 남이 만든서비스에 로그인하기도 꺼림직하고 누가 나를 팔로우하고 있지 않는지 여부도 따로 안 보여주는것 같아서 직접 한번 만들어 봤다.
처음엔 Twitter API를 통해서 하려고 했으나 Twitter측에 확인을 받고 white list에 들어가지 않으면 시간당 150번 호출 제한이 걸려서 이것 때문에 따로 요청하고 하는 것도 귀찮아서 Perl의 WWW::Mechanize 모듈을 사용하여 일반 웹페이지를 긁어서 분석하도록 만들었다.
프로그램의 동작방식을 간단히 설명하자면 소스에서 아이디와 패스워드 부분을 자기계정정보로 바꾼다음 Perl 스크립트를 실행시키면 로그인한다음 following 페이지를 클릭하고 유저리스트가 끝날때 까지 다음 페이지를 계속 넘겨가며 매 페이지의 HTML소스를 분석하여 direct-messageable인 계정은 서로 맞팔로우하고 있다는 것이므로 이것을 카운트 한다.
본인의 실행결과는 다음과 같다.
0 al3x
1 kwonjuga
1 stephenodonnell
1 LimeBurst
0 planetsysad
1 lifewind
.
.
중간생략
.
.
0 clkao
1 pung96
1 takesako
0 bradfitz
1 obra
0 miyagawa
1 hanekomu
170/345 Cross following rate is 49.28%
처음엔 Twitter API를 통해서 하려고 했으나 Twitter측에 확인을 받고 white list에 들어가지 않으면 시간당 150번 호출 제한이 걸려서 이것 때문에 따로 요청하고 하는 것도 귀찮아서 Perl의 WWW::Mechanize 모듈을 사용하여 일반 웹페이지를 긁어서 분석하도록 만들었다.
프로그램의 동작방식을 간단히 설명하자면 소스에서 아이디와 패스워드 부분을 자기계정정보로 바꾼다음 Perl 스크립트를 실행시키면 로그인한다음 following 페이지를 클릭하고 유저리스트가 끝날때 까지 다음 페이지를 계속 넘겨가며 매 페이지의 HTML소스를 분석하여 direct-messageable인 계정은 서로 맞팔로우하고 있다는 것이므로 이것을 카운트 한다.
본인의 실행결과는 다음과 같다.
0 al3x
1 kwonjuga
1 stephenodonnell
1 LimeBurst
0 planetsysad
1 lifewind
.
.
중간생략
.
.
0 clkao
1 pung96
1 takesako
0 bradfitz
1 obra
0 miyagawa
1 hanekomu
170/345 Cross following rate is 49.28%
jeen님의
주의! - 다음은 system wide하게 모듈을 인스톨 할 수 있는 root권한이 없으며 이전에 아무런 cpan 사용환경이 구축되지 않은 계정에서 사용자 계정안에 독립적으로 모듈을 설치해서 쓰려고 할 때 적용되는 방법임.
1. cpanm 소스를 임시로 받는다.
wget http://github.com/miyagawa/cpanminus/raw/master/cpanm
또는
wget http://xrl.us/cpanm
2. local::lib 과 App::cpanminus를 임시로 받은 cpanm을 통해 설치한다.
perl cpanm --local-lib=~/perl5 local::lib App::cpanminus
3. local::lib사용을 위한 환경변수를 .bashrc에 추가한다.
echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >> ~/.bashrc
4. .bashrc를 다시 읽어들인다. ( 적절한 local::lib 환경변수 추가됨)
. ~/.bashrc
5. 기존에 wget으로 받은 cpanm은 App::cpanminus로 새로운 cpanm이 local::lib이 지정하는 경로에 설치되어 더이상 필요 없으므로 지운다.
rm cpanm
6. 이제 local::lib으로 ~/perl5/bin/ 에 설치된 cpanm을 그냥 실행가능하다.
cpanm
이제
cpanm 모듈명 으로 모듈 설치가능
자세한 옵션은 cpanm --help
참고: local::lib 모듈로 CPAN 모듈을 일반계정에 설치하기
[Perl/CPAN] cpanm 이 당신의 Perl 생활을 윤택하게 해드립니다
포스팅을 보니 처음 사용하는 사람에게는 몇가지 신경써줘야 할 부분이 생략된 것 같아서 전체 bootstrapping 과정을 적용해봄주의! - 다음은 system wide하게 모듈을 인스톨 할 수 있는 root권한이 없으며 이전에 아무런 cpan 사용환경이 구축되지 않은 계정에서 사용자 계정안에 독립적으로 모듈을 설치해서 쓰려고 할 때 적용되는 방법임.
1. cpanm 소스를 임시로 받는다.
wget http://github.com/miyagawa/cpanminus/raw/master/cpanm
또는
wget http://xrl.us/cpanm
2. local::lib 과 App::cpanminus를 임시로 받은 cpanm을 통해 설치한다.
perl cpanm --local-lib=~/perl5 local::lib App::cpanminus
3. local::lib사용을 위한 환경변수를 .bashrc에 추가한다.
echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >> ~/.bashrc
4. .bashrc를 다시 읽어들인다. ( 적절한 local::lib 환경변수 추가됨)
. ~/.bashrc
5. 기존에 wget으로 받은 cpanm은 App::cpanminus로 새로운 cpanm이 local::lib이 지정하는 경로에 설치되어 더이상 필요 없으므로 지운다.
rm cpanm
6. 이제 local::lib으로 ~/perl5/bin/ 에 설치된 cpanm을 그냥 실행가능하다.
cpanm
이제
cpanm 모듈명 으로 모듈 설치가능
자세한 옵션은 cpanm --help
참고: local::lib 모듈로 CPAN 모듈을 일반계정에 설치하기
요즘 Perl 5의 새로운 OOP프레임웍으로 뜨고있는 Moose로 클래스를 정의할 때 각종 문서나 책마다 조금씩은 다른 방법으로 사용하는 부분이 있는데 그것은 네임스페이스를 청소하는 방법이다.
package SomeClass;
use Moose;
.
.
.
__PACKAGE__->meta->make_immutable;
no Moose;
1;
package SomeClass;
use Moose;
use namespace::clean -except => 'meta';
.
.
.
__PACKAGE__->meta->make_immutable;
1;
package SomeClass;
use Moose;
use namespace::autoclean;
.
.
.
__PACKAGE__->meta->make_immutable;
1;
여기서 네임스페이스를 청소한다는 말은 use Moose 하면서 import된 클래스/객체를 구성하기 위해 사용되는 Sugar함수들(has,after,extends등)을 사용이 다 끝나면 제거한다는 말이다.(meta 관련 함수는 meta object protocol 구현과 관련있기 때문에 제거하지 않는다.) 제거를 하지 않아도 문제가 없을 수 있겠지만 어떠한 함수들이 자동으로 import되었는지 알기 어렵고 나중에 해당 클래스를 사용하는 코드에서 그러한 함수들이 예기치 않은 문제를 일으킬 소지가 있기 때문에 제거하는 것이 좋다. ( __PACKAGE__->meta->make_immutable; 은 더이상 meta object protocol을 통한 동적인 변화가 없다는 걸 명시하는 것으로 처리속도를 높이기 위해 넣어주는 부분 )
그럼 위의 3가지가 어떻게 다른지 한 번 살펴보자.
여기서 제일 먼저 이해하고 넘어가야 할 것은 namespace::clean 의 동작방식이다. namespace::clean의 동작방식은 Avoid accidently creating methods from module exports( http://www.effectiveperlprogramming.com/blog/124 )와 namespace::clean 모듈문서( http://search.cpan.org/perldoc?namespace::clean )를 참고
간단하게 말하자면 namespace::clean은 use namespace::clean 이전에 정의되었거나 import된 함수(function)들을 use namespace::clean이 정의된 렉시컬 영역이 끝나는 시점에 제거하며( 여기서 주의할 것은 제거하는 시점은 compile time이 아니라는 것 ) no namespace::clean 이 나오면 제거 대상들을 use namespace::clean 다시 나올 때 까지 다시 모은다는 것이다. 그리고 제거에서 제외할 대상을 -except를 사용하여 지정할 수 있다.
$ perl -e '{ sub hello { print "hello\n" } } hello()'
hello
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean; } hello()'
Undefined subroutine &main::hello called at -e line 1.
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean -except=>"hello"; } hello()'
hello
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean; sub say_hello { hello() } } say_hello(); hello()'
hello
Undefined subroutine &main::hello called at -e line 1.
$ perl -e '{ use namespace::clean; sub hello2 { print "hello2\n" } no namespace::clean; sub hello3 { print "hello3\n" } use namespace::clean; } hello2(); hello3()'
hello2
Undefined subroutine &main::hello3 called at -e line 1.
위 결과를 보면 이해가 갈 것이다.
그러면 이제 Avoid accidently creating methods from module exports 에 있는 현재 package에서 정의된 함수들을 보여주는 show_defined_subs 함수가 포함된 Moose 클래스를 처음에 얘기한 3가지 경우와 그것들은 사용하지 않았을 경우를 만들어서 비교해보자.
<아무것도 사용하지 않을 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
around
has
blessed
meta
after
augment
inner
new
extends
get_defined_subs
before
super
DESTROY
croak
confess
override
with
<no Moose를 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
no Moose;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
croak
<use namespace::clean -except => 'meta' 를 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
use namespace::clean -except => 'meta';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
<use namespace::autoclean 을 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
use namespace::autoclean;
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
위 결과를 종합해 보면 3가지 모두 Moose와 관련된 Sugar함수들을 제거 하기는 하나 no Moose의 경우 다른 모듈을 통해서 import한 함수(위에서는 Carp의 croak함수)들은 제대로 제거하지 못하며 use namespace::clean -except => 'meta'; 나 use namespace::autoclean; 은 meta관련 함수들 빼고는 모두 똑같이 제거함을 볼 수 있다.( 다르게 보면 namespace::autoclean 은 namespace::clean의 Moose특화 버젼으로 볼 수 있음 )
그러면 Moose로 클래스를 만들때 어떤 방법을 쓰는 게 좋을까? 일단 no Moose는 위에서 보듯 어떤 경우에 완벽하지 못함을 볼 수 있다. 따라서 use namespace::autoclean;을 쓰는 것이 좋아 보인다. 그러면 use namespace::clean -except => 'meta';은 쓸데없이 길기만 한 방법일까?
하지만 꼭 그런건 아니다. Avoid accidently creating methods from module exports 에서도 보듯이 클래스 메소드가 아닌 클래스 내부에서만 접근가능한 함수를 정의할 필요가 있을때 namespace::autoclean 모듈은 namespace::clean 의 no namespace::clean 처럼 unimport 기능을 통해 나중에 네임스페이스에서 제거할 함수를 따로 지정할 방법이 없기 때문에 경우에 따라서는 namespace::clean으로만 가능한 경우도 있게 된다.
결론을 내리자면 Moose로 클래스를 정의할때 namespace::autoclean을 쓰면 되겠고 위에서 말한 부득이한 경우에만 namespace::clean을 사용하면 된다. 둘다 나름 존재의 이유가 있다고 볼 수 있는 것이다.
package SomeClass;
use Moose;
.
.
.
__PACKAGE__->meta->make_immutable;
no Moose;
1;
package SomeClass;
use Moose;
use namespace::clean -except => 'meta';
.
.
.
__PACKAGE__->meta->make_immutable;
1;
package SomeClass;
use Moose;
use namespace::autoclean;
.
.
.
__PACKAGE__->meta->make_immutable;
1;
여기서 네임스페이스를 청소한다는 말은 use Moose 하면서 import된 클래스/객체를 구성하기 위해 사용되는 Sugar함수들(has,after,extends등)을 사용이 다 끝나면 제거한다는 말이다.(meta 관련 함수는 meta object protocol 구현과 관련있기 때문에 제거하지 않는다.) 제거를 하지 않아도 문제가 없을 수 있겠지만 어떠한 함수들이 자동으로 import되었는지 알기 어렵고 나중에 해당 클래스를 사용하는 코드에서 그러한 함수들이 예기치 않은 문제를 일으킬 소지가 있기 때문에 제거하는 것이 좋다. ( __PACKAGE__->meta->make_immutable; 은 더이상 meta object protocol을 통한 동적인 변화가 없다는 걸 명시하는 것으로 처리속도를 높이기 위해 넣어주는 부분 )
그럼 위의 3가지가 어떻게 다른지 한 번 살펴보자.
여기서 제일 먼저 이해하고 넘어가야 할 것은 namespace::clean 의 동작방식이다. namespace::clean의 동작방식은 Avoid accidently creating methods from module exports( http://www.effectiveperlprogramming.com/blog/124 )와 namespace::clean 모듈문서( http://search.cpan.org/perldoc?namespace::clean )를 참고
간단하게 말하자면 namespace::clean은 use namespace::clean 이전에 정의되었거나 import된 함수(function)들을 use namespace::clean이 정의된 렉시컬 영역이 끝나는 시점에 제거하며( 여기서 주의할 것은 제거하는 시점은 compile time이 아니라는 것 ) no namespace::clean 이 나오면 제거 대상들을 use namespace::clean 다시 나올 때 까지 다시 모은다는 것이다. 그리고 제거에서 제외할 대상을 -except를 사용하여 지정할 수 있다.
$ perl -e '{ sub hello { print "hello\n" } } hello()'
hello
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean; } hello()'
Undefined subroutine &main::hello called at -e line 1.
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean -except=>"hello"; } hello()'
hello
$ perl -e '{ sub hello { print "hello\n" } use namespace::clean; sub say_hello { hello() } } say_hello(); hello()'
hello
Undefined subroutine &main::hello called at -e line 1.
$ perl -e '{ use namespace::clean; sub hello2 { print "hello2\n" } no namespace::clean; sub hello3 { print "hello3\n" } use namespace::clean; } hello2(); hello3()'
hello2
Undefined subroutine &main::hello3 called at -e line 1.
위 결과를 보면 이해가 갈 것이다.
그러면 이제 Avoid accidently creating methods from module exports 에 있는 현재 package에서 정의된 함수들을 보여주는 show_defined_subs 함수가 포함된 Moose 클래스를 처음에 얘기한 3가지 경우와 그것들은 사용하지 않았을 경우를 만들어서 비교해보자.
<아무것도 사용하지 않을 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
around
has
blessed
meta
after
augment
inner
new
extends
get_defined_subs
before
super
DESTROY
croak
confess
override
with
<no Moose를 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
no Moose;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
croak
<use namespace::clean -except => 'meta' 를 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
use namespace::clean -except => 'meta';
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
<use namespace::autoclean 을 사용한 경우>
#!/usr/bin/env perl
use strict;
use warnings;
{
package SomeClass;
use Moose;
use Carp 'croak';
use namespace::autoclean;
sub get_defined_subs
{
my( $package ) = @_;
no strict 'refs';
foreach my $name ( keys %{"${package}::"} )
{
next unless defined &{"${package}::$name"};
print "$name\n";
}
}
__PACKAGE__->meta->make_immutable;
}
SomeClass->get_defined_subs;
<결과>
meta
new
get_defined_subs
DESTROY
위 결과를 종합해 보면 3가지 모두 Moose와 관련된 Sugar함수들을 제거 하기는 하나 no Moose의 경우 다른 모듈을 통해서 import한 함수(위에서는 Carp의 croak함수)들은 제대로 제거하지 못하며 use namespace::clean -except => 'meta'; 나 use namespace::autoclean; 은 meta관련 함수들 빼고는 모두 똑같이 제거함을 볼 수 있다.( 다르게 보면 namespace::autoclean 은 namespace::clean의 Moose특화 버젼으로 볼 수 있음 )
그러면 Moose로 클래스를 만들때 어떤 방법을 쓰는 게 좋을까? 일단 no Moose는 위에서 보듯 어떤 경우에 완벽하지 못함을 볼 수 있다. 따라서 use namespace::autoclean;을 쓰는 것이 좋아 보인다. 그러면 use namespace::clean -except => 'meta';은 쓸데없이 길기만 한 방법일까?
하지만 꼭 그런건 아니다. Avoid accidently creating methods from module exports 에서도 보듯이 클래스 메소드가 아닌 클래스 내부에서만 접근가능한 함수를 정의할 필요가 있을때 namespace::autoclean 모듈은 namespace::clean 의 no namespace::clean 처럼 unimport 기능을 통해 나중에 네임스페이스에서 제거할 함수를 따로 지정할 방법이 없기 때문에 경우에 따라서는 namespace::clean으로만 가능한 경우도 있게 된다.
결론을 내리자면 Moose로 클래스를 정의할때 namespace::autoclean을 쓰면 되겠고 위에서 말한 부득이한 경우에만 namespace::clean을 사용하면 된다. 둘다 나름 존재의 이유가 있다고 볼 수 있는 것이다.
KLDP에서 어느분이 Ruby로 메타프로그래밍에 대해서 소개하시길래 Perl로 따라해봤다.
Perl에서도 현대적이고 최신의 OOP Framework인 Moose를 사용하면 손쉽고 강력한 메타프로그래밍이 가능하다. 그리고 유연하고 풍부한 문법은 다양한 프로그래밍 스타일을 구사하는데 막힘이 없다.
use 5.010;
# Tool 클래스 정의
{
package Tool;
use MooseX::SingletonMethod;
sub setup1 {
say "setup1";
}
}
# Tool 클래스에 setup2 메소드 추가
Tool->meta->add_method( setup2 => sub { say "setup2" } );
my $tool = Tool->new;
# $tool 객체에 singleton 메소드 추가
$tool->add_singleton_method( setup3 => sub { say "setup3" } );
$tool->setup1;
$tool->setup2;
$tool->setup3;
my $tool2 = Tool->new;
$tool2->setup1;
$tool2->setup2;
$tool2->setup3; # error
use 5.010;
# Brain 클래스 정의
{
package Brain;
use Moose;
has iq => ( isa => 'Int', is => 'rw', default => 100 );
}
my $brain = Brain->new;
# 클래스 내부 들여다 보기
say $brain->meta->get_attribute('iq')->type_constraint; # Int
say $brain->meta->get_attribute('iq')->get_value( $brain ); # 100
# 블럭 메소드 호출하기
use 5.010;
sub func {
my ( $block ) = @_;
$block->();
&$block; # 이렇게도 호출~
}
sub func2 {
$_[0]->(); # 더 간단하게
&{ $_[0] }; # 이렇게도 호출~
}
my $block = sub { say "Block" };
func($block);
func2($block);
use strict;
use warnings;
use 5.010;
# 메소드 호출테이블
my $METHOD_TABLE = [ qw/a b c d/ ];
sub a { say "sub a" }
sub b { say "sub b" }
sub c { say "sub c" }
sub d { say "sub d" }
&{$main::{$_}} for @{$METHOD_TABLE};
$main::{$_}->() for @{$METHOD_TABLE};
no strict 'refs';
foreach my $i ( 0 .. $#{$METHOD_TABLE} ) {
&{ $METHOD_TABLE->[$i] };
}
$_->() for @{$METHOD_TABLE};
foreach my $func ( 'a' .. 'd' ) {
&$func;
}
foreach my $func ( 'a' .. 'd' ) {
$func->();
}
# 이런식이 더 나은?
my %METHOD_TABLE2 = (
a => sub { say "sub a" },
b => sub { say "sub b" },
c => sub { say "sub c" },
d => sub { say "sub d" },
);
$METHOD_TABLE2{$_}->() for 'a'..'d';
참고:
Ruby & Javascript Metaprogramming
Perl 5 Metaprogramming
Perl 6 Metaprogramming
Perl에서도 현대적이고 최신의 OOP Framework인 Moose를 사용하면 손쉽고 강력한 메타프로그래밍이 가능하다. 그리고 유연하고 풍부한 문법은 다양한 프로그래밍 스타일을 구사하는데 막힘이 없다.
use 5.010;
# Tool 클래스 정의
{
package Tool;
use MooseX::SingletonMethod;
sub setup1 {
say "setup1";
}
}
# Tool 클래스에 setup2 메소드 추가
Tool->meta->add_method( setup2 => sub { say "setup2" } );
my $tool = Tool->new;
# $tool 객체에 singleton 메소드 추가
$tool->add_singleton_method( setup3 => sub { say "setup3" } );
$tool->setup1;
$tool->setup2;
$tool->setup3;
my $tool2 = Tool->new;
$tool2->setup1;
$tool2->setup2;
$tool2->setup3; # error
use 5.010;
# Brain 클래스 정의
{
package Brain;
use Moose;
has iq => ( isa => 'Int', is => 'rw', default => 100 );
}
my $brain = Brain->new;
# 클래스 내부 들여다 보기
say $brain->meta->get_attribute('iq')->type_constraint; # Int
say $brain->meta->get_attribute('iq')->get_value( $brain ); # 100
# 블럭 메소드 호출하기
use 5.010;
sub func {
my ( $block ) = @_;
$block->();
&$block; # 이렇게도 호출~
}
sub func2 {
$_[0]->(); # 더 간단하게
&{ $_[0] }; # 이렇게도 호출~
}
my $block = sub { say "Block" };
func($block);
func2($block);
use strict;
use warnings;
use 5.010;
# 메소드 호출테이블
my $METHOD_TABLE = [ qw/a b c d/ ];
sub a { say "sub a" }
sub b { say "sub b" }
sub c { say "sub c" }
sub d { say "sub d" }
&{$main::{$_}} for @{$METHOD_TABLE};
$main::{$_}->() for @{$METHOD_TABLE};
no strict 'refs';
foreach my $i ( 0 .. $#{$METHOD_TABLE} ) {
&{ $METHOD_TABLE->[$i] };
}
$_->() for @{$METHOD_TABLE};
foreach my $func ( 'a' .. 'd' ) {
&$func;
}
foreach my $func ( 'a' .. 'd' ) {
$func->();
}
# 이런식이 더 나은?
my %METHOD_TABLE2 = (
a => sub { say "sub a" },
b => sub { say "sub b" },
c => sub { say "sub c" },
d => sub { say "sub d" },
);
$METHOD_TABLE2{$_}->() for 'a'..'d';
참고:
Ruby & Javascript Metaprogramming
Perl 5 Metaprogramming
Perl 6 Metaprogramming
Continue reading Perl 메타프로그래밍.
Perl에서 CPAN모듈들을 설치할때 해당 모듈이 필요로 하는 모듈이 많을 경우 다음과 같이 기본적으로 설치할 것인지를 물어보는데 이런 모듈의 수가 많아지면 일일이 확인하며 yes를 해주기가 귀찮을 때가 많다. 특히나 Catalyst 웹프레임웍 같이 의존성을 많이 가지는 모듈일 경우는 더더욱..
- Catalyst::Plugin::I18N ...loaded. (0.04)
[XMLRPC Support]
- Catalyst::Plugin::XMLRPC ...missing.
==> Auto-install the 1 optional module(s) from CPAN? [y] y
[Pluggable Application Support]
- Catalyst::Plugin::Pluggable ...loaded. (0.04)
[DBIx::Class Support]
- Catalyst::Model::DBIC ...missing.
- Catalyst::Model::DBIC::Plain ...missing.
==> Auto-install the 2 optional module(s) from CPAN? [y] y
이럴때 물어보지 않고 필요할 모듈들을 자동으로 설치하려면 어떻게 해야 할까?
방법은 크게 2가지가 있다.
PERL__MM_USE_DEFAULT 환경변수를 1로 세팅하는 방법
$ PERL_MM_USE_DEFAULT=1 cpan
cpan> install Some::Module
CPAN설정에서 prerequisites_policy 을 follow로 설정하는 방법
$ cpan
cpan> o conf prerequisites_policy follow
cpan> o conf commit
cpan> install Some::Module
참고:
http://sipb.mit.edu/doc/cpan/
http://stackoverflow.com/questions/898782/how-do-i-tell-cpan-to-install-all-dependencies
- Catalyst::Plugin::I18N ...loaded. (0.04)
[XMLRPC Support]
- Catalyst::Plugin::XMLRPC ...missing.
==> Auto-install the 1 optional module(s) from CPAN? [y] y
[Pluggable Application Support]
- Catalyst::Plugin::Pluggable ...loaded. (0.04)
[DBIx::Class Support]
- Catalyst::Model::DBIC ...missing.
- Catalyst::Model::DBIC::Plain ...missing.
==> Auto-install the 2 optional module(s) from CPAN? [y] y
이럴때 물어보지 않고 필요할 모듈들을 자동으로 설치하려면 어떻게 해야 할까?
방법은 크게 2가지가 있다.
PERL__MM_USE_DEFAULT 환경변수를 1로 세팅하는 방법
$ PERL_MM_USE_DEFAULT=1 cpan
cpan> install Some::Module
CPAN설정에서 prerequisites_policy 을 follow로 설정하는 방법
$ cpan
cpan> o conf prerequisites_policy follow
cpan> o conf commit
cpan> install Some::Module
참고:
http://sipb.mit.edu/doc/cpan/
http://stackoverflow.com/questions/898782/how-do-i-tell-cpan-to-install-all-dependencies

