Perlのサブルーチン定義を簡素化
Perlはサブルーチンの引数を明示的に取り出さなくてはならない。
たとえば、数nを+1するサブルーチンの定義は次のようになる。
# 定義 sub inc { my ($n) = @_; $n + 1; } # 呼び出し print inc(255) , "\n"; # 256と表示
めんどくさい。Rubyっぽくしたい。
# 定義 sub inc2 { |$n| $n + 1; } # 呼び出し print inc2(255) , "\n"; # 256と表示
そこでソースフィルタを使ってみた。
use Filter::Simple; # '{ |...|' => '{ my (...) = @_;' FILTER_ONLY code => sub { s{ ( \{ \s* \| )( .*? )( \| ) } { \{ my \($2\) = \@_; }gxs };
調子に乗って無名関数も簡素にしてみる。
use Filter::Simple; # '\{' => ' sub{' FILTER_ONLY code => sub { s{ \\\{ }{ sub \{ }gxs };
アキュムレータの例。Perlの方言?
# 定義 sub accum { |$n| \{ |$i| $n += $i }; } # 呼び出し my $foo = accum(2); print $foo->(100), "\n"; # 102と表示 print $foo->(100), "\n"; # 202と表示 print $foo->(100), "\n"; # 302と表示
ソースコードを書き換えてしまうためソースフィルタは危険すぎる。
もっと安全に構文を変える方法が知りたいな・・・
やっぱりマクロするならlispみたいなS式が向いてるのだろうか?
Magic.pm
use strict; use warnings; package Magic; use Filter::Simple; # '\{' => ' sub{' FILTER_ONLY code => sub { s{ \\\{ }{ sub \{ }gxs }; # '{ |...|' => '{ my (...) = @_;' FILTER_ONLY code => sub { s{ ( \{ \s* \| )( .*? )( \| ) } { \{ my \($2\) = \@_; }gxs }; 1;
sample.pl
#! /usr/bin/perl use strict; use warnings; use Magic; # 定義 sub inc2 { |$n| $n + 1; } # 実行 print inc2(255) , "\n"; # 256と表示 # 定義 sub accum { |$n| \{ |$i| $n += $i }; } # 実行 my $foo = accum(2); print $foo->(100), "\n"; # 102と表示 print $foo->(100), "\n"; # 202と表示 print $foo->(100), "\n"; # 302と表示