web-dev-qa-db-ja.com

Scalaで型のサブスクリプションを使用する目的は何ですか?

仕様にはどのタイプのサブスクリプションであるかについての情報はそれほど多くなく、その目的については確かに何もありません。 「通過可変引数を機能させる」以外に、型の表記を何に使用しますか?下記は、いくつかのscala REPL)を使用して、構文と効果を示しています。

scala> val s = "Dave"
s: Java.lang.String = Dave

scala> val p = s:Object
p: Java.lang.Object = Dave

scala> p.length
<console>:7: error: value length is not a member of Java.lang.Object
       p.length
         ^
scala> p.getClass
res10: Java.lang.Class[_ <: Java.lang.Object] = class Java.lang.String

scala> s.getClass
res11: Java.lang.Class[_ <: Java.lang.Object] = class Java.lang.String

scala> p.asInstanceOf[String].length
res9: Int = 4
72
davetron5000

型の割り当てとは、考えられるすべての有効な型から、式に期待される型をコンパイラに伝えるだけです。

タイプは、バリアンスやタイプ宣言などの既存の制約を尊重し、「is a "に適用される式のタイプの1つであるか、スコープに適用される変換がある場合に有効です。

したがって、_Java.lang.String extends Java.lang.Object_、つまりStringObjectです。あなたの例では、式sObjectではなくStringとして扱うことを宣言しています。それを妨げる制約はなく、目的のタイプはタイプsis aの1つなので、機能します。

さて、なぜあなたはそれを望みますか?このことを考慮:

_scala> val s = "Dave"
s: Java.lang.String = Dave

scala> val p = s: Object
p: Java.lang.Object = Dave

scala> val ss = scala.collection.mutable.Set(s)
ss: scala.collection.mutable.Set[Java.lang.String] = Set(Dave)

scala> val ps = scala.collection.mutable.Set(p)
ps: scala.collection.mutable.Set[Java.lang.Object] = Set(Dave)

scala> ss += Nil
<console>:7: error: type mismatch;
 found   : scala.collection.immutable.Nil.type (with underlying type object Nil)
 required: Java.lang.String
       ss += Nil
             ^

scala> ps += Nil
res3: ps.type = Set(List(), Dave)
_

s宣言でタイプascripting ssを使用してこれを修正したり、ssの型を_Set[AnyRef]_として宣言したりすることもできます。

ただし、型宣言は、識別子に値を割り当てている限り、同じことを実現します。もちろん、1回限りの識別子でコードを散らかすことに関心がない場合は、どちらを実行できますか。たとえば、次のコードはコンパイルされません。

_def prefixesOf(s: String) = s.foldLeft(Nil) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}
_

しかし、これは:

_def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}
_

ここでNilの代わりに識別子を使用するのはばかげています。代わりにList[String]()と書くこともできますが、これは常にオプションとは限りません。例えばこれを考えてください:

_def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { 
  case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
  case (vowel, _) => vowel
}
_

参考までに、これはScala 2.7仕様(2009年3月15日ドラフト)がタイプのサブスクリプションについて述べなければならないことです。

_Expr1 ::= ...
        | PostfixExpr Ascription

Ascription ::= ‘:’ InfixType
             | ‘:’ Annotation {Annotation}
             | ‘:’ ‘_’ ‘*’
_
74

1つの可能性は、ネットワークおよびシリアルプロトコルレベルのもので、これは次のとおりです。

val x = 2 : Byte

よりはるかにきれいです

val x = 2.asInstanceOf[Byte]

2番目の形式もランタイム変換であり(コンパイラーでは処理されません)、興味深いオーバーフロー/アンダーフロー状態が発生する可能性があります。

27
Kevin Wright

型推論:型推論と呼ばれる、ソースコードで何かの型の名前を明示的に指定することをスキップできます(一部の例外的なケースでは必須です)。

型の表記:何かの型を明示することを型の表記と呼びます。それはどんな違いを生むことができますか?

例:val x = 2:バイト

次も参照してください:1.関数に戻り値の型を明示的に指定できます

_def t1 : Option[Option[String]] = Some(None)

> t1: Option[Option[String]]
_

これを宣言する別の方法は次のとおりです。

_def t2 = Some(None: Option[String])
> t2: Some[Option[String]]
_

ここでは、_Option[Option[String]]_の戻り値の型を明示的に指定せず、コンパイラは_Some[Option[String]]_としてそれを推定しました。なぜ_Some[Option[String]]_なのかは、定義で型の説明を使用したからです。

  1. 同じ定義を使用できる別の方法は次のとおりです。

    def t3 = Some(None)

    _> t3: Some[None.type]_

今回は、コンパイラーに明示的に何も伝えませんでした(どちらもこれに反することはありません)。そして、それは私たちの定義をSome [None.type]として推論しました

0
Vikas Sharma

少し複雑になると、 this thread がわかるかもしれません。注意すべき重要な点は、型ヒントに制約ヒントを追加していることです。これにより、コンパイルフェーズの動作を少し制御できます。

0
Justin W

私はScalaの型推論で穴の上に紙を書くために型の表記を使用しています。たとえば、タイプAのコレクションに対するfoldLeftは、タイプBの初期要素と、コレクションの要素を初期要素に折りたたむために使用される関数(B、A)=> Bを取ります。タイプBの実際の値は、初期要素のタイプから推測されます。 NilはList [Nothing]を拡張するため、それを初期要素として使用すると問題が発生します。

scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)

scala> x.foldLeft(Nil)( (acc,elem) => elem::acc)
<console>:9: error: type mismatch;
 found   : List[Int]
 required: scala.collection.immutable.Nil.type
              x.foldLeft(Nil)( (acc,elem) => elem::acc)
                                                 ^

scala> x.foldLeft(Nil:List[Int])( (acc,elem) => elem::acc )
res2: List[Int] = List(4, 3, 2, 1)

または、Nil:List [Int]の代わりにList.empty [Int]を使用することもできます。

scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)

編集:List.empty [A]は次のように実装されます

override def empty[A]: List[A] = Nil

(ソース)

これは事実上、Nil:List [A]のより冗長な形式です。

0
pkinsky