Scala初心者ガイド中国語版-第三篇Patterns Everywhere(モードはどこにもありません)

5380 ワード

原文出典:http://danielwestheide.com/blog/2012/12/05/the-neophytes-guide-to-scala-part-3-patterns-everywhere.html、翻訳:トーマス
 
前二篇では、case classがモードでどのように構成されているかを説明するのに時間がかかりましたが、どのようにあらゆる種類のデータを抽出することができる抽出器を実現しますか?
今までは少数の使用パターンの方法しか見られませんでしたが、今はあなたのScaraコードの中でどのようにパターンを使うべきかを見に来ました。始めましょう。
 
パターンマッチング式
モードがよく出てくるシーンはモードマッチング式で、CourseraのScaraコースに参加したり、前の2つの文章を完全に読んだりした後、この使い方に詳しいはずです。まず、表式eがあります。後ろにはmatchキーワードとコードブロックがあります。コードブロックには任意のcaseサブフレーズが含まれます。一つのcaseサブフレーズはcaseキーワードの先頭から後にモードとオプションの防護従節に従って、後はモードマッチングに成功した後に実行するコードの一部です。
以下は、パターンと保護文を含むcaseを使用した簡単な例です。
 
case class Player(name: String, score: Int)

def printMessage(player: Player) = player match {
  case Player(_, score) if score > 100000 => println("Get a job, dude!")
  case Player(name, _) => println("Hey " + name + ", nice to see you again!")
}
printMessage  Unitは、副作用を実行すること、すなわち情報を印刷することが唯一の目的である。ちょっと重要です。ここでモードを合わせなければならないとは限らないです。Javaの中のSwitch文のように使えます。ここでモードマッチング式と呼ぶ理由がありますが、match全体の戻り値は最初にマッチしたモードの戻り値です。
 
通常、この特性を使うのはいい方法です。二つの原本は同じではないことを結合してもいいです。コードをテストしやすいです。上のコードを書き換えてもいいです。
 
def message(player: Player) = player match {
  case Player(_, score) if score > 100000 => "Get a job, dude!"
  case Player(name, _) => "Hey " + name + ", nice to see you again!"
}
def printMessage(player: Player) = println(message(player))
今私たちはStringタイプのメッセージを返す方法を持っています。今は純粋な関数です。パターンマッチングの結果を返します。もちろん結果を定数で与えられます。
 
定数/変数定義にモードを使う
Scalaでは定数定義文の左側にモードを使用することもできます。(変数定義ではもちろん使えますが、できるだけScalコードの関数スタイルを維持したいです。だから、私のシリーズの文章では変数の使用はあまり見られません。)もし我々が現在のプレイヤーに戻る方法があるとしたら、まず偽の方法を実現します。いつも固定されたプレイヤーに戻ります。
 
def currentPlayer(): Player = Player("Daniel", 3500)
は、通常あなたの定数定義がこう見えます。
 
 
val player = currentPlayer()
doSomethingWithTheName(player.name)
もしPythonプログラマーだったら、シーケンスの解凍機能に詳しいかもしれません。Scalaは同様の機能を提供しています。定量定義文の左側で任意のパターンを使ってもいいです。上のコードを改造して、playerを構成してから定数を指定できます。
 
 
val Player(name, _) = currentPlayer()
doSomethingWithTheName(name)
は任意のモードでこの用途に使えますが、通常はモードが常にマッチしていることを確認しなければなりません。そうでないと運行時に異常が発生します。例えば、次の例は問題があります。
スコアリストを返す方法です。この方法は空のリストを返すと問題になります。
 
 
def scores: List[Int] = List()
val best :: rest = scores
println("The score of our champion is " + best)
を見て、プログラムはMatch Errorを一つなくしました。結局、私たちのゲームプログラムはもう走れなくなりました。ゲームの成績が取れませんでした。
 
このようにモードを使いたいです。一番いい方法は構造case classです。コンパイルする時にそのタイプを確定できます。tupleも同時に使用すれば、コードの可読性がより良くなります。もし私たちがtupleパッケージのプレイヤー名とその得点を返す関数があるとします。Playerクラスはもう使いません。
 
def gameResult(): (String, Int) = ("Daniel", 3500)
 
tupleにアクセスする要素は迷惑になります。
 
val result = gameResult()
println(result._1 + ": " + result._2)
この時、定数定義時にモードで構成するのは安全です。私たちが直面しているのはTuple 2データタイプだと知っています。
 
 
val (name, score) = gameResult()
println(name + ": " + score)
これは前のコードより読むことができるのではないですか?
 
 
for文でモードを使う
for文でモードを使うのも価値があります。例えば、for文には定数の定義が含まれています。前に紹介した定数定義文の左側の使用パターンの使い方は、for文にも適用されます。私たちがゲームのプログラムで名人堂を実現したいなら、つまり得点がしきい値を超えるプレイヤーリストです。for文を使って、強い可読性のあるコードを実現できます。
 
def gameResults(): Seq[(String, Int)] =
  ("Daniel", 3500) :: ("Melissa", 13000) :: ("John", 7000) :: Nil

def hallOfFame = for {
  result <- gameResults()
  (name, score) = result
  if (score > 5000)
} yield name
 
hallOfFameの結果はList("Melissa", "John")です。最初のプレイヤーは子文を守る条件を満たしていないからです。
コードをさらに簡潔にして、for文の中で、generatorの左側もモデルであることができます。だから、私達はresult定数を導入しなくてもいいです。直接generator左側でモードで解決できます。
 
def hallOfFame = for {
   (name, score) <- gameResults()
  if (score > 5000)
} yield name
はここの例では、パターンは常に一致しているので、子文は守られていません。
if(score>5000)
このコードは、tupleをプレイヤー名に変換するのに相当します。
 
もう一つ重要なのは、generatorの左側のモードにフィルタ機能を備えていることです。左側のモードが合わないと、該当する元素がフィルタされます。例えば、リストがあると仮定して、非空リストのサイズをすべて返します。これは空リストをフィルタして、残りのリストのサイズを返すという意味です。次は解決方法です。
val lists = List(1, 2, 3) :: List.empty :: List(5, 3) :: Nil

for {
  list @ head :: _ <- lists
} yield list.size
generator左側のパターンは空リストと一致しない。Match Errorを投げ出すのではなく、空listをフィルタするので、結果はList(3,2)に戻ります。for文の中でモードを使うのはとても自然で強い組み合わせです。Scalaを使うと、好きになります。
匿名関数
最後に、モデルは匿名関数を定義するためにも使用され得る。もしあなたがScatch文のブロックを使って異常を処理したら、実はもうこのような使い方を使ったことがあります。モデルマッチング匿名関数は単独の章で説明する必要があるテーマです。言いたいことが多すぎるので、このモードに関するページでは多すぎません。このシリーズの後編で紹介します。
更新:hallOfFameのエラーを修正します。Rajivに感謝します。エラーを見つけてください。
作者:Daniel Westheide、202.2.5