Scala 3

Equivalencias idiomáticas entre Kotlin y Scala 3. Kotlin se presenta como referencia en cada concepto.

Tipos paramétricos y convenciones del lenguaje

Genéricos, operadores y rangos cambian de sintaxis entre ecosistemas, pero las preguntas de diseño detrás son las mismas: qué varía, qué se comprueba y cuándo.

Equivalencia desde Kotlin

Genéricos y varianza

Cercana

En Scala 3, parámetros +T y -T declarados en el tipo expresa la responsabilidad del fixture: Source<T> produce valores y Sink<T> los consume sin mezclar ambas responsabilidades.

Referencia Kotlin: Source<out T> es covariante y Sink<in T> es contravariante.

Mecanismo
parámetros +T y -T declarados en el tipo
Riesgo de diseño
Copiar la sintaxis de Kotlin en vez de usar parámetros +T y -T declarados en el tipo.
Recomendación
Expón el contrato del fixture y usa parámetros +T y -T declarados en el tipo solo para la garantía que realmente ofrece.

Diferencias relevantes

  • La varianza puede declararse, proyectarse en el uso o no tener una noción de subtipado equivalente.
  • La forma idiomática de Scala 3 debe conservarse aunque la sintaxis difiera de Kotlin.

Source<T> produce valores y Sink<T> los consume sin mezclar ambas responsabilidades.

trait Source[+T]:
  def get: T
trait Sink[-T]:
  def put(value: T): Unit

Fuentes

Equivalencia desde Kotlin

Operadores

Cercana

En Scala 3, método contains, invocable en notación infija (range contains price) expresa la responsabilidad del fixture: Comprueba si un precio de 79.9 cae dentro de un rango válido entre 50.0 y 100.0.

Referencia Kotlin: operator fun contains permite escribir price in range para una pertenencia definida por el dominio.

Mecanismo
método contains, invocable en notación infija (range contains price)
Riesgo de diseño
Copiar la sintaxis de Kotlin en vez de usar método contains, invocable en notación infija (range contains price).
Recomendación
Expón el contrato del fixture y usa método contains, invocable en notación infija (range contains price) solo para la garantía que realmente ofrece.

Diferencias relevantes

  • Muy pocos lenguajes permiten definir el operador de pertenencia (in) sobre un tipo propio; la mayoría exige un método con nombre como contains.
  • La forma idiomática de Scala 3 debe conservarse aunque la sintaxis difiera de Kotlin.

Comprueba si un precio de 79.9 cae dentro de un rango válido entre 50.0 y 100.0.

case class PriceRange(min: Double, max: Double):
  def contains(price: Double): Boolean = price >= min && price <= max

PriceRange(50.0, 100.0) contains 79.9

El método apply permite invocar la instancia con la sintaxis objeto(argumento).

class MinimumPrice(threshold: Double):
  def apply(price: Double): Boolean = price >= threshold

MinimumPrice(10.0)(79.9)

Fuentes

Equivalencia desde Kotlin

Rangos

Cercana

En Scala 3, rango inclusivo 1 to limit expresa la responsabilidad del fixture: Itera los enteros desde 1 hasta limit, incluyendo limit.

Referencia Kotlin: 1..limit representa una progresión de extremos inclusivos.

Mecanismo
rango inclusivo 1 to limit
Riesgo de diseño
Copiar la sintaxis de Kotlin en vez de usar rango inclusivo 1 to limit.
Recomendación
Expón el contrato del fixture y usa rango inclusivo 1 to limit solo para la garantía que realmente ofrece.

Diferencias relevantes

  • Un rango puede ser una colección reutilizable, un iterable perezoso o solo una forma de construir un bucle.
  • La forma idiomática de Scala 3 debe conservarse aunque la sintaxis difiera de Kotlin.

Itera los enteros desde 1 hasta limit, incluyendo limit.

(1 to limit).foreach(println)

Fuentes