Spec2.8Chap8b

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

8.2 型パターン (Type Patterns)

構文:

   TypePat     ::= Type

Type patterns consist of types, type variables, and wildcards . A type pattern T is of one of the following forms:

型パターンは、型、型変数、ワイルドカードからなります。 型パターン T は、次の形の 1 つをとります。:

・ A reference to a class C , p.C , or T#C . This type pattern matches any non-null instance of the given class . Note that the prefix of the class, if it is given, is relevant for determining class instances . For instance, the pattern p.C matches only instances of classes C which were created with the path p as prefix .

The bottom types scala.Nothing and scala.Null cannot be used as type patterns , because they would match nothing in any case .

・ クラス C、p.C、あるいは T#C への参照。 この型パターンは、与えられたクラスの任意の非 null インスタンスとマッチします。 クラスの前置子は、もしそれが与えられていれば、 クラスインスタンスの決定に関係があるあることに注意してください。 例えばパターン p.C は、 パス p を前置子として生成されたクラス C のインスタンスとのみマッチします。

最下位の型 scala.Nothing と scala.Null は型パターンとして使用できません。 なぜなら、それらは如何なる場合も何ともマッチしないからです。

・ A singleton type p.type . This type pattern matches only the value denoted by the path p (that is, a pattern match involved a comparison of the matched value with p using method eq in class AnyRef) .

・ A compound type pattern T1 with ... with Tn where each Ti is a type pattern . This type pattern matches all values that are matched by each of the type patterns Ti .

・ シングルトン型 p.type。 この型パターンは、パス p で示される値とだけマッチします (すなわち、クラス AnyRef 中の eq メソッドを使っての、 p とマッチされた値との比較を含むパターンマッチ) 。

・ 複合型パターン T1 with ... with Tn。ここで、各 Ti は型パターン。 この型パターンは、各型パターン Ti がマッチするすべての値とマッチします。

・ A parameterized type pattern T[a1,...,an], where the ai are type variable patterns or wildcards _. This type pattern matches all values which match T for some arbitrary instantiation of the type variables and wildcards . The bounds or alias type of these type variable are determined as described in (§8.3) .

・ パラメータ化された型パターン T[a1,...,an]。ここで ai は型変数パターンあるいはワイルドカード _ 。 この型パターンは、 型変数とワイルドカードの何らかの任意のインスタンス化について T にマッチする、 すべての値とマッチします。 これら型変数の境界あるいはエイリアス型は、 (§8.3)の記述に従って決定されます。

・ A parameterized type pattern scala.Array[T1], where T1 is a type pattern . This type pattern matches any non-null instance of type scala.Array[U1], where U1 is a type matched by T1 .

・ パラメータ化された型パターン scala.Array[T1]。 ただしここで T1 は 1 つの型パターン。 この型パターンは、型が scala.Array[U1] である任意の非 null インスタンスにマッチします。 ここで U1 は T1 とマッチする型です。

Types which are not of one of the forms described above are also accepted as type patterns . However, such type patterns will be translated to their erasure (§3.7). The Scala compiler will issue an "unchecked" warning for these patterns to flag the possible loss of type-safety .

上述した形の 1 つではないものも、型パターンとして受け入れられます。 しかし、そのような型パターンは、 それらの型消去(§3.7)に変換されます。 Scala コンパイラは、これらのパターンが型安全でない可能性を合図する 「unchecked」という警告を発します。

A type variable pattern is a simple identifier which starts with a lower case letter . However, the predefined primitive type aliases unit, boolean, byte, short, char, int, long, float, and double are not classified as type variable patterns .

型変数パターン(type variable pattern) は小文字で始まる単純な識別子です。 しかし、事前定義されたプリミティブな型エイリアス unit、boolean、byte、 short、char、int、float、double は、型変数パターン に分類されません。



8.3 パターン中の型パラメータ推論 (Type Parameter Inference in Patterns)

Type parameter inference is the process of finding bounds for the bound type variables in a typed pattern or constructor pattern . Inference takes into account the expected type of the pattern .

型パラメータ推論は、型付きパターン あるいはコンストラクタパターン中の束縛された型変数の境界を見つけるプロセスです。 推論は、パターンの要請型を計算に入れます。


