文法 - scala 関数




Scalaで複数の変数を宣言する (4)

私はこのように複数の変数を宣言するためにvalを使用したいと思います:

val a = 1, b = 2, c = 3

しかし何らかの理由で構文エラーですので、どちらかを使用して終了しました:

val a = 1
val b = 2
val c = 3

または

val a = 1; val b = 2; val c = 3;

私は個人的に、両方のオプションをあまりにも冗長で醜いものにしています。

より良い選択肢がありますか?

また、Scalaは非常によく考えられた言語なので、なぜval a = 1, b = 2, c = 3構文が許されないのですか?


あなたがタプルでそれらを宣言するなら、それはうまくいくようです

scala> val (y, z, e) = (1, 2, 45)
y: Int = 1
z: Int = 2
e: Int = 45
scala> e
res1: Int = 45

私はおそらく個々の声明のために行くだろうが。 私には、これはより明確に見える:

val y = 1
val z = 2
val e = 45

特に変数に意味のある名前が付けられている場合


すべての変数が同じ型で、同じ初期値をとる場合は、これを行うことができます。

val a, b, c: Int = 0;

ダニエルの答えは、これを行うための正しい方法とそれがなぜ機能するかをきちんとまとめたものです。 彼はすでにその角度をカバーしていたので、私はあなたのより広い質問に答えようとします(言語デザインに関して)...

Scalaは可能な限り、既存のメカニズムを使って処理することに賛成して言語機能を追加することを避けるよう努めています。 たとえば、Scalaにはbreakステートメントは含まれていません。 しかし、あなた自身のものを図書館として転記することはほとんど自明です。

case object BreakException extends RuntimeException

def break = throw BreakException

def breakable(body: =>Unit) = try {
  body
} catch {
  case BreakException => ()
}

これは次のように使用できます。

breakable {
  while (true) {
    if (atTheEnd) {
      break
    }

    // do something normally
  }
}

注:これはScala 2.8の標準ライブラリに含まれています)

Ruby( x = 1, y = 2, z = 3 )などの言語で許可されているような複数の代入構文は、「冗長構文」のカテゴリに分類されます。 Scalaに既に特定のパターンを有効にする機能がある場合、そのパターンの特殊なケースを処理するためだけに新しい機能を追加することはありません。 この場合、Scalaはすでに複数の代入を扱うために使用できるパターンマッチング(一般的な機能)を持っています(他の解答で概説したタプルトリックを使用して)。 特定の特殊なケースを別の方法で処理する必要はありません。

わずかに異なるところでは、Cの(したがってJavaの)複数の代入構文も別のより一般的な機能の特殊なケースであることに注意することは重要です。 検討してください:

int x = y = z = 1;

これは、代入がC派生言語で割り当てられた値(および代入が右結合であるという事実)を返すという事実を利用する。 Scalaではそうではありません。 Scalaでは、代入がUnit返します。 これにはいくつかの面倒な欠点がありますが、直接的に型の副作用を強調するため、理論的には有効です。


簡単な答えは、それらをタプルとして宣言することです。

val (a, b, c) = (1, 2, 3)

ここで興味深いのは、これはパターンマッチングに基づいているということです。 実際には、タプルを構築してからパターンマッチングを行い、 bbc値を代入します。

他にパターンマッチングの例をいくつか見てみましょう。

val DatePattern = """(\d{4})-(\d\d)-(\d\d)""".r
val DatePattern(year, month, day) = "2009-12-30"
val List(rnd1, rnd2, rnd3) = List.fill(3)(scala.util.Random.nextInt(100))
val head :: tail = List.range(1, 10)

object ToInt {
  def unapply(s: String) = try {
    Some(s.toInt)
  } catch {
    case _ => None
  }
}

val DatePattern(ToInt(year), ToInt(month), ToInt(day)) = "2010-01-01"

rnd同様に、特にrnd例は、以下に示すように、より簡単に、そしてパターンマッチングを示すことなく記述することができます。

val rnd1, rnd2, rnd3 = scala.util.Random.nextInt(100)




scala