2010.03.25
yna

ハッシュ引数、perl、PHP、ruby

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

 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()も不必要です。

一覧に戻る