型付きパターンの型パラメータ推論 (Type parameter inference for typed patterns..)

Assume a typed pattern p : T´ . Let T result from T´ , where all wildcards in T´ are renamed to fresh variable names . Let a1,...,an be the type variables in T . These type variables are considered bound in the pattern . Let the expected type of the pattern be pt .

型付きパターン p : T´を仮定します。 T を、 T´中のすべてのワイルドカードを新規の変数名へリネームして得られたものとします。 a1,...,an を T 中の型変数とします。 これらの型変数は、パターン中で束縛されていると考えられます。 パターンの要請型を pt とします。

Type parameter inference constructs first a set of subtype constraints over the type variables ai . The initial constraints set CC0 reflects just the bounds of these type variables . That is, assuming T has bound type variables a1,...,an which correspond to class type parameters a´1,...,a´n with lower bounds L1,...,Ln and upper bounds U1,...,Un , CC0 contains the constraints

型パラメータ推論は最初に、型変数 ai 上のサブ型制約の集合を構築します。 最初の制約集合 CC0 は、それら型変数の境界そのものの反映です。 すなわち、T が束縛された型変数 a1,...,an をもつと仮定します。 ただしここで a1,...,an は、下限境界 L1,...,Ln と上限境界 U1,...,Un をもつクラス型パラメータ a´1,...,a´n に対応するものであり、 CC0 は次の制約を含みます。

       ai      <: σUi     (i = 1,...,n)
       σLi    <: ai       (i = 1,...,n)

ここで σ は置換 [a´1: = a1,...,a´n := an] です。

The set CC0 is then augmented by further subtype constraints . There are two cases .

このとき集合 CC0 は、さらなるサブ型制約によって大きくなります。 次の 2 つの場合があります。


Case 1:

If there exists a substitution over the type variables ai,...,an such that σT conforms to pt, one determines the weakest subtype constraints CC1 over the type variables a1,...,an such that CC0∧CC1 implies that T conforms to pt .

もし σT が pt に適合するような型変数 ai,...,an 上の置換が存在するなら、 CC0∧CC1 が T の pt への適合を意味するような、 型変数 a1,...,an 上の最も弱いサブ型制約 CC1 を決定します。


Case 2:

Otherwise, if T can not be made to conform to pt by instantiating its type variables, one determines all type variables in pt which are defined as type parameters of a method enclosing the pattern . Let the set of such type parameters be b1,...,bm .

そうでなければ、もし T の型変数のインスタンス化で T を pt に適合させることができないなら、 パターンを囲むメソッドの型パラメータとして定義された、 pt 中のすべての型変数を決定します。 そのような型パラメータのセットを b1,...,bm とします。

Let CC´0 be the subtype constraints reflecting the bounds of the type variables bi . If T denotes an instance type of a final class, let CC2 be the weakest set of subtype constraints over the type variables a1,...,an and b1,...,bm such that CC0∧CC´0∧CC2 implies that T conforms to pt .

CC´0 を型変数 bi の境界を反映するサブ型制約とします。 もし T が final クラスのインスタンス型を表すなら、CC2 を、CC0∧CC´0∧CC2 が T の pt への適合を意味するような、型変数 a1,...,an と b1,...,bm 上のサブ型制約の最も弱い集合とします。

If T does not denote an instance type of a final class, let CC2 be the weakest set of subtype constraints over the type variables a1,...,an and b1,...,bm such that CC0∧CC´0∧CC2 implies that it is possible to construct a type T´ which conforms to both T and pt . It is a static error if there is no satisfiable set of constraints CC2 with this property . The final step consists in choosing type bounds for the type variables which imply the established constraint system . The process is different for the two cases above.

もし T が final クラスのインスタンス型を表さないなら、CC2 を、 CC0∧CC´0∧CC2 が T と pt の両方に適合する型 T´ の構成可能性を意味するような、型変数 a1,...,an と b1,...,bm 上のサブ型制約の最も弱い集合とします。 もしこの属性をもつ制約 CC2 の集合がないなら、静的エラーです。

The final step consists in choosing type bounds for the type variables which imply the established constraint system. The process is different for the two cases above.

