汎用的な関数を書いていると、可変パラメータの関数を必要とすることがある。
一般には、可変引数を使うことが多いのだが、可変引数はでは個数を変えることはできますが、フラグを設定するような場合は不便なことが多い。
2個の固定パラメータと、いくつかの可変引数、それにハッシュ引数を渡す関数と書いてみよう。
まず、perl
funcSample(10, 20, 30,31,32, {"google"=>10, "yahoo"=>20} );
ここでは、2個のパラメータと、いくつかの可変引数、最後にハッシュのリファレンスを渡すようにしている。
sub funcSample($$@)
{
my ($a,$b,@args) = @_;
print "a=$a\n";
print "b=$b\n";
$i = 0;
$opt = {}
$opt = pop( @args) if( ref($args[-1]) eq 'HASH' );
for $x( @args ){
print "\targs[$i] => $x\n";
$i++;
}
while( ($k,$v) = each(%$opt)){
print "\topt[$k] => $v\n";
}
}
最後のパラメータが、ハッシュのリファレンスかどうかをチェックして、ハッシュなら$optに読み込んでいます。
使うほうとしては、忘れずにハッシュ引数を{}で囲まないとならないけど、読みづらいということはなさそう。
次はPHP。可変引数が使えるけど、可変引数では、ハッシュ(連想記憶配列)の形式では渡せません。そこで、固定引数3個にして、最後の引数をarrayにします。
funcSample(10, 20, 30,31,32, array("google"=>10, "yahoo"=>20 ));
毎回arrayを書かなくてはならないので、書きやすさ、読みやすさはちょっと劣るけど、一応の目的は達成できそう。
function funcSample($a, $b)
{
print "a=$a\n";
print "b=$b\n";
$args = func_get_args();
array_shift($args ); #!!
array_shift($args ); #!!
$opt = array();
if( is_array( $args[sizeof($args)-1] )){
$opt = array_pop( $args );
}
foreach( $args as $k => $v ){
print "\targs[$k] => $v\n";
}
foreach( $opt as $k => $v ){
print "\topt[$k] => $v\n";
}
}
PHPの場合は、関数を書くほうはかなり大変。特に#!!でコメントマークをつけた行は、固定パラメータの部分を読み飛ばす処理だけど、保守性はよくなさそう。こんな書き方をするくらいなら、固定パラメータを書かずに、こうしたほうが利口かもしれない。
$a = array_shift($args ); #!!
$b = array_shift($args ); #!!
最後にruby。
rubyは、パラメータリストの最後に、ハッシュパラメータを置く約束になっています。ハッシュパラメータの後ろに普通のパラメータを置いた場合は、文法エラーになります。これは、使うほうも使いやすいですね。
funcSample 10, 20, 30,31,32, :google=>10, :yahoo=>20
def funcSample(a,b,*ary, &func)
print "a=#{a}\n";
print "b=#{b}\n";
opt = {}
opt = ary.pop if ary[-1].is_a?(Hash)
ary.each_with_index {|x,i|
print "\tary(#{i})=#{x}\n"
}
opt.each{|k,v|
print "\topt[#{k}]=#{v}\n"
}
end
関数を書くほうも比較的自然に書けるし、使い側も普通に書けます。{}で囲む必要もなければ、ましてやarray()も不必要です。