Pregunta

¿Es posible en Rust crear una función con un argumento predeterminado?

fn add(a: int = 1, b: int = 2) { a + b }
¿Fue útil?

Solución

No, no está en la actualidad.Creo que es probable que eventualmente se implemente implementado, pero no hay trabajo activo en este espacio en la actualidad.

La técnica típica empleada aquí es usar funciones o métodos con diferentes nombres y firmas.

Otros consejos

Dado que los argumentos predeterminados no son compatibles, puede obtener un comportamiento similar usando Option<T>

fn add(a: Option<i32>, b: Option<i32>) -> i32 {
    a.unwrap_or(1) + b.unwrap_or(2)
}

Esto logra el objetivo de tener el valor predeterminado y la función codificados solo una vez (en lugar de en cada llamada), pero, por supuesto, hay mucho más que escribir.La llamada a la función se verá así add(None, None), que puede que te guste o no dependiendo de tu perspectiva.

Si ve que no escribir nada en la lista de argumentos significa que el codificador podría olvidarse de tomar una decisión, entonces la gran ventaja aquí es la claridad;la persona que llama dice explícitamente que quiere usar su valor predeterminado y obtendrá un error de compilación si no pone nada.Piense en ello como escribir add(DefaultValue, DefaultValue).

También puedes usar una macro:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

macro_rules! add {
    ($a: expr) => {
        add($a, 2)
    };
    () => {
        add(1, 2)
    };
}
assert_eq!(add!(), 3);
assert_eq!(add!(4), 6);

La gran diferencia entre las dos soluciones es que con argumentos "Opcionales" es completamente válido escribir add(None, Some(4)), pero con la coincidencia del patrón macro no es posible (esto es similar a las reglas de argumentos predeterminadas de Python).

También podría utilizar una estructura de "argumentos" y el From/Into rasgos:

pub struct FooArgs {
    a: f64,
    b: i32,
}

impl Default for FooArgs {
    fn default() -> Self {
        FooArgs { a: 1.0, b: 1 }
    }
}

impl From<()> for FooArgs {
    fn from(_: ()) -> Self {
        Self::default()
    }
}

impl From<f64> for FooArgs {
    fn from(a: f64) -> Self {
        Self {
            a: a,
            ..Self::default()
        }
    }
}

impl From<i32> for FooArgs {
    fn from(b: i32) -> Self {
        Self {
            b: b,
            ..Self::default()
        }
    }
}

impl From<(f64, i32)> for FooArgs {
    fn from((a, b): (f64, i32)) -> Self {
        Self { a: a, b: b }
    }
}

pub fn foo<A>(arg_like: A) -> f64
where
    A: Into<FooArgs>,
{
    let args = arg_like.into();
    args.a * (args.b as f64)
}

fn main() {
    println!("{}", foo(()));
    println!("{}", foo(5.0));
    println!("{}", foo(-3));
    println!("{}", foo((2.0, 6)));
}

Esta elección obviamente implica mucho más código, pero a diferencia del diseño de macro, utiliza el sistema de tipos, lo que significa que los errores del compilador serán más útiles para el usuario de su biblioteca/API.Esto también permite a los usuarios crear sus propios From implementación si eso les resulta útil.

No, ROX no admite los argumentos de función predeterminados.Tienes que definir diferentes métodos con diferentes nombres.Tampoco hay una sobrecarga de funciones, ya que los nombres de las funciones del uso del óxido para obtener tipos (sobrecarga de la función requiere lo contrario).

En caso de inicialización de estructuras, puede usar la sintaxis de Struct Update así:

use std::default::Default;

#[derive(Debug)]
pub struct Sample {
    a: u32,
    b: u32,
    c: u32,
}

impl Default for Sample {
    fn default() -> Self {
        Sample { a: 2, b: 4, c: 6}
    }
}

fn main() {
    let s = Sample { c: 23, .. Sample::default() };
    println!("{:?}", s);
}

[a petición, he publicado esta respuesta de una pregunta duplicada]

Si está utilizando Rust 1.12 o posterior, al menos puede hacer que los argumentos de función sean más fáciles de usar con Option y into():

fn add<T: Into<Option<u32>>>(a: u32, b: T) -> u32 {
    if let Some(b) = b.into() {
        a + b
    } else {
        a
    }
}

fn main() {
    assert_eq!(add(3, 4), 7);
    assert_eq!(add(8, None), 8);
}

ROXT no admite argumentos de función predeterminados, y no creo que se implemente implementado en el futuro. Así que escribí un proc_macro Duang para implementarlo en la forma macro.

Por ejemplo:

duang! ( fn add(a: i32 = 1, b: i32 = 2) -> i32 { a + b } );
fn main() {
    assert_eq!(add!(b=3, a=4), 7);
    assert_eq!(add!(6), 8);
    assert_eq!(add(4,5), 9);
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top