最後のステップは型変数の型境界を選ぶことであり、 制約システムの確定を意味します。そのプロセスは、上記 2 つの場合で異なります。


Case 1:

We take ai >: Li <: Ui , where each Li is minimal and each Ui is maximal wrt <: such that ai >: Li <: Ui for i = 1,...,n implies CC0∧CC1 .

我々は ai >: Li <: Ui を得ます。ここで i = 1,...,n に対して ai >: Li <: Ui が CC0∧CC1 を意味するような、<: に関して各 Li は最小、 各 Ui は最大のものです。


Case 2:

We take ai >: Li <: Ui and bi >: L´i <: U´i , where each Li and L´j is minimal and each Ui and U´j is maximal such that ai >: Li <: Ui for i = 1,...,n and bj >: L´j <: U´j for j = 1,...,m implies CC0∧CC´0∧CC2 .

我々は ai >: Li <: Ui と bi >: L´i <: U´i を得ます。ここで i = 1,...,n、 j = 1,...m に対して ai >: Li <: Ui と bj >: L´j <: U´j が CC0∧CC´0∧CC2 を意味するような、各 Li と L´j は最小、各 Ui と U´j は最大のものです。

In both cases, local type inference is permitted to limit the complexity of inferred bounds . Minimality and maximality of types have to be understood relative to the set of types of acceptable complexity .

どちらの場合も、ローカルな型推論は、 推論される境界の複雑さを制限することが許されます。 型の最小性と最大性は、 型集合の受け入れ可能な複雑さと比較して解釈されなければなりません。


コンストラクタパターンの型パラメータ推論 (Type parameter inference for constructor patterns..)

Assume a constructor pattern C(p1,...,pn) , where class C has type type parameters a1,...,an . These type parameters are inferred in the same way as for the typed pattern (_: C[a1,...,an]).

コンストラクタパターン C(p1,...,pn) を仮定します。ここで、クラス C は、 型パラメータ a1,...,an を持つとします。 これらの型パラメータは、型付きパターン (_: C[a1,...,an]) と同じ方法で推論されます。


Example 8.3.1 次のプログラム断片について考えます。:

   val x: Any
   x match {
     case y: List[a] => ...
   }

Here, the type pattern List[a] is matched against the expected type Any . The pattern binds the type variable a . Since List[a] conforms to Any for every type argument , there are no constraints on a . Hence, a is introduced as an abstract type with no bounds . The scope of a is right-hand side of its case clause .

On the other hand, if x is declared as

ここで、型パターン List[a] は、要請型 Any に対してマッチされます。 パターンは型変数 a を束縛します。 List[a] はすべての型引数に対して Any に適合するので、a 上に何も制約がありません。 ですから、a は境界をもたない抽象型として導入されます。 a のスコープは、そのケース節の右側です。

他方、もし x が次のように宣言されれば

   val x: List[List[String]],

this generates the constraint List[a] <: List[List[String]], which simplifies to a <: List[String], because List is covariant . Hence, a is introduced with upper bound List[String] .

これは 制約 List[a] <: List[List[String]] を生み出し、List が共変なので a <: List[String] へ単純化されます。 ですから、a は上限境界 List[String] をもって導入されます。


Example 8.3.2 次のプログラム断片について考えます。:

   val x: Any
   x match {
     case y: List[String] => ...
   }

Scala does not maintain information about type arguments at run-time, so there is no way to check that x is a list of strings . Instead, the Scala compiler will erase (§3.7) the pattern to List[_]; that is, it will only test whether the top-level runtime-class of the value x conforms to List, and the pattern match will succeed if it does . This might lead to a class cast exception later on, in the case where the list x contains elements other than strings . The Scala compiler will flag this potential loss of typesafety with an "unchecked" warning message .

Scala は型引数の情報を実行時に保持しません。 ですから x が文字列のリストであることをチェックする方法がありません。 その代わりに、Scala コンパイラはパターンを List[_] に型消去 (§3.7)します。; つまり、値 x のトップレベルの実行時クラスが List に適合するかテストするだけです。 そしてもしそうなら、パターンマッチングは成功します。 これは、リスト x が文字列以外の要素を含む場合に、 後でクラスキャスト例外を発生させるかもしれません。 Scala コンパイラは、「unchecked」というメッセージで、 型安全でない可能性を合図します。


