Spec2.8Chap6b

6.10 インスタンス生成式 (Instance Creation Expressions)

構文:

   SimpleExpr        ::=     'new' (ClassTemplate | TemplateBody)

A simple instance creation expression is of the form new c , where c is a constructor invocation (§5.1.1). Let T be the type of c. Then T must denote a (a type instance of) a non-abstract subclass of scala.AnyRef. Furthermore, the concrete self type of the expression must conform to the self type of the class denoted by T (§5.1). The concrete self type is normally T , except if the expression new c appears as the right hand side of a value definition

単純なインスタンス生成式は new c の形をしています。 ここで、c はコンストラクタ呼び出し(constructor invocation §5.1.1)です。 c の型を T とします。 このとき T は、scala.AnyRef の非抽象サブクラス(の型インスタンス) を表さなければなりません。 さらに、式の 具象自己型 は、 T によって表されるクラスの自己型に適合しなくてはなりません (§5.1)。 具象自己型は通常 T です。 ただし、式 new c が値定義の右辺として現われる場合を除きます。

   val x : S = new c

(where the type annotation : S may be missing). In the latter case, the concrete self type of the expression is the compound type T with x.type .

(ここで、型アノテーション :S はないかもしれません) 後者の場合、式の具象自己型は複合型 T with x.type です。

The expression is evaluated by creating a fresh object of type T which is is initialized by evaluating c. The type of the expression is T .

式は、型 T の新しいオブジェクトを生成することで評価され、 そのオブジェクトは c を評価することで初期化されます。 式の型は T です。

一般的なインスタンス生成式は、あるクラステンプレート t (§5.1)については、 new t の形をしています。 そのような式はブロック

   { class a extends t ; new a }

に等価です。ここで a は、ユーザープログラムはアクセスできない 無名クラス の新規の名前です。

構造型(structural types)の値を生成するための略記表現もあります。 もし {D} がクラス本体なら、new {D} は一般的なインスタンス生成式 new AnyRef {D} と同じです。


Example 6.10.1 : 次の構造的なインスタンス生成式について 考えます。:

   new { def getName() = "aaron" }

これは次の一般的なインスタンス生成式の略記表現です。

   new AnyRef{ def getName() = "aaron" }

後者は、今度は次のブロックの略記表現です。

   { class anon$X extends AnyRef{ def getName() = "aaron" }; new anon$X }

ここで anon$X は、ある新規に生成された名前です。



6.11 ブロック (Blocks)

構文:

   BlockExpr   ::=   '{' Block '}'
   Block       ::=   {BlockStat semi} [ResultExpr]

A block expression {s1 ; ...; sn ; e } is constructed from a sequence of block statements s1,...,sn and a final expression e. The statement sequence may not contain two definitions or declarations that bind the same name in the same namespace . The final expression can be omitted, in which case the unit value () is assumed .

ブロック式 {s1 ; ...; sn ; e } は、ブロック文 s1,...,sn の並びと 最後の式 e から構成されます。 文並びは同じ名前空間中で同じ名前を束縛する 2 つの定義/宣言を含んではなりません。 最後の式は省略されることがあり、その場合、unit 値()が想定されます。

The expected type of the final expression e is the expected type of the block. The expected type of all preceding statements is undefined .

最後の式 e の要請型は、ブロックの要請型です。 先行するすべての文の要請型は未定義です。

The type of a block s1 ; ...; sn ; e is T forSome { Q }, where T is the type of e and Q contains existential clauses (§3.2.10) for every value or type name which is free in T and which is defined locally in one of the statements s1,...,sn . We say the existential clause binds the occurrence of the value or type name. Specifically,

