7

foreach や map などの高次関数のコード ブロックを Scala で初期化する興味深い可能性を見ました。

(1 to 3) map {
  val t = 5
  i => i * 5
}


(1 to 3) foreach {  
  val line = Console.readLine  
  i => println(line)  
}  

これは文書化された機能ですか、それともそのような構造を避けるべきですか? 「初期化」ブロックがコンストラクターに入り、クロージャー自体が apply() メソッドになると想像できますか?

元の質問をしてくれた Pat に感謝します ( http://extrabright.com/blog/2010/07/10/scala-question-regarding-readline )

4

2 に答える 2

12

使用される機能は珍しいものではありませんが、かなり奇妙な機能の組み合わせであることは認めます。基本的なトリックは、Scala のすべてのブロックが式であり、その型がブロック内の最後の式と同じであるということです。最後の式が関数である場合、これはブロックに関数型があることを意味し、したがって "map" または "foreach" への引数として使用できます。これらの場合に何が起こるかというと、「map」または「foreach」が呼び出されると、ブロックが評価されます。ブロックは関数 (最初のケースでは i=> i*5 ) に評価され、その関数は範囲にマップされます。

このコンストラクトの考えられる用途の 1 つは、ブロックで変更可能な変数を定義し、結果の関数が呼び出されるたびに変数を変更することです。変数は一度初期化され、関数によって閉じられ、関数が呼び出されるたびに値が更新されます。

たとえば、最初の 6 つの階乗数を計算するやや驚くべき方法を次に示します。

(1 to 6) map {
      var total = 1
      i => {total *= i;total}
    } 

(ちなみに、例として階乗を使用して申し訳ありません。それはそれかフィボナッチのどちらかでした。Functional Progamming Guild のルールです。それについては問題があるでしょう。ホールで男の子と一緒に取り上げてください。)

ブロックに関数を返す必要があまりない理由は、ブロックの早い段階でヘルパー関数を定義することです。たとえば、2 番目の例が代わりに

(1 to 3) foreach {  
  def line = Console.readLine  
  i => println(line)  
}

その結果、3 行がそれぞれ 1 回読み取られ、エコーされますが、この例では 1 回読み取られ、3 回エコーされます。

于 2010-07-10T20:55:29.850 に答える
1

まず、元ブログのコメント「Scala Question About readLine」投稿言及

「<code>line」は値であり、実行することはできません。「<code>Console.readLine」メソッドの実行結果から一度だけ割り当てられます。
クロージャでの使用回数は 3 回未満です。
ただし、メソッドとして定義すると、3 回実行されます。

(1 to 3) foreach {
  def line = Console.readLine
  i => println(line)
}

ブログScala for Java Refugees Part 6: Getting Over Javaには、次のような高次関数に関する興味深いセクションがあります。

Scala は、これらの高階関数の構文にさらに柔軟性を提供します。
iterate 呼び出しでは、メソッドへの別の呼び出しを行うためだけに、匿名メソッド全体を作成していますprintln(String)。is 自体が a を受け取りを返すメソッドであることを
考えると、これを少し圧縮できると考える人もいるでしょう。結局のところ、次のことができます。println(String)StringUnit

iterate(a, println)

括弧を省略してメソッド名だけを指定することで、Scala コンパイラーに関数値として使用したいことを伝え、printlnそれをメソッドに渡しますiterate
したがって、単一の呼び出しセットを処理するためだけに新しいメソッドを作成する代わりに、必要なことを既に実行している古いメソッドを渡します。
これは、C および C++ で一般的に見られるパターンです。実際、関数を関数値として渡す構文はまったく同じです。変わらないものもあるようです…</p>

于 2010-07-10T20:55:10.577 に答える