Example 8.3.3 次のプログラム断片について考えます。

   class Term[A]
   class Number(val n: Int) extends Term[Int]
   def f[B](t: Term[B]): B = t match {
     case y: Number => y.n
   }

The expected type of the pattern y: Number is Term[B]. The type Number does not conform to Term[B]; hence Case 2 of the rules above applies .

パターン y: Number の要請型は Term[B] です。 型 Number は Term[B] に適合しません。;ですから、上記規則の Case 2 が 適用されます。

This means that b is treated as another type variable for which subtype constraints are inferred . In our case the applicable constraint is Number <: Term[B], which entails B = Int . Hence, B is treated in the case clause as an abstract type with lower and upper bound Int . Therefore, the right hand side of the case clause, y.n, of type Int, is found to conform to the function's declared result type, Number .

このことは b が、 そのサブ型制約が推論された他の型変数として扱われることを意味します。 この場合、適用可能な制約は Number <: Term[B] です。 ここで B = Int が引き起こされます。ですから、 B は、ケース節で上・下限境界 Int をもつ抽象型として扱われます。 したがって、ケース節の右側 y.n は型 Int をもち、 関数の宣言された結果型 Number に適合することが判明します。 (訳注: Numberは B の誤記?)



8.4 パターンマッチ式 (Pattern Matching Expressions)

構文:

   Expr            ::=    PostfixExpr 'match' '{' CaseClauses '}'
   CaseClauses     ::=    CaseClause {CaseClause}
   CaseClause      ::=    'case' Pattern [Guard] '=>' Block

パターンマッチ式

 e match { case p1 => b1 ... case pn => bn }

consists of a selector expression e and a number n > 0 of cases . Each case consists of a (possibly guarded) pattern pi and a block bi . Each pi might be complemented by a guard if e , where e is a boolean expression . The scope of the pattern variables in pi comprises the pattern's guard and the corresponding block bi .

は、セレクター式 e と n 個(>0)の ケースからなります。 各ケースは、(ガードがあってもよい) パターン pi とブロック bi からなります。 各 pi には、ガード if e が補完されていても構いません。 ここで e は boolean 式です。 pi 中のパターン変数のスコープは、 パターンのガードと対応するブロック bi から構成されます。

Let T be the type of the selector expression e and let a1,...,am be the type parameters of all methods enclosing the pattern matching expression . For every ai , let Li be its lower bound and Ui be its higher bound . Every pattern p ∈ {p1 ,,...,pn} can be typed in two ways .

セレクター式 e の型を T 、 パターンマッチ式を囲むすべてのメソッドの型パラメータを a1,...,am とします。 各 ai に対し、Li をその下限境界、Ui をそのより高い境界 (higher bound)とします。 各パターン p ∈ {p1 ,,...,pn} は、次の 2 つの方法で型付けされます。

First, it is attempted to type p with T as its expected type . If this fails, p is instead typed with a modified expected type T´ which results from T by replacing every occurrence of a type parameter ai by undefined . If this second step fails also, a compile-time error results . If the second step succeeds, let Tp be the type of pattern p seen as an expression .One then determines minimal bounds L´1,...,L´m and maximal bounds U´1,...,U´m such that for all i , Li <: L´i and U´i <: Ui and the following constraint system is satisfied:

最初に、その要請型である T で p の型付けを試みます。 もしそれが失敗するなら、T の代わりに、T 中の型パラメータ ai のすべての出現を 未定義 で置き換えて得られる、 修正された要請型 T´ で p を型付けします。 もしこの 2 つめのステップも失敗するなら、実行時エラーとなります。 もし 2 つめのステップが成功したなら、式として見たパターン p の型を Tp とします。 このとき、最小の境界 L´1,...,L´m と最大の境界 U´1,...,U´m を、 各 i に対し Li <: L´i かつ U´i <: Ui、 そして次の制約システムが満たされるようなものとして決定します。

   L1 <: a1 <: U1∧ ...∧ Lm <: am <: Um => Tp <: T

If no such bounds can be found, a compile time error results . If such bounds are found, the pattern matching clause starting with p is then typed under the assumption that each ai has lower bound L´i instead of Li and has upper bound U´i instead of Ui .