ブロック s1 ; ...; sn ; e の型は T forSome { Q } です。 ここで T は e の型であり、Q は、T 中で自由でかつ文 s1,...,sn の 1 つでローカルに定義された、すべての値あるいは型名の存在節 (§3.2.10) を含みます。 我々は、 存在節が値あるいは型名の存在(occurrence)を 束縛 すると言います。 特に、

  • A locally defined type definition type t = T is bound by the existential clause type t >: T <: T . It is an error if t carries type parameters .
  • A locally defined value definition val x : T = e is bound by the existential clause val x : T .
  • A locally defined class definition class c extends t is bound by the existential clause type c <: T , where T is the least class type or refinement type which is a proper supertype of the type c. It is an error if c carries type parameters .
  • A locally defined object definition object x extends t is bound by the existential clause val x : T , where T is the least class type or refinement type which is a proper supertype of the type x.type .
  • ローカルに定義された型定義 type t = T は、存在節 type t >: T <: T によって束縛されます。もし t が型パラメータをもつなら、エラーです。
  • ローカルに定義された値定義 val x : T = e は、存在節 val x : T によって束縛されます。
  • ローカルに定義されたクラス定義 class c extends t は、存在節 type c <: T によって束縛されます。ここで T は、型 c の固有のスーパー型である、最小のクラス型あるいは細別型です。 もし c が型パラメータをもつなら、エラーです。
  • ローカルに定義されたオブジェクト定義 object x extends t は、存在節 val x : T によって束縛されます。ここで T は、型 x.type の固有のスーパー型である、最小のクラス型あるいは細別型です。

Evaluation of the block entails evaluation of its statement sequence, followed by an evaluation of the final expression e, which defines the result of the block .

ブロックの評価は、その文並びの評価と、後に、最後の式 e の評価を必要とし、 式 e の評価はブロックの結果を定義します。


Example 6.11.1 : クラス Ref[T](x: T)を仮定します。ブロック

   { class C extends B {...} ; new Ref(new C) }

は、型 Ref[_1] forSome { type _1 <: B } を持ちます。ブロック

   { class C extends B {...} ; new C }

