アットウィキロゴ

Example7.2

「Example7.2」の編集履歴(バックアップ)一覧はこちら

Example7.2 - (2011/02/24 (木) 08:40:06) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

#co(){ 7.2 Pattern Matching Pattern matching is a generalization of C or Java's switch statement to class hierarchies. Instead of a switch statement, there is a standard method match, which is defined in Scala's root class Any, and therefore is available for all objects. The match method takes as argument a number of cases. For instance, here is an implementation of eval using pattern matching. } ** 7.2 パターンマッチング (Pattern Matching) パターンマッチングは C や Java の switch 文をクラス階層に一般化したものです。switch 文の代わりに標準メソッド match があり、それは Scala のルートクラス Any で定義されていて、したがって全てのオブジェクトで使用できます。match メソッドは引数として複数のケースを取ります。たとえば、次はパターンマッチングを用いた eval の実装です。 def eval(e: Expr): Int = e match { case Number(n) => n case Sum(l, r) => eval(l) + eval(r) } #co(){ In this example, there are two cases. Each case associates a pattern with an expression. Patterns are matched against the selector values e. The first pattern in our example, Number(n), matches all values of the form Number(v), where v is an arbitrary value. In that case, the pattern variable n is bound to the value v. Similarly, the pattern Sum(l, r) matches all selector values of form Sum(v1 , v2 ) and binds the pattern variables l and r to v1 and v2 , respectively. } この例では,2つのケースがあります。各ケースはパターンと式を関連付けます。パターンはセレクタ値 e に対してマッチされます。この例の最初のパターンでは、Number(n) は形式 Number(v)、ただし v は任意の値、のすべての値にマッチします。この場合、&bold(){パターン変数} n は値 v に束縛されます。同様に、パターン Sum(l,r) は形式 Sum(v1,v2) のすべてのセレクタ値にマッチし、パターン変数 l と r を v1 と v2 へそれぞれ束縛します。 #co(){ In general, patterns are built from - Case class constructors, e.g. Number, Sum, whose arguments are again patterns, - pattern variables, e.g. n, e1, e2, - the "wildcard" pattern _, - literals, e.g. 1, true, "abc", - constant identifiers, e.g. MAXINT, EmptySet. } 一般的に、パターンは次項より構成されます - ケースクラスのコンストラクタ、たとえば Number, Sum などであり、その引数もまたパターン - パターン変数、たとえば n, e1, e2 - 「ワイルドカード」パターン _ - リテラル、たとえば 1, true, "abc" - 定数識別子、たとえば MAXINT, EmptySet #co(){ Pattern variables always start with a lower-case letter, so that they can be distinguished from constant identifiers, which start with an upper case letter. Each variable name may occur only once in a pattern. For instance, Sum(x, x) would be illegal as a pattern, since the pattern variable x occurs twice in it. } パターン変数は常に小文字で始まりますが、それは大文字で始まる定数識別子と区別するためです。各変数名は一つのパターンに1回だけ登場できます。たとえば Sum(x, x) は正しくないパターンですが、それはパターン変数 x が2回登場するからです。 #co(){ Meaning of Pattern Matching. A pattern matching expression } &b(){パターンマッチングの意味 } パターンマッチング式 e match { case p1 => e1 ... case pn => en } #co(){ matches the patterns p 1 , . . . , p n in the order they are written against the selector value e. -A constructor pattern C (p1 , . . . , pn ) matches all values that are of type C (or a subtype thereof ) and that have been constructed with C-arguments matching patterns p1 , . . . , pn . - A variable pattern x matches any value and binds the variable name to that value. - The wildcard pattern '_' matches any value but does not bind a name to that value. - A constant pattern C matches a value which is equal (in terms of ==) to C.} は、パターン p1,...pn に、書かれた順番で、セレクタ値 e に対してマッチします。 - コンストラクタパターン C(p1,...,pn) は型 C (あるいはそのサブタイプ) であり、パターン p1,...pn にマッチする、C の引数で生成されるすべての値でマッチします。 - 変数パターン x は任意の値にマッチし、変数名をその値に束縛します。 - ワイルドカードパターン '_' は任意の値にマッチしますが、名前をその値に束縛しません。 - 定数パターン C は C と (==の意味で) 等しい値にマッチします。 #co(){ The pattern matching expression rewrites to the right-hand-side of the first case whose pattern matches the selector value. References to pattern variables are replaced by corresponding constructor arguments. If none of the patterns matches, the pattern matching expression is aborted with a MatchError exception. } パターンマッチング式は、セレクタ値が最初にマッチするパターンの、ケースの右辺へと書き換えられます。パターン変数への参照は、対応するコンストラクタ引数で置き換えられます。もしどのパターンにもマッチしなければ、パターンマッチ式は MatchError 例外でアボートされます。 #co(){ Example 7.2.1 Our substitution model of program evaluation extends quite naturally to pattern matching, For instance, here is how eval applied to a simple expression is re-written: -> (by rewriting the application) -> (by rewriting the pattern match) -> (by rewriting the first application) -> (by rewriting the pattern match) } &b(){Example 7.2.1 } プログラム評価の置き換えモデルはきわめて自然にパターンマッチングへ拡張できます。たとえば次は、簡単な式に適用された eval がどの様に書き換えるかを示します。 eval(Sum(Number(1), Number(2))) -> (適用を書き換え) Sum(Number(1), Number(2)) match { case Number(n) => n case Sum(e1, e2) => eval(e1) + eval(e2) } -> (パターンマッチを書き換え) eval(Number(1)) + eval(Number(2)) -> (最初の適用を書き換え) Number(1) match { case Number(n) => n case Sum(e1, e2) => eval(e1) + eval(e2) } + eval(Number(2)) -> (パターンマッチを書き換え) 1 + eval(Number(2)) ->∗ 1 + 2 -> 3 #co(){ Pattern Matching and Methods. In the previous example, we have used pattern matching in a function which was defined outside the class hierarchy over which it matches. Of course, it is also possible to define a pattern matching function in that class hierarchy itself. For instance, we could have defined eval is a method of the base class Expr, and still have used pattern matching in its implementation: } &b(){パターンマッチングとメソッド } 前の例では、パターンマッチングを、マッチするクラス階層の外で定義された関数で使用しました。もちろん、そのクラス階層自身の中でもパターンマッチングを定義できます。たとえば eval を基底クラス Expr のメソッドとして定義しても、パターンマッチングをその実装で使えます。 abstract class Expr { def eval: Int = this match { case Number(n) => n case Sum(e1, e2) => e1.eval + e2.eval } } #co(){ Exercise 7.2.2 Consider the following definitions representing trees of integers. These definitions can be seen as an alternative representation of IntSet: } &b(){演習 7.2.2 } 整数の木を表現する次の定義について考えなさい。この定義は IntSet の別表現とみることもできます。 abstract class IntTree case object EmptyTree extends IntTree case class Node(elem: Int, left: IntTree, right: IntTree) extends IntTree #co(){ Complete the following implementations of function contains and insert for IntTree's. } 次の IntTree の関数 contains と insert の実装を完成させなさい。 def contains(t: IntTree, v: Int): Boolean = t match { ... ... } def insert(t: IntTree, v: Int): IntTree = t match { ... ... } #co(){ Pattern Matching Anonymous Functions. So far, case-expressions always appeared in conjunction with a match operation. But it is also possible to use case-expressions by themselves. A block of case-expressions such as } &b(){パターンマッチング無名関数 } ここまでケース式は常に match 操作と一緒に現れました。しかしケース式だけでも使用できます。次のようなケース式ブロック { case P1 => E1 ... case Pn => En } #co(){{ is seen by itself as a function which matches its arguments against the patterns P1 , . . . , Pn , and produces the result of one of E1 , . . . , En . (If no pattern matches, the function would throw a MatchError exception instead). In other words, the expression above is seen as a shorthand for the anonymous function (x => x match { case P1 => E1 ... case Pn => En }) where x is a fresh variable which is not used otherwise in the expression. }} は、それ自身が引数をパターン P1,...,Pn にマッチさせ、E1,...,En のどれか一つの結果を生み出す関数 (もしどのパターンにもマッチしなければ、関数は代わりに MatchError 例外を投げます) 、と見ることもできます。別の言い方をすれば、上の式は、無名関数 (x => x match { case P1 => E1 ... case Pn => En }) の短縮形、ただし x は式の中で他には使われていない新規の変数、と見ることができます。 #center(){[[前ページ>Example7.1]] [[ 7 章>ExampleChap7]] [[目次>ScalaByExample和訳]] [[次ページ>Chapter 8 Generic Types and Methods]]} ---- #comment
#co(){ 7.2 Pattern Matching Pattern matching is a generalization of C or Java's switch statement to class hierarchies. Instead of a switch statement, there is a standard method match, which is defined in Scala's root class Any, and therefore is available for all objects. The match method takes as argument a number of cases. For instance, here is an implementation of eval using pattern matching. } #setmenu2(ex-r-menu) ** 7.2 パターンマッチング (Pattern Matching) パターンマッチングは C や Java の switch 文をクラス階層に一般化したものです。switch 文の代わりに標準メソッド match があり、それは Scala のルートクラス Any で定義されていて、したがって全てのオブジェクトで使用できます。match メソッドは引数として複数のケースを取ります。たとえば、次はパターンマッチングを用いた eval の実装です。 def eval(e: Expr): Int = e match { case Number(n) => n case Sum(l, r) => eval(l) + eval(r) } #co(){ In this example, there are two cases. Each case associates a pattern with an expression. Patterns are matched against the selector values e. The first pattern in our example, Number(n), matches all values of the form Number(v), where v is an arbitrary value. In that case, the pattern variable n is bound to the value v. Similarly, the pattern Sum(l, r) matches all selector values of form Sum(v1 , v2 ) and binds the pattern variables l and r to v1 and v2 , respectively. } この例では,2つのケースがあります。各ケースはパターンと式を関連付けます。パターンはセレクタ値 e に対してマッチされます。この例の最初のパターンでは、Number(n) は形式 Number(v)、ただし v は任意の値、のすべての値にマッチします。この場合、&bold(){パターン変数} n は値 v に束縛されます。同様に、パターン Sum(l,r) は形式 Sum(v1,v2) のすべてのセレクタ値にマッチし、パターン変数 l と r を v1 と v2 へそれぞれ束縛します。 #co(){ In general, patterns are built from - Case class constructors, e.g. Number, Sum, whose arguments are again patterns, - pattern variables, e.g. n, e1, e2, - the "wildcard" pattern _, - literals, e.g. 1, true, "abc", - constant identifiers, e.g. MAXINT, EmptySet. } 一般的に、パターンは次項より構成されます - ケースクラスのコンストラクタ、たとえば Number, Sum などであり、その引数もまたパターン - パターン変数、たとえば n, e1, e2 - 「ワイルドカード」パターン _ - リテラル、たとえば 1, true, "abc" - 定数識別子、たとえば MAXINT, EmptySet #co(){ Pattern variables always start with a lower-case letter, so that they can be distinguished from constant identifiers, which start with an upper case letter. Each variable name may occur only once in a pattern. For instance, Sum(x, x) would be illegal as a pattern, since the pattern variable x occurs twice in it. } パターン変数は常に小文字で始まりますが、それは大文字で始まる定数識別子と区別するためです。各変数名は一つのパターンに1回だけ登場できます。たとえば Sum(x, x) は正しくないパターンですが、それはパターン変数 x が2回登場するからです。 #co(){ Meaning of Pattern Matching. A pattern matching expression } &b(){パターンマッチングの意味 } パターンマッチング式 e match { case p1 => e1 ... case pn => en } #co(){ matches the patterns p 1 , . . . , p n in the order they are written against the selector value e. -A constructor pattern C (p1 , . . . , pn ) matches all values that are of type C (or a subtype thereof ) and that have been constructed with C-arguments matching patterns p1 , . . . , pn . - A variable pattern x matches any value and binds the variable name to that value. - The wildcard pattern '_' matches any value but does not bind a name to that value. - A constant pattern C matches a value which is equal (in terms of ==) to C.} は、パターン p1,...pn に、書かれた順番で、セレクタ値 e に対してマッチします。 - コンストラクタパターン C(p1,...,p2) は型 C (あるいはそのサブタイプ) であり、パターン p1,...pn にマッチする、C の引数で生成されるすべての値でマッチします。 - 変数パターン x は任意の値にマッチし、変数名をその値に束縛します。 - ワイルドカードパターン '_' は任意の値にマッチしますが、名前をその値に束縛しません。 - 定数パターン C は C と (==の意味で) 等しい値にマッチします。 #co(){ The pattern matching expression rewrites to the right-hand-side of the first case whose pattern matches the selector value. References to pattern variables are replaced by corresponding constructor arguments. If none of the patterns matches, the pattern matching expression is aborted with a MatchError exception. } パターンマッチング式は、セレクタ値が最初にマッチするパターンの、ケースの右辺へと書き換えられます。パターン変数への参照は、対応するコンストラクタ引数で置き換えられます。もしどのパターンにもマッチしなければ、パターンマッチ式は MatchError 例外でアボートされます。 #co(){ Example 7.2.1 Our substitution model of program evaluation extends quite naturally to pattern matching, For instance, here is how eval applied to a simple expression is re-written: -> (by rewriting the application) -> (by rewriting the pattern match) -> (by rewriting the first application) -> (by rewriting the pattern match) } &b(){Example 7.2.1 } プログラム評価の置き換えモデルはきわめて自然にパターンマッチングへ拡張できます。たとえば次は、簡単な式に適用された eval がどの様に書き換えるかを示します。 eval(Sum(Number(1), Number(2))) -> (適用を書き換え) Sum(Number(1), Number(2)) match { case Number(n) => n case Sum(e1, e2) => eval(e1) + eval(e2) } -> (パターンマッチを書き換え) eval(Number(1)) + eval(Number(2)) -> (最初の適用を書き換え) Number(1) match { case Number(n) => n case Sum(e1, e2) => eval(e1) + eval(e2) } + eval(Number(2)) -> (パターンマッチを書き換え) 1 + eval(Number(2)) ->∗ 1 + 2 -> 3 #co(){ Pattern Matching and Methods. In the previous example, we have used pattern matching in a function which was defined outside the class hierarchy over which it matches. Of course, it is also possible to define a pattern matching function in that class hierarchy itself. For instance, we could have defined eval is a method of the base class Expr, and still have used pattern matching in its implementation: } &b(){パターンマッチングとメソッド } 前の例では、パターンマッチングを、マッチするクラス階層の外で定義された関数で使用しました。もちろん、そのクラス階層自身の中でもパターンマッチングを定義できます。たとえば eval を基底クラス Expr のメソッドとして定義しても、パターンマッチングをその実装で使えます。 abstract class Expr { def eval: Int = this match { case Number(n) => n case Sum(e1, e2) => e1.eval + e2.eval } } #co(){ Exercise 7.2.2 Consider the following definitions representing trees of integers. These definitions can be seen as an alternative representation of IntSet: } &b(){演習 7.2.2 } 整数の木を表現する次の定義について考えなさい。この定義は IntSet の別表現とみることもできます。 abstract class IntTree case object EmptyTree extends IntTree case class Node(elem: Int, left: IntTree, right: IntTree) extends IntTree #co(){ Complete the following implementations of function contains and insert for IntTree's. } 次の IntTree の関数 contains と insert の実装を完成させなさい。 def contains(t: IntTree, v: Int): Boolean = t match { ... ... } def insert(t: IntTree, v: Int): IntTree = t match { ... ... } #co(){ Pattern Matching Anonymous Functions. So far, case-expressions always appeared in conjunction with a match operation. But it is also possible to use case-expressions by themselves. A block of case-expressions such as } &b(){パターンマッチング無名関数 } ここまでケース式は常に match 操作と一緒に表れました。しかしケース式だけでも使用できます。次のようなケース式ブロック { case P1 => E1 ... case Pn => En } #co(){{ is seen by itself as a function which matches its arguments against the patterns P1 , . . . , Pn , and produces the result of one of E1 , . . . , En . (If no pattern matches, the function would throw a MatchError exception instead). In other words, the expression above is seen as a shorthand for the anonymous function (x => x match { case P1 => E1 ... case Pn => En }) where x is a fresh variable which is not used otherwise in the expression. }} は、それ自身が引数をパターン P1,...Pn にマッチさせ、E1,...,En のどれか一つの結果を生み出す関数 (もしどのパターンにもマッチしなければ、関数は代わりに MatchError 例外を投げます) 、と見ることもできます。別の言い方をすれば、上の式は、無名関数 (x => x match { case P1 => E1 ... case Pn => En }) の短縮形、ただし x は式の中で他には使われていない新規の変数、と見ることができます。 #center(){[[前ページ>Example7.1]] [[ 7 章>ExampleChap7]] [[目次>ScalaByExample和訳]] [[次ページ>Chapter 8 Generic Types and Methods]]} ---- #comment

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。