もしそのような境界が見つからないなら、実行時エラーとなります。 もしそのような境界が見つかれば、p で始まるパターンマッチ節はこのとき、 各 ai が Li の代わりに下限境界 L´i を持ち、 Ui の代わりに上限境界 U´i を持つという仮定の下で型付けされます。

The expected type of every block bi is the expected type of the whole pattern matching expression . The type of the pattern matching expression is then the weak least upper bound (§3.5.3) of the types of all blocks bi .

どのブロック bi の要請型も、パターンマッチ式全体の要請型です。 パターンマッチ式の型はこのとき、全てのブロック bi の型の、弱い最少の上限境界 (§3.5.3)です。

When applying a pattern matching expression to a selector value, patterns are tried in sequence until one is found which matches the selector value (§8.1). Say this case is case pi ⇨ bi . The result of the whole expression is then the result of evaluating bi , where all pattern variables of pi are bound to the corresponding parts of the selector value . If no matching pattern is found, a scala.MatchError exception is thrown .

パターンマッチ式をセレクター値へ適用するとき、 セレクター値(§8.1) にマッチするものが 1 つ見つかるまで次々にパターンが試みられます。 たとえば、この場合は case pi ⇨ bi です。 式全体の結果はこのとき、bi の評価結果です。ここで pi のすべてのパターン変数は、 セレクター値の対応する部分に束縛されます。 もしマッチするパターンが見つからなければ、scala.MatchError 例外が送出されます。

The pattern in a case may also be followed by a guard suffix if e with a boolean expression e . The guard expression is evaluated if the preceding pattern in the case matches . If the guard expression evaluates to true, the pattern match succeeds as normal . If the guard expression evaluates to false, the pattern in the case is considered not to match and the search for a matching pattern continues .

ケース中のパターンには、boolean 式 e を伴うガード接尾部 if e が続いても構いません。 ガード式は、もしケース中の先行するパターンがマッチするなら、評価されます。 もしガード式が true に評価されるなら、パターンマッチは通常通り成功します。 もしガード式が false に評価されるなら、 ケース中のパターンはマッチしないと考えられ、 マッチするパターンの検索が継続されます。

In the interest of efficiency the evaluation of a pattern matching expression may try patterns in some other order than textual sequence . This might affect evaluation through side effects in guards . However, it is guaranteed that a guard expression is evaluated only if the pattern it guards matches .

効率化のため、パターンマッチ式の評価は原文の並びと いくぶん異なる順序でパターンを試みることがあります。 これはガード中の副作用を通して、評価に影響を与えるかもしれません。 しかし、そのガードするパターンがマッチする場合に限り、 ガード式が評価されることは保証されています。

If the selector of a pattern match is an instance of a sealed class (§5.2), the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchError being raised at run-time .

もしパターンマッチのセレクタが sealed クラス (§5.2)のインスタンスなら、 パターンマッチングのコンパイル時に、 与えられたパターンセットが網羅的ではないと診断する警告が出ます。 すなわち、実行時に MatchError が発生する可能性があるということです。


Example 8.4.1

Consider the following definitions of arithmetic terms:

つぎの算術項の定義を考えてみます。:

   abstract class Term[T]
   case class Lit(x: Int) extends Term[Int]
   case class Succ(t: Term[Int]) extends Term[Int]
   case class IsZero(t: Term[Int]) extends Term[Boolean]
   case class If[T](c: Term[Boolean],
                    t1: Term[T],
                    t2: Term[T]) extends Term[T]

There are terms to represent numeric literals, incrementation, a zero test, and a conditional . Every term carries as a type parameter the type of the expression it representes (either Int or Boolean) . A type-safe evaluator for such terms can be written as follows .

数値リテラル、インクリメント、ゼロテスト、条件を表す項があります。 各項には、型パラメータとして、それが表す式の型 (Int あるいは Boolean) のいずれかが伴っています。そのような項に対する型安全な評価子は、 次のように書けます。

   def eval[T](t: Term[T]): T = t match {
     case Lit(n)        => n
     case Succ(u)       => eval(u) + 1
     case IsZero(u)     => eval(u) == 0
     case If(c, u1, u2) => eval(if (eval(c)) u1 else u2)
   }

