2

ループを使用してScalaのキューを空にするための次のスケッチを検討してください。

var queue = immutable.Queue[T]( /* .. some content ..*/ )
while( !queue.isEmpty ) {
   val (record, tempQueue) = queue.dequeue
   queue = tempQueue
   doSomethingWith(record)
}

tempQueue一時変数を回避し、 Scalaに返されたキュー値をループ変数に直接割り当てるためのトリックはありますqueueか?余分なシンボルを導入しなければならないのは面倒です。さらに、おそらく余分なコピーがあるかもしれません(ただし、これは最適化される可能性がありますが、確かではありません)。

編集1:もちろん、Ionut G. Stanが指摘しているように、次のように、パターンマッチングをスキップして、返されたペアを自分で分解できます。

while( !queue.isEmpty ) {
   val pair = queue.dequeue
   queue = pair._2
   doSomethingWith(pair._1)
}

だから私は次のように質問を洗練する必要があります:これをよりエレガントに行うためにパターンマッチングの構文糖衣を使用する方法はありますか?私はこのようなものを望んでいましたが、残念ながらコンパイルされません:

var queue = immutable.Queue[T]( /* .. some content ..*/ )
var record : A = _
while( !queue.isEmpty ) {
   (record, queue) = queue.dequeue
   doSomethingWith(record)
}
4

7 に答える 7

3

その構造(ループなど)を維持することを主張する場合while、おそらく次の場合を除いて、どのように短くすることができるかわかりません。

var queue = immutable.Queue[T]( /* some content */ )
while( !queue.isEmpty ) queue.dequeue match {
  case (record, tempQueue) =>
    queue = queue.dequeue
    doSomethingWith(record)
}

ただし、不変のキューを使用しているため、最も単純な同等のコードはおそらく次のとおりです。

for(record <- queue) {
  doSomethingWith(record)
}

パターンマッチング表記を使用して既存のものに割り当てる方法がないことを確認するこの関連する質問も参照してください。var

Scala言語仕様のセクション4.1も明確です。パターンマッチングスタイルの割り当てはval定義に拡張されます。つまり、新しい識別子をバインドします。

于 2011-12-20T14:29:15.410 に答える
2

不変のwhileループを使用していますQueue。より機能的なアプローチを使用してみませんか(Queueとにかく不変であるため)?

の各アイテムで実行する関数を定義しQueue、コレクション操作(必要なリターンに応じてマップなど)を使用して適用できます。

例えば

  import scala.collection.immutable._

  val q = Queue[(Int,Int)]((1,2),(3,4),(5,6))

  def doSomethingWith(a:(Int,Int)) = {
    a swap
  }

  //returns a new Queue with each tuple's elements swapped
  q map doSomethingWith

  //returns unit (so only useful if doSomethingWith has a side effect)
  q foreach doSomethingWith   
于 2011-12-20T14:45:10.187 に答える
2

不変のデータ構造では、再帰は物事を行うためのFPの方法です。

def foo[T](queue: immutable.Queue[T]) {
  if (!queue.isEmpty) {
    val (record, remaining) = queue.dequeue
    doSomethingWith(record)
    foo(remaining)
  }
}

foo(queue)基本的にはqueue foreach doSomethingWith、ブライアン・スミスが提案したものと同じです。

于 2011-12-20T16:12:47.563 に答える
1

_最大で使用可能なプレフィックス付きメンバーを使用できますTuple22

scala> val a = (1,2)
a: (Int, Int) = (1,2)

scala> a._1
res0: Int = 1

scala> a._2
res1: Int = 2
于 2011-12-20T13:54:12.503 に答える
0

これがパターンマッチですが、それでも一時変数が導入されています。

while( !queue.isEmpty ) {
  queue = queue.dequeue match {
    case (t: T, q: immutable.Queue[T]) =>      
      doSomethingWith(t)
      q
  }
}
于 2011-12-20T14:44:32.867 に答える
0

ここに少しハックがあります:

queue forall doSomethingWith

doSomethingWithそれがタイプであると仮定してT => Boolean

于 2011-12-20T16:06:26.243 に答える
0

条件に応じて、最初にリストをフィルタリングするか、takeWhileを使用してから、結果のセットにマップすることができます。何かのようなもの

(queue takeWhile condition) foreach operation

また

(queue withFilter condition) foreach operation

これは、条件が単一の要素の関数である場合にのみ機能します。必要な部分を折りたたんで蓄積することもできます(次のようになります:)

(Nil /: queue)(<add element to accumulator if needed>) foreach operation
于 2011-12-20T19:56:21.827 に答える