Rust

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

Funciones y abstracciones de comportamiento

Tratar funciones como valores es la base para leer y escribir el resto de las comparaciones: sin esto, los mecanismos posteriores parecen sintaxis arbitraria.

Equivalencia desde Kotlin

Comportamiento como valor

Cercana

Rust representa las closures mediante tipos propios y expresa la capacidad de invocarlas con los traits Fn, FnMut o FnOnce. Un límite genérico evita fijar una representación única.

Referencia Kotlin: Declarar una operación reutilizable y recibir otra operación como valor.

Mecanismo
Una función genérica restringida por el trait Fn(i32) -> i32.
Idea conservada
La transformación se recibe como valor y se invoca dos veces sobre el mismo argumento; quien la declara no necesita conocer apply_twice.
Riesgo de diseño
Elegir Fn para una closure que debe consumir una captura; en ese caso la frontera puede requerir FnOnce.
Recomendación
Elige el límite menos restrictivo que comunique cómo la función invocará la closure.
Convención del curso
Elige el trait menos restrictivo (Fn antes que FnMut o FnOnce) que describa cómo se invoca la closure.
Mecanismo del lenguaje
Closures y los traits Fn, FnMut y FnOnce.

Diferencias relevantes

  • La closure puede capturar valores por préstamo, préstamo mutable o movimiento; eso afecta el trait que la API acepta.
  • Fn requiere poder llamar la closure sin consumirla ni mutarla.

El trait Fn expresa cómo puede invocarse la transformación recibida.

Kotlin
fun applyTwice(
    value: Int,
    transform: (Int) -> Int,
): Int = transform(transform(value))

val result = applyTwice(3) { it + 1 } // 5
Rust
fn apply_twice<F>(value: i32, transform: F) -> i32
where
    F: Fn(i32) -> i32,
{
    transform(transform(value))
}

let result = apply_twice(3, |number| number + 1); // 5

Otra forma de recibir comportamiento: un predicado para filtrar un slice.

fn keep(xs: &[i32], p: impl Fn(i32) -> bool) -> Vec<i32> {
    xs.iter().copied().filter(p).collect()
}

Fuentes

Equivalencia desde Kotlin

Parámetros variádicos

Cercana

En Rust, un slice &[i32] (sin variádicos definidos por usuarios) expresa la responsabilidad del fixture: Suma una cantidad variable de enteros.

Referencia Kotlin: Una función recibe vararg values: Int.

Mecanismo
un slice &[i32] (sin variádicos definidos por usuarios)
Riesgo de diseño
Copiar la sintaxis de Kotlin en vez de usar un slice &[i32] (sin variádicos definidos por usuarios).
Recomendación
Expón el contrato del fixture y usa un slice &[i32] (sin variádicos definidos por usuarios) solo para la garantía que realmente ofrece.

Diferencias relevantes

  • Distingue una llamada variádica de recibir explícitamente una colección.
  • La forma idiomática de Rust debe conservarse aunque la sintaxis difiera de Kotlin.

Suma una cantidad variable de enteros.

fn sum(values: &[i32]) -> i32 { values.iter().sum() }

Fuentes

Equivalencia desde Kotlin

Interfaces

Cercana

En Rust, trait implementado explícitamente expresa la responsabilidad del fixture: Permite reemplazar un proveedor de resultados por su contrato.

Referencia Kotlin: Una interfaz declara comportamiento sin fijar una representación.

Mecanismo
trait implementado explícitamente
Riesgo de diseño
Copiar la sintaxis de Kotlin en vez de usar trait implementado explícitamente.
Recomendación
Expón el contrato del fixture y usa trait implementado explícitamente solo para la garantía que realmente ofrece.

Diferencias relevantes

  • La conformidad puede ser nominal, estructural o basada en traits; no son la misma garantía.
  • La forma idiomática de Rust debe conservarse aunque la sintaxis difiera de Kotlin.

Permite reemplazar un proveedor de resultados por su contrato.

trait Score { fn value(&self) -> i32; }

Fuentes