Note that the evaluator makes crucial use of the fact that type parameters of enclosing methods can acquire new bounds through pattern matching . For instance, the type of the pattern in the second case, Succ(u), is Int . It conforms to the selector type T only if we assume an upper and lower bound of Int for T . Under the assumption Int <: T <: Int we can also verify that the type right hand side of the second case, Int conforms to its expected type, T .

評価子が、取り囲むメソッドの型パラメータがパターンマッチングを通して 新しい境界を獲得できることを深く利用することに注意してください。 たとえば、2 つめのケース中のパターン Succ(u) の型は Int です。 それは、T に対して Int の上・下限境界を仮定する場合のみ、 セレクタ型 T に適合します。Int <: T <: Int の仮定の下、 2 つめのケースの右側の型 Int が その要請型 T に適合することも確かめることができます。



8.5 パターンマッチング無名関数 (Pattern Matching Anonymous Functions)

構文:

   BlockExpr ::= '{' CaseClauses '}'

無名関数は次のようなケースの並びで定義できます。

   { case p1 => b1 ... case pn => bn }

which appear as an expression without a prior match. The expected type of such an expression must in part be defined. It must be either scala.Functionk[S1,...,Sk, R] for some k > 0, or scala.PartialFunction[S1 , R], where the argument type(s) S1,...,Sk must be fully determined, but the result type R may be undetermined .

If the expected type is scala.Functionk[S1,...,Sk, R] , the expression is taken to be equivalent to the anonymous function:

これは match が前につかずに、式として現われます。 このような式の要請型は、ある程度定義されなければなりません。 それは、ある k > 0 に対して scala.Functionk[S1,...,Sk , R] であるか、 あるいは、scala.PartialFunction[S1, R] でなければなりません。 ここで 引数型 S1,...,Sk は完全に決まっていなければなりませんが、 しかしその結果型 R は未決定でも構いません。

もしその要請型が scala.Functionk[S1,...,Sk, R] なら、 式は次の無名関数に等価とみなされます。

   (x1 : S1,...,xk : Sk) => (x1,...,xk) match {
     case p1 => b1 ... case pn => bn
   }

Here, each xi is a fresh name. As was shown in (§6.23), this anonymous function is in turn equivalent to the following instance creation expression, where T is the weak least upper bound of the types of all bi .

ここで、各 xi は新規の名前です。 (§6.23)で見たように、 この無名関数は今度は、次のインスタンス生成式に等価です。 ここで T は、すべての bi の型の弱い最少の上限境界です。

   new scala.Functionk[S1,...,Sk, T] {
     def apply(x1 : S1,...,xk : Sk): T = (x1,...,xk) match {
       case p1 => b1 ... case pn => bn
     }
   }

If the expected type is scala.PartialFunction[S, R], the expression is taken to be equivalent to the following instance creation expression:

もしその要請型が scala.PartialFunction[S, R] なら、 式は次のインスタンス生成式に等価とみなされます。

   new scala.PartialFunction[S, T] {
       def apply(x : S): T = x match {
         case p1 => b1 ... case pn => bn
       }
       def isDefinedAt(x : S): Boolean = {
         case p1 => true ... case pn => true
         case _ => false
       }
   }

Here, x is a fresh name and T is the weak least upper bound of the types of all bi .The final default case in the isDefinedAt method is omitted if one of the patterns p1,...,pn is already a variable or wildcard pattern .

ここで x は新規の名前、T はすべての bi の型の弱い最少の上限境界です。 isDefinedAt メソッド中の最後のデフォルトケースは、もしパターン p1,...,pn の 1 つがすでに変数あるいはワイルドカードパターンなら、除かれます。


Example 8.5.1 次は、左畳み込み操作 /: を使うメソッドで、 2 つのベクトルのスカラ積を計算します。:

   def scalarProduct(xs: Array[Double], ys: Array[Double]) =
     (0.0 /: (xs zip ys)) {
       case (a, (b, c)) => a + b * c
     }

このコード中のケース節は、次の無名関数に等価です:

   (x, y) => (x, y) match {
     case (a, (b, c)) => a + b * c
   }
最終更新:2011年02月23日 18:38
ツールボックス

下から選んでください:

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