web-dev-qa-db-ja.com

Scalaの式とforeachの場合

私は Scalaでのプログラミング を進めており、Pythonの観点から物事を見てみたいと思いますが、 "Python in Scala"をプログラミングしたくありません。

制御フローに関する限り、私は何をすべきかよくわかりません。Pythonでは、for x in some_iterableを使用して死にます。 Scalaには、Oderskyがforexpressionと呼ぶ非常によく似た構造があり、おそらくJava forループと区別するためです。また、Scalaには、反復可能なデータ型のforeach属性(属性であると推測されるため、Scalaについて正しく名前を付けるのに十分な知識がない)があります。ただし、foreachを使用して、コンテナ内の各アイテムに対して1つの関数を呼び出す以上のことを実行できるとは思えません。

これにはいくつかの質問があります。 1つ目は、PythonのようにScalaで重要な/頻繁に使用されるコンストラクトの式です。2つ目は、for式の代わりにforeachを使用する必要がある場合です(関数を呼び出す明らかな場合を除く)コンテナの各アイテムに)?

ひどく曖昧になったり広すぎたりしないことを願っていますが、Scala(これまでのところ非常にクールに思えます)のデザイン/言語の基礎をいくつかつかもうとしています。

54
Rafe Kettler

pythonはリスト内包表記とジェネレーター式でforを使用します。それらはvery scala for式に似ています:

これはpythonです

_>>> letters = ['a', 'b', 'c', 'd']
>>> ints = [0, 1, 2, 3]
>>> [l + str(i) for l in letters for i in ints if i % 2 == 0]
['a0', 'a2', 'b0', 'b2', 'c0', 'c2', 'd0', 'd2']
_

これはscalaです

_scala> val letters = List('a', 'b', 'c', 'd')
scala> val ints = List(0, 1, 2, 3)
scala> for (l <- letters; i <- ints if i % 2 == 0) yield l.toString + i
res0: List[Java.lang.String] = List(a0, a2, b0, b2, c0, c2, d0, d2)
_

各コンストラクトは、多数のジェネレーター/イテレーターを受け取り、フィルター式を適用して、組み合わせた式を生成できます。 pythonでは_(expr for v1 in gen1 if expr1 for v2 in gen2 if expr2)_はおおよそ次と同等です:

_for v1 in gen1:
  if expr1:
    for v2 in gen2:
      if expr2:
        yield expr
_

In scala for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield exprはおおよそ次と同等です:

_gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))
_

python _for x in xs_構文が好きなら、おそらくscala for式が好きでしょう。

Scalaには、いくつかの追加の構文と翻訳の工夫があります。構文的にforを中括弧と共に使用すると、ステートメントを別々の行に配置できます。値の割り当ても実行できます。

_val res = for {
    i <- 1 to 20; i2 = i*i
    j <- 1 to 20; j2 = j*j
    k <- 1 to 20; k2 = k*k
    if i2 + j2 == k2
  } yield (i, j, k)
_

また、_v1 <- gen1_は実際に__case v1 => gen1_と一致します。一致しない場合、これらの要素は反復から無視されます。

_scala> val list = List(Some(1), None, Some(2))
scala> for (Some(i) <- list) yield i
res2: List[Int] = List(1, 2)
_

forは言語の重要な場所だと思います。あなたが読んでいる本の中にそれについての章全体(23)があるという事実から私は知ることができます!

59
huynhjl

はい、Scala(一般的に知られているように)理解のために多く使用されますが、実際にはメソッドの特定の組み合わせのための単なる構文糖であり、多くはこれらのメソッドを直接呼び出す代わりに構文糖を使用します。

Scala内包表記については、 この質問 を参照してください。特に、for (x <- xs) f(x)xs.foreach(x => f(x))

さて、あなたはforeachメソッドではあまり使用しないように見えると言いますが、Scalaコレクションのほとんどすべてのメソッドは(または)foreachのみで実装されています.Traversableのドキュメントを参照してください-すべてのメソッドはforeachのみで実装できます。

ScalaのyieldはPythonのyieldとは似ていないことに注意してください-that質問も。

25

ネストされた反復、フィルター、および変換をサポートしているため、Scalaのforは言語の長所の1つであり、非常に重要です。 foreachmap、およびfilterを使用するよりも好む傾向があります。

3
Fabian Steeg

Foreachは機能的なスタイルですが、forは必須のスタイルです。 LISPまたはスキームを実行したことがあれば、関数型プログラミングにすでに精通しています。そうでない場合は、最初は少し混乱するかもしれません。私が最初に行うことは、foreachのようなものに渡す匿名関数であるクロージャー構文について調べます。あなたはそれがすべてより理にかなっていることを理解したら。

3
JOTN

あなたの質問は、主に以下によって答えられます:

Scala's For Comprehensions

スカラ利回り

要約すると:それは主に文体的です。個人的には、機能的な方法論を好みますが、入れ子になったループを扱うときは理解が簡潔であることを好みます。

3
Northover