3

ruby のコーディング中に奇妙な状況に遭遇しました。

def foo(bar=true,baz,*args)
end

次のエラーが発生します。

syntax error, unexpected tSTAR

これらに対して:

def foo(bar,baz=true,*args)
end

def foo(bar=true,baz=true,*args)
end

大丈夫です。

奇妙なことに、これらは次のとおりです。

def foo(bar,baz=true)
end

def foo(bar=true,baz)
end

どちらも機能します。

ただし、これは次のとおりです。

def foo(bar=true,baz,args=true)
end

エラーが発生しますが、これらは次のとおりです。

def foo(bar=true,baz=true,args)
end

def foo(bar,baz=true,args=true)
end

は大丈夫です。

特定の組み合わせが許可され、他の組み合わせが許可されないのには論理的な理由があると思いますが、Googleでもstackoverflowでも検索してもどこにも見つかりません。私の質問は単純です: これらの組み合わせのいくつかは許可されているのに、他の組み合わせは許可されていないのはなぜですか?

4

1 に答える 1

5

そこにあるRubyの本はこれを詳細に説明しています。しかし、それがなくても、その論理に慣れます。まともなコーダーは、次のように、強制的な順序付きパラメーターが最初になるように関数を定義します。

def foo( a, b, c=0, d=0 )
  # ...
end

簡単に言えば、最初の 2 つの引数はa, に移動し、b最大 2 つのオプションの引数cは ,dにこの順序で移動します。しかし、あなたには常識を超えた自由が与えられています。

def foo( a=0, b )
  # ...
end

引数を 1 つ指定すると、 に移動しbます。引数を 2 つ指定すると、 、 、 の順に割り当てられaますb。これは、ユーザーからより多くのことを学ぶ必要があるため、まともではありません。あなた自身がユーザーなら、あなたは自分自身に卑猥ですが、それでも構文上のあいまいさはまったくありません。これを見てください:

def foo( a=0, b, c=0 )
  # ...
end

に電話した場合、、、、または、、というfoo( 1, 2 )意味でしたか? おそらく最初の可能性が高いですが、コーディングのルールは、ユーザーの意図を推測しないことです。そのため、Ruby チームはこの構文を甘やかさないことに決めたのでしょう。以下を定義することで、それを実現できます。a = 1b = 2c = 0a = 0b = 1c = 2

def foo( *args )
  a, b, c = case args.size
            when 1 then [0, args[0], 0]
            when 2 then [*args, 0]
            when 3 then args
            else fail ArgumentError; "#{args.size} arguments for 1..3!" end
  # ...
end

これにより、実際には完全な自由が与えられますが、Ruby は優れた実践へと導きます。つまり、良いコードを悪いコードよりも見栄えよくすることです。*splat で引数を収集する場合も同様です。まともなケースは明白です:

def foo( a, b=0, *c )
  # ...
end

ただし、次の場合:

def foo( a=0, b, *c )
  # ...
end

を呼び出したとき、、、および、または、、およびのfoo( 1, 2, 3 )ことでしたか? したがって、この 2 番目のケースも推奨されませんが、実現可能です。a = 1b = 2c = [3]a = 0b = 1c = [2, 3]

def foo( *c )
  a, b = case c.size
         when 0 then fail ArgumentError, "Too few arguments!"
         when 1 then [0, c.shift]
         else [c.shift, c.shift] end
  # ...
end

多くの引数、特に多くの順序付けされた引数を持つ関数を書くことは、悪い習慣です。バイナリ メソッドは 3 項よりも優れており、単項はバイナリよりも優れており、最後に、ヌルは単項よりも優れているという古いことわざがあります。メソッドに多くの引数が必要な場合は、 object に置き換えてリファクタリングする必要があります。これはあなたの質問に答えていますか?

于 2013-06-09T02:21:25.653 に答える