C is created for a concrete class C, provided the class does not have already a companion, and there is also no other value or method named C defined or inherited in the scope where C is defined. 2. Constructor proxy apply methods are generated for a concrete class provided a. the class has a companion object (which might have been generated in step 1), and b. that companion object does not already define a member named apply. --------------------------------------------------------------------------------------------------- 1. コンパニオンオブジェクトを持っておらず、かつそのクラスと同名の値やメソッドがスコープ内になければ、Constructor Proxy のコンパニオンオブジェクトが生成される 2. Constructor Proxy の apply メソッドは、以下を満たす具象クラスに対して生成される: a. クラスがコンパニオンオブジェクト (1 で生成されたものを含む) を持っており、かつ b. コンパニオンオブジェクトが apply という名前のメンバーを定義していないこと
メソッドが生成される class CHaveConstructorProxies(v: Int): def hello = println("CHaveConstructorProxies class have constructor proxies (companion and apply)") // apply メソッドが生成される class CHaveConstructorProxy(v: Int): def hello = println("CHaveConstructorProxy class have a constructor proxy (apply)") object CHaveConstructorProxy: def zero = CHaveConstructorProxy(0) scala> CHaveConstructorProxies(3).hello CHaveConstructorProxies class have constructor proxies (companion and apply) scala> CHaveConstructorProxy(3).hello CHaveConstructorProxy class have a constructor proxy (apply)
◦ getter, equals, toString 等は使えない scala> val cp = ConstructorProxy("abc") val cp: ConstructorProxy = ConstructorProxy@34073423 scala> cp.s 1 |cp.s |^^^^ |value s cannot be accessed as a member of (cp : ConstructorProxy) from module class rs$line$4$. scala> cp == ConstructorProxy("abc") val res0: Boolean = false scala> cp.toString val res1: String = ConstructorProxy@34073423
(x < 0) { println(1) println(2) println(3) } ダメな例 [warn] -- Warning: /path/to/have-fun-scala3/chapters/src/main/scala/chapter 2/IndentRule.scala:9:4 [warn] 9 | println(3) [warn] | ^ [warn] | Line is indented too far to the left, or a `}` is missing [warn] one warning found [warn] one warning found コンパイル結果
なお、インデント範囲は、以下が成り立つときに始まる a. extension のパラメータの後であるか b. given インスタンスにおける with の後であるか c. 行末トークンの後であるか d. 以下のトークンのいずれかのあとであるか ▪ = => ?=> <- catch do else finally for ▪ if match return then throw try while yield e. if や while の条件式の閉じ括弧 ) の後であるか f. for ループの enumerator の閉じ括弧 ) or } の後であること
finally for if match return then throw try while yield def hello: Int => Unit = x => for y <- 0 to 5 do for z <- 6 to 10 yield if y % 2 == 0 then try throw new Exception("hoge error: " + y) catch case e => println(e.getMessage) finally println("z is divided by y") else if y % 3 == 0 then println("multiple number of three") else x match case _ if x % 2 == 0 => println("x is an even number") case _ => println("x is an odd number") インデント規則: <indent> が入る例 ※ ?=> これが何を意味しているのかわからなかったので、わかる人いたら教えてくだ さい・・・関数型を表すらしいけど・・・ [4] 2021年11月3日追記:これは Context Function 型です。詳しくは #3 で。 FunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type | HKTypeParamClause '=>' Type
の後 • f) for ループの enumerator の閉じ括弧 ) or } の後 if (x > 0) // e) <indent> println("hello") var y = 0 while (y < 5) // e) <indent> println(y) y = y + 1 for (x <- 1 to 5) // f) <indent> yield println(x) for { x <- 1 to 5 } // f) <indent> yield println(x)
then else do catch finally yield match c. 次の行の先頭トークンが infix 演算子の場合で、そのインデント幅が現在のインデント幅より小 さく、前のインデント幅と一致するか、終了インデント幅より小さいこと • あるいは、以下が成り立つときも <outdent> が入る a. 次のいずれかのトークンが <indent> で始まる文に続いており、そのインデント範囲を閉じること ▪ then, else, do, catch, finally, yield, }, ), ], case b. インデント範囲が括弧によって閉じている場合、 <indent> から始まる文に続くコンマの前に入る
a. 中括弧で囲まれた範囲のインデント幅は、中括弧の後に開始された行の最初のトークンのインデン ト幅になる b. ブラケットまたは括弧で囲まれたインデント幅は以下のようになる ▪ 開き括弧 [ or ( が行末にある場合、それに続くトークンのインデント幅になる ▪ それ以外の場合は、囲んでいる括弧のインデント幅になる c. 閉じ括弧 }, ] or ) が検出されると、必要な数の <outdent> が挿入される
が続いた場合、インデント範 囲が開始する ◦ 上記の場合、case でない同じインデント幅のトークンにおいて、またはより小さいインデント幅の トークンにおいてインデント範囲が終了する Case 句の特別な取り扱い def f(x: Int) = // Indent region starts after this `match` because // the following `case` appears at the indentation width // that’s current for the match itself. x match case 1 => println("I") case 2 => println("II") case 3 => println("III") case 4 => println("IV") case 5 => println("V") case _ => println(x) println("indent region ended.") scala> chapter2.IndentRuleForCase.f(1) I indent region ended. scala> chapter2.IndentRuleForCase.f(5) V indent region ended. scala> chapter2.IndentRuleForCase.f(100) 100 indent region ended.
try new this val given • end マーカー指定子トークンはその前にある文に対応している必要がある a. 文がメンバー x を定義する場合、指定子トークンは x b. 文がコンストラクターを定義する場合、指定子トークンは this c. 文が匿名 given を定義する場合、指定子トークンは given d. 文が匿名拡張メソッドを定義する場合、指定子トークンは extension e. 文が匿名クラスを定義する場合、指定子トークンは new f. 文が val 定義の場合、指定子トークンは val g. 文が package 句の場合、指定子トークンは package の識別子 h. 文が if, while, for, try, あるいは match の場合、指定子トークンはそれと同じトークン
b) 文がコンストラクターを定義する場合、指定子トークンは this // a) member object Member: // ... end Member // a) member abstract class Member(): // b) constructor def this(x: Int) = this() // ... end this def f: String end Member
e) 文が匿名クラスを定義する場合、指定子トークンは new // a) member object Member: // c) anonymous given given Member = // e) anonymous class new Member: // a) member def f = "!" end f end new end given end Member
val 定義の場合、指定子トークンは val • f) 文が package 句の場合、指定子トークンは package の識別子 // d) anonymous extension extension (x: Member) def ff: String = x.f ++ x.f end extension // f) val definition val a :: b = x :: Nil end val // f) package clause package chapter2.end.marker: // ... end marker
あるいは match の場合、指定子トークンは それと同じトークン // h) if statement if x > 0 then // h) while statement while y > 0 do println(y) y -= 1 end while // h) try statement try // h) match statement x match case 0 => println("0") case _ => end match finally println("done") end try end if