web-dev-qa-db-ja.com

入れ子関数に名前を付ける方法は?

Scalaで別の関数をラップする関数がある場合。ネストされた関数を何と呼びますか?

私はこれを見つけました :

def factorial(i: Int): Int = {

  def fact(i: Int, accumulator: Int): Int = {
     if (i <= 1)
        accumulator
     else
        fact(i - 1, i * accumulator)
  }

  fact(i, 1)

}

私は通常doを使用します。これは、短く、汎用的で、明示的だからです。しかし、入れ子関数のより良い方法または命名規則はありますか?

def myFunction() = {

  def do(i: Int) = {
    ...
  }
  do(1)

}
6
user34903

慣習は必要ありません。ローカル関数はコードの残りの部分には公開されないため、他の誰もそれを気にすることはありません。別の場所ではなく、ある場所でうまく機能する可能性のある慣習について心配するのではなく、状況に応じて意味のあるものを選択するといいます。

これが末尾再帰フィボナッチ実装です:

def fib (n: Long): Long = {
  def loop(current: Long, next: => Long, iteration: Long): Long = {
    if (n == iteration) 
      current
    else
      loop(next, current + next, iteration + 1)
  }
  loop(0, 1, 0)
}

私はそれをfibloopと呼ぶこともできましたが、それが何かを追加することは本当にないと思います。他の場所にはアクセスできないので、なぜ「名前空間」を設定する必要があるのでしょうか。おそらく、それをforwardloopと呼んだ方がわかりやすいかもしれませんが、fibloopはそうではありません。どちらかと言えば、それをloopと呼ぶことは、それがローカルであることを強調します。

メソッド/関数が長すぎて、ヘルパー/ローカル関数が再び表示されるまでにどこで定義されたかを忘れてしまった場合は、命名規則の必要性がわかります(ただし、関数が目的が明確で、どのくらいの頻度で問題になるのですか?個人的には、私は冗長なものを書くことを避けようとしますが、そうする場合は、これが実際に問題となるメソッドの特別な規則を保存することをお勧めします。それでも、適切に選択された名前は、アンダースコアの数よりも役立つはずです。

メソッドが十分に簡潔な場合(およびローカル関数も単純な場合)、名前を気にする必要がないようにするために、関数リテラルを使用することがあります。

ここで、ローカル関数の前にアンダースコアを付けることで、外部関数をシャドウする可能性を完全に回避できることに対抗できます。あなたが別のローカル関数の中にローカル関数を持っている場合はどうなるのかと尋ねることによって私はそれに答えますか? 2つのアンダースコアを使用しますか?コードを再編成する場合、自分で作成したこの問題を追跡するために、どれだけの検索と置換を行う準備ができていますか?

5
itsbruce

他のいくつかの言語で私が見た慣習は、純粋に実装の詳細として存在するプライベートな一時的な名前付き関数に先頭または末尾の下線を使用することです。

def factorial(i : Int): Int = {
  def _factorial(i : Int, acc : Int): Int = {
    ...
  }
  _factorial(i)
}

この場合、公式の基準があるとは思いません。それをfactfactorialImplementationと呼ぶだけでもいいでしょう。

階乗といえば、これは正しい学習のために行われていると思いますか?同じ結果を得るには、短くてメンテナンスが簡単な方法がいくつかあるからです。 reduceLeft(またはHaskellの出身の場合はfoldl1)を使用する実装が好きです。

Stream.from(1).take(n).reduceLeft(_*_)
2
KChaloux