汎用的な関数を書いていると、可変パラメータの関数を必要とすることがある。
一般には、可変引数を使うことが多いのだが、可変引数はでは個数を変えることはできますが、フラグを設定するような場合は不便なことが多い。
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()も不必要です。