simply has type B, because with the rules in (§3.2.10 the existentially quantified type _1 forSome { type _1 <: B } can be simplified to B .

は、単なる 型 B をもちます。なぜなら (§3.2.10) 中の規則を用いて、 存在量化された型 _1 forSome { type _1 <: B} は B に簡略化できるからです。



6.12 前置、中置、後置演算 (Prefix, Infix, and Postfix Operations)

構文:

   PostfixExpr    ::=    InfixExpr [id [nl]]
   InfixExpr      ::=    PrefixExpr
                    |    InfixExpr id [nl] InfixExpr
   PrefixExpr     ::=    ['-' | '+' | '!' | '~'] SimpleExpr

式は、オペランドと演算子から構築できます。



6.12.1 前置演算 (Prefix Operations)

A prefix operation op e consists of a prefix operator op, which must be one of the identifiers '+', '-', '!' or '~'. The expression op e is equivalent to the postfix method application e.unary_op .

Prefix operators are different from normal function applications in that their operand expression need not be atomic. For instance, the input sequence -sin(x) is read as -(sin(x)), whereas the function application negate sin(x) would be parsed as the application of the infix operator sin to the operands negate and (x).

前置演算 op e は前置子オペレータ op からなり、それは識別子 '+'、'-'、'!'、'~' の 1 つでなければなりません。 式 op e は、後置メソッド適用 e.unary_op に等価です。

前置演算子は、それらのオペランド式がアトミックである必要がない点で、 通常の関数適用と異なります。 例えば、入力シーケンス -sin(x) は、-(sin(x)) として読まれ、 一方、関数適用 negate sin(x) は、中置演算子 sin の、 オペランド negate(反転) と (x) への適用として構文解析されます。



6.12.2 後置演算 (Postfix Operations)

A postfix operator can be an arbitrary identifier. The postfix operation e op is interpreted as e.op .

後置演算子は任意の識別子です。 後置演算 e op は e.op と解釈されます。



6.12.3 中置演算 (Infix Operations)

An infix operator can be an arbitrary identifier. Infix operators have precedence and associativity defined as follows:

The precedence of an infix operator is determined by the operator's first character . Characters are listed below in increasing order of precedence, with characters on the same line having the same precedence .

中置演算子は任意の識別子です。 中置演算子は次のように定義された優先順位と結合性をもちます。:

中置演算子の 優先順位 は演算子の最初の文字で決まります。 次にリストした文字は、優先順位の増加順で、同じ行の文字は同じ優先順位です。

           (すべての文字(letters))
           |
           ^
           &
           < >
           = !
           :
           + -
           * / %
           (他のすべての特殊文字(special characters))

すなわち、文字で始まる演算子が最も低い優先順位を持ち、次に '|'、 その他が続きます。

There's one exception to this rule, which concerns assignment operators(§6.12.4) . The precedence of an assigment operator is the same as the one of simple assignment (=). That is, it is lower than the precedence of any other operator .

この規則には 1 つの例外があり、 代入演算子 (§6.12.4) に関係しています。 代入演算子の優先順位は、単純な代入(=)のそれと同じです。 すなわち、それは他のすべての演算子の優先順位よりも低いです。

The associativity of an operator is determined by the operator's last character. Operators ending in a colon ':' are right-associative. All other operators are leftassociative .

演算子の 結合性 は演算子の最後の文字によって決まります。 コロン ':' で終わるオペレータは右結合です。 他のすべての演算子は左結合です。

Precedence and associativity of operators determine the grouping of parts of an expression as follows .

  • If there are several infix operations in an expression, then operators with higher precedence bind more closely than operators with lower precedence .
  • If there are consecutive infix operations e0 op1 e1 op2 ... opn en with operators op1,...,opn of the same precedence, then all these operators must have the same associativity. If all operators are left-associative, the sequence is interpreted as (... (e0 op1 e1) op2 ...) opn en . Otherwise, if all operators are rightassociative , the sequence is interpreted as e0 op1 (e1 op2 (... opn en) ...) .
  • postfix operators always have lower precedence than infix operators. E.g . e1 op1 e2 op2 is always equivalent to (e1 op1 e2) op2 .

演算子の優先順位と結合性は、次のように式の一部をグループ化します。

  • もし1つの式の中に複数の中置演算があるなら、より高い優先順位の演算子が、より低い優先順位の演算子よりもより強く結びつきます。
  • もし、同じ優先順位の演算子 op1,...,opn をもつ 連続した中置演算 e0 op1 e1 op2 ... opn en があるなら、すべての演算子は同じ結合性を持たなくてはなりません。もしすべての演算子が左結合なら、その連続は、(...(e0 op1 e1)op2 ...) opn en と解釈されます。そうでなく、もしすべての演算子が右結合なら、その連続は、e0 op1(e1 op2(... opn en)...)と解釈されます。
  • 後置演算子は常に、中置演算子より低い優先順位を持ちます。たとえば、e1 op1 e2 op2 は常に、(e1 op1 e2)op2 に等価です。

The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op (e1,...,en). This expression is then interpreted as e.op(e1,...,en) .

A left-associative binary operation e1 op e2 is interpreted as e1.op(e2). If op is rightassociative , the same operation is interpreted as { val x =e1 ; e2.op(x) }, where x is a fresh name .

左結合演算子の右オペランドは、 丸括弧で囲まれる複数の引数からできていても構いません。 たとえば、e op (e1,...,en)。 この式は e.op(e1,...,en)と解釈されます。

左結合バイナリ演算 e1 op e2 は、e1.op(e2) と解釈されます。 もし op が 右結合なら、同じオペレーションは { val x =e1 ; e2.op(x) } と解釈されます。ここで x は新規の名前です。



6.12.4 代入演算子 (Assignment Operators)

An assignment operator is an operator symbol (syntax category op in (§1.1)) that ends in an equals character "=", with the exception of operators for which one of the following conditions holds:
(1) the operator also starts with an equals character, or
(2) the operator is one of (<=), (>=), (!=) .

代入演算子は、末尾が等号文字「=」になっている演算子シンボル ((§1.1)中の構文カテゴリ op) であり、 次の条件の 1 つを満たす、演算子の例外があります。:
(1) 演算子の始まりも等号文字である。あるいは、
(2) 演算子が (<=)、(>=)、(!=)のうちの1つ。

Assignment operators are treated specially in that they can be expanded to assignments if no other interpretation is valid .

代入演算子は、もし他のどのような解釈も有効でないなら、 それらは代入に拡張されるという点で、特別に扱われます。

中置演算 l += r 中の += のような代入演算子について考えてみましょう。 ここで l、r は式です。 このオペレーションは、代入に対応するオペレーション

   l = l + r

として、オペレーションの左辺 l がただ 1 度だけ評価されることを除き、 再解釈されます。 。

The re-interpretation occurs if the following two conditions are fulfilled .

  1. The left-hand-side l does not have a member named +=, and also cannot be converted by an implicit conversion (§6.26) to a value with a member named += .
  2. The assignment l = l + r is type-correct. In particular this implies that l refers to a variable or object that can be assigned to, and that is convertible to a value with a member named + .

もし次の 2 つの条件がフルに満たされるなら、再解釈が起きます。

  1. 左辺 l が += という名前のメンバーを持たず、暗黙の変換 (§6.26) によって += という名前のメンバーを用いて値へ変換できない。
  2. 代入 l = l + r が型的に正しい。特に、このことは l が、それへの代入が可能な変数/オブジェクトを参照し、+ という名前のメンバーを用いて値に変換できることを意味します。



6.13 型付けされた式 (Typed Expressions)

構文:

   Expr1          ::=    PostfixExpr ':' CompoundType

The typed expression e : T has type T . The type of expression e is expected to conform to T . The result of the expression is the value of e converted to type T .

型付けされた式 e : T は型 T を持ちます。 式 e の型は T に適合することが要請されます。 式の結果は、型 T に変換された e の値です。


Example 6.13.1 : 次は、正しく型付けされた式と、不正に型付けされた 式の例です。

   1: Int                    // 正しい、Int 型
   1: Long                   // 正しい、Long 型
   // 1: string              // ***** 不正



6.14 アノテーション(注釈)付きの式 (Annotated Expressions)

構文:

   Expr1            ::=    PostfixExpr ':' Annotation {Annotation}

An annotated expression e : @a1 ... @an attaches annotations a1,...,an to the expression e (§11) .

アノテーション付きの式 e : @a1 ...@an は、アノテーション a1,...,an を式 e へ加えます(§11)。



6.15 代入 (Assignments)

構文:

   Expr1         ::=   [SimpleExpr '.'] id '=' Expr
                   |   SimpleExpr1 ArgumentExprs '=' Expr

The interpretation of an assignment to a simple variable x = e depends on the definition of x. If x denotes a mutable variable, then the assignment changes the current value of x to be the result of evaluating the expression e. The type of e is expected to conform to the type of x. If x is a parameterless function defined in some template, and the same template contains a setter function x_= as member, then the assignment x = e is interpreted as the invocation x_=(e) of that setter function. Analogously, an assignment f.x = e to a parameterless function x is interpreted as the invocation f.x_=(e) .

単純変数への代入 x = e の解釈は、x の定義に依存します。 もし x がミュータブル変数を表すなら、 代入は x の現在の値を式 e の評価結果に変えます。 e の型は、x の型に適合することが要請されます。 もし x があるテンプレート中で定義されたパラメータなしの関数で、 同じテンプレートがメンバーとしてセッター関数 x_= を含むなら、 代入 x = e はそのセッター関数の呼び出し x_=(e)と解釈されます。 同様に、パラメータなしの関数 x への代入 f.x = e は、呼び出し f.x_=(e) と解釈されます。

An assignment f(args) = e with a function application to the left of the '=' operator is interpreted as f.update(args, e), i.e. the invocation of an update function defined by f .

'=' 演算子の左辺への関数適用をもつ代入 f(args) = e は、f.update(args,e)、 すなわち、f で定義された update 関数の呼び出しと解釈されます。


Example 6.15.1 : 次は、行列乗算の通常の命令型コードです。

   def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
     val zss: Array[Array[Double]] = new Array(xss.length, yss(0).length)
     var i = 0
     while (i < xss.length) {
       var j = 0
       while (j < yss(0).length) {
         var acc = 0.0
         var k = 0
         while (k < yss.length) {
           acc = acc + xss(i)(k) * yss(k)(j)
           k += 1
         }
         zss(i)(j) = acc
         j += 1
       }
       i += 1
     }
     zss
   }

配列のアクセスと代入の糖衣を取り除くと、次の展開バージョンを得ます。:

   def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
     val zss: Array[Array[Double]] = new Array(xss.length, yss.apply(0).length)
     var i = 0
     while (i < xss.length) {
       var j = 0
       while (j < yss.apply(0).length) {
         var acc = 0.0
         var k = 0
         while (k < yss.length) {
           acc = acc + xss.apply(i).apply(k) * yss.apply(k).apply(j)
           k += 1
         }
         zss.apply(i).update(j, acc)
         j += 1
       }
       i += 1
     }
     zss
   }

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2011年02月23日 18:35
ツールボックス

下から選んでください:

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