scala scala-2.8

¿Cuál es el concepto de "conformidad débil" en Scala?



scala-2.8 (3)

3.5.3 Conformidad débil En algunas situaciones, Scala utiliza una relación de conformidad más general. Un tipo S se ajusta débilmente a un tipo T, escrito S <: w T, si S <: T o S y T son tipos de números primitivos y S precede a T en el siguiente ordenamiento.

  • Byte <: w Corto
  • Byte <: w carácter
  • Corto <: w Int
  • Int <: w Long
  • Largo <: w Flotador
  • Flotante <: w Doble

Un límite inferior mínimo débil es un límite inferior superior con respecto a la conformidad débil.

¿Dónde se usa esto? Por un lado, determina el tipo de expresiones if :

El tipo de expresión condicional es el límite inferior débil (§3.5.3) de los tipos de e2 y e3

En Scala 2.7.x, esto sería del tipo AnyVal , el límite mínimo de Int y Double . En 2.8.x, se escribe como Double .

scala> if (true) 1 else 1d res0: Double = 1.0

Similar:

scala> try { 1 } catch { case _ => 1.0 } res2: Double = 1.0 scala> (new {}: Any) match { case 1 => 1; case _ => 1.0 } res6: Double = 1.0 scala> def pf[R](pf: PartialFunction[Any, R]): PartialFunction[Any, R] = pf pf: [R](pf: PartialFunction[Any,R])PartialFunction[Any,R] scala> pf { case 1 => 1; case _ => 1d } res4: PartialFunction[Any,Double] = <function1>

Otro lugar donde se usa es en inferencia de tipo:

scala> def foo[A](a1: A, a2: A): A = a1 foo: [A](a1: A,a2: A)A scala> foo(1, 1d) res8: Double = 1.0 scala> def foos[A](as: A*): A = as.head foos: [A](as: A*)A scala> foos(1, 1d) res9: Double = 1.0

Y también para la ampliación numérica simple:

Ampliación Numérica. Si e tiene un tipo de número primitivo que se adapta débilmente (§3.5.3) al tipo esperado, se amplía al tipo esperado usando uno de los 6.26 métodos de conversión numérica de Conversiones Implícitas 97 a Cortar, aChar, aInt, aLong, aFloat, aDouble definido en §12.2.1. el tipo esperado es un tipo numérico primitivo Byte, Short o Char, y la expresión e es un ajuste literal entero en el rango de ese tipo, se convierte al mismo literal en ese tipo.

scala> 1: Double res10: Double = 1.0

ACTUALIZAR

Como lo señaló Daniel, la especificación es errónea acerca de qué tipos tienen una conformidad débil. Preguntemos al compilador mismo:

scala> :power ** Power User mode enabled - BEEP BOOP ** ** scala.tools.nsc._ has been imported ** ** New vals! Try repl, global, power ** ** New cmds! :help to discover them ** ** New defs! Type power.<tab> to reveal ** scala> settings.maxPrintString = 10000 scala> import global.definitions._ import global.definitions._ scala> (for{c1 <- ScalaValueClasses; c2 <- ScalaValueClasses isNSC = isNumericSubClass(c1, c2) if isNSC } yield ("isNumericSubClass (%s, %s) = %b" format (c1, c2, isNSC))).mkString("/n") res5: String = isNumericSubClass (class Byte, class Byte) = true isNumericSubClass (class Byte, class Short) = true isNumericSubClass (class Byte, class Int) = true isNumericSubClass (class Byte, class Long) = true isNumericSubClass (class Byte, class Float) = true isNumericSubClass (class Byte, class Double) = true isNumericSubClass (class Short, class Short) = true isNumericSubClass (class Short, class Int) = true isNumericSubClass (class Short, class Long) = true isNumericSubClass (class Short, class Float) = true isNumericSubClass (class Short, class Double) = true isNumericSubClass (class Int, class Int) = true isNumericSubClass (class Int, class Long) = true isNumericSubClass (class Int, class Float) = true isNumericSubClass (class Int, class Double) = true isNumericSubClass (class Long, class Long) = true isNumericSubClass (class Long, class Float) = true isNumericSubClass (class Long, class Double) = true isNumericSubClass (class Char, class Int) = true isNumericSubClass (class Char, class Long) = true isNumericSubClass (class Char, class Char) = true isNumericSubClass (class Char, class Float) = true isNumericSubClass (class Char, class Double) = true isNumericSubClass (class Float, class Float) = true isNumericSubClass (class Float, class Double) = true isNumericSubClass (class Double, class Double) = true

