program story

Scala에서 유형 지정의 목적은 무엇입니까?

inputbox 2020. 10. 30. 07:59
반응형

Scala에서 유형 지정의 목적은 무엇입니까?


사양에 어떤 유형 지정이 있는지에 대한 정보가 많지 않으며 그 목적에 대한 내용도 확실히 없습니다. "전달하는 varargs 작동하기"외에 어떤 용도로 유형 지정을 사용합니까? 다음은 구문 및 사용 효과에 대한 몇 가지 스칼라 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

유형 지정은 가능한 모든 유효한 유형에서 표현식에서 예상하는 유형을 컴파일러에 알려주는 것입니다.

유형은 분산 및 유형 선언과 같은 기존 제약 조건을 준수하고 " is a "에 적용되는 표현식 유형 중 하나 이거나 범위에 적용되는 변환 이있는 경우 유효합니다 .

따라서, java.lang.String extends java.lang.Objectany StringObject. 귀하의 예제에서 당신은 당신이 표현이 원하는 선언 s로 취급 Object하는 없습니다 String. 거기를 방해하는 제약 조건입니다 원하는 유형이 유형 중 하나이기 때문에 s A는 , 그것을 작동합니다.

자, 왜 그것을 원하십니까? 이걸 고려하세요:

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)

또한 타입 ascripting하여이 문제를 해결 한 수 s에서 ss선언하거나 선언 할 수 ss될의 유형을 Set[AnyRef].

그러나 유형 선언은 식별자에 값을 할당하는 한 동일한 결과를 얻습니다. 물론 일회성 식별자로 코드를 버리는 것에 신경 쓰지 않는다면 항상 할 수 있습니다. 예를 들어 다음은 컴파일되지 않습니다.

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}
             | ‘:’ ‘_’ ‘*’

한 가지 가능성은 네트워크 및 직렬 프로토콜 수준의 경우 다음과 같습니다.

val x = 2 : Byte

보다 훨씬 깨끗하다

val x = 2.asInstanceOf[Byte]

두 번째 형식은 런타임 변환 (컴파일러에서 처리하지 않음)이며 흥미로운 오버 / 언더 플로 조건으로 이어질 수 있습니다.


I use type ascription to paper over holes in Scala's type inference. For example, foldLeft over a collection of type A takes an initial element of type B and a function (B, A) => B that is used to fold the elements of the collection into the initial element. The actual value of type B is inferred from the type of the initial element. Since Nil extends List[Nothing], using it as an initial element causes problems:

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)

Alternatively, you could just use List.empty[Int] instead of Nil:List[Int].

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

edit: List.empty[A] is implemented as

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

(source)

This is effectively a more verbose form of Nil:List[A]


You may find this thread illuminating, if a bit convoluted to follow. The important thing to note is that you're adding constraint hints to the type checker - it gives you a little more control over what that compilation phase is doing.


Type Inference: We can skip Explicitly giving Name of Type of Something in source code, called Type Inference.(Although required in some exceptional cases.)

Type Ascription: Being explicit about the type of something is called a Type Ascription. What Difference It can make?

ex: val x = 2 : Byte

also see: 1. We can explicitly give return type to our functions

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

> t1: Option[Option[String]]

Another way of declaring this could be:

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

Here we did not give Option[Option[String]] return type explicitly and Compiler inferred it as Some[Option[String]]. Why Some[Option[String]] is because we used type ascription in the definition.

  1. Another way we can use the same definition is:

    def t3 = Some(None)

    > t3: Some[None.type]

This time We did not explicitly tell the compiler anything(neither this defi). And It inferred our definition as Some[None.type]

참고URL : https://stackoverflow.com/questions/2087250/what-is-the-purpose-of-type-ascriptions-in-scala

반응형