Hace poco me encontré con el término "Conformidad débil" (en la respuesta de los retronym usuario de Stack Overflow a ¿Cómo configurar la conversión implícita para permitir la aritmética entre tipos numéricos? ).

¿Qué es?


Para completar la respuesta de Sandor , esa nueva característica en 2.8 aún se está cocinando (y arreglando).

En este hilo , Esser descubre un efecto secundario desagradable:

scala> val a= 10 a: Int = 10 scala> val b= 3 b: Int = 3 scala> if (b!=0) a/b else Double.NaN res0: Double = 3.0 scala> def div1(a: Int, b: Int) = if (b!=0) a/b else Double.NaN div1: (a: Int,b: Int)Double scala> def div2(a: Int, b: Int): Double = if (b!=0) a/b else Double.NaN div2: (a: Int,b: Int)Double scala> div1(10,3) res1: Double = 3.0 scala> div2(10,3) res2: Double = 3.3333333333333335

Parece interesante, porque el tipo de resultado encontrado implícitamente es Double y el resultado es 3.0.
Si se da Doble explícitamente, el resultado es 3.33 ...

En este hilo , Martin Odersky agrega (21 de junio):

ha descubierto un serio efecto secundario no deseado de las reglas de conformidad débiles en la resolución de sobrecarga.
El problema era que los argumentos de los métodos sobrecargados se requieren para ajustarse débilmente, mientras que el tipo de resultado fue requerido para ajustarse fuertemente.

Esto favoreció el método de adición Float => Float en un Int sobre el método Int => Int si el tipo de resultado era Float.
Trataba de ser conservador en mi cambio a una conformidad débil en el sentido de que requería una conformidad débil solo cuando parecía absolutamente necesario.
¡Pero ahora parece que ser conservador causó el problema que estamos viendo!

Y aún otro lanzamiento de Scala RC;)

Confirmado en este hilo por Martin Odersky (22 de junio) :

Así que habrá un RC7 con hasta ahora tres cambios de RC6:

  1. val x: Double = 10/3 dará 3.0 , no 3.3333333 , esa fue la regresión que mencioné
  2. [...]
  3. [...]

Eso es. Nuestras prioridades ahora son desplegar 2.8 lo más rápido posible, y al mismo tiempo evitar las regresiones realmente malas como la (1) anterior.

Línea de tiempo:

  • Esperaremos una semana más para recibir comentarios sobre RC6.
  • Vamos a sacar RC7 a principios de la próxima semana.
    Si no aparecen más problemas, RC7 se convertirá en 2.8 final 10-14 días después de su lanzamiento.

(Así que alrededor del 12 de julio, creo, pero esta suposición es solo mía;))


Según Scala lang spec 2.8:
http://www.scala-lang.org/archives/downloads/distrib/files/nightly/pdfs/ScalaReference.pdf

3.5.3 Conformidad débil
En algunas situaciones Scala usa una relación de conformidad más genral. Un tipo S se ajusta débilmente a un tipo T, escrito S <: w T, si S <: T o S y T son tipos de números primitivos y S precede a T en el siguiente ordenamiento.
Byte <: w Corto
Byte <: w carácter
Corto <: w Int
Int <: w Long
Largo <: w Flotador
Flotante <: w Doble
Un límite inferior mínimo débil es un límite inferior superior con respecto a la conformidad débil.