是否可以创建一个带有默认参数的函数?
fn add(a: int = 1, b: int = 2) { a + b }
aor9mmx11#
由于不支持缺省参数,因此可以使用Option<T>获得类似的行为
Option<T>
fn add(a: Option<i32>, b: Option<i32>) -> i32 { a.unwrap_or(1) + b.unwrap_or(2) }
这样就实现了只对默认值和函数编码一次(而不是在每次调用中)的目标,但当然要输入更多的代码,函数调用看起来像add(None, None),这取决于您的观点。如果你发现在参数列表中什么也没输入,因为编码者可能忘记做选择,那么这里最大的优势就是显式性;调用者明确地说他们想使用你的默认值,如果他们什么都不输入,将会得到一个编译错误,就像输入add(DefaultValue, DefaultValue)。也可以使用宏:x一个一个一个一个x一个一个二个x这两种解决方案之间最大的区别在于,使用"Option"-al参数时,编写add(None, Some(4))是完全有效的,但使用宏模式匹配时,就不能这样做了(这类似于Python的默认参数规则)。你也可以使用一个"arguments"结构和From/Into特征:
add(None, None)
add(DefaultValue, DefaultValue)
add(None, Some(4))
From
Into
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))); }
这种选择显然需要更多的代码,但与宏设计不同的是,它使用类型系统,这意味着编译器错误将对您的库/API用户更有帮助。这也允许用户制作自己的From实现,如果这对他们有帮助的话。
ej83mcc02#
不,目前还没有。我认为它最终很可能会得到实施,但目前在这一领域还没有积极的工作。这里采用的典型技术是使用具有不同名称和签名的函数或方法。
n9vozmp43#
不,Rust不支持默认函数参数。你必须用不同的名字定义不同的方法。也没有函数重载,因为Rust使用函数名来派生类型(函数重载要求相反)。在结构初始化的情况下,可以使用如下结构更新语法:
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); }
[on请求,我从重复问题交叉发布了此答案]
kupeojn64#
Rust不支持默认的函数参数,我也不相信它将来会被实现,所以我写了一个proc_macro duang来实现它。例如:
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); }
velaa5lx5#
如果您使用的是Rust 1.12或更高版本,至少可以使函数参数更易于与Option和into()一起使用:
Option
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); }
ctehm74n6#
另一种方法是将一个带有可选参数的枚举声明为变量,变量可以被参数化,以便为每个选项获取正确的类型。函数可以实现为获取枚举变量的可变长度切片。变量可以是任何顺序和长度。默认值在函数中实现为初始赋值。
enum FooOptions<'a> { Height(f64), Weight(f64), Name(&'a str), } use FooOptions::*; fn foo(args: &[FooOptions]) { let mut height = 1.8; let mut weight = 77.11; let mut name = "unspecified".to_string(); for opt in args { match opt { Height(h) => height = *h, Weight(w) => weight = *w, Name(n) => name = n.to_string(), } } println!(" name: {}\nweight: {} kg\nheight: {} m", name, weight, height); } fn main() { foo( &[ Weight(90.0), Name("Bob") ] ); }
输出:
name: Bob weight: 90 kg height: 1.8 m
args本身也可以是可选的。
args
fn foo(args: Option<&[FooOptions]>) { let args = args.or(Some(&[])).unwrap(); // ... }
gkl3eglg7#
在前面答案的基础上,请记住,您可以创建与现有变量同名的新变量,这将隐藏以前的变量。如果您不打算再使用Option<...>,这对于保持代码清晰非常有用。
Option<...>
fn add(a: Option<i32>, b: Option<i32>) -> i32 { let a = a.unwrap_or(1); let b = a.unwrap_or(2); a + b }
7条答案
按热度按时间aor9mmx11#
由于不支持缺省参数,因此可以使用
Option<T>
获得类似的行为这样就实现了只对默认值和函数编码一次(而不是在每次调用中)的目标,但当然要输入更多的代码,函数调用看起来像
add(None, None)
,这取决于您的观点。如果你发现在参数列表中什么也没输入,因为编码者可能忘记做选择,那么这里最大的优势就是显式性;调用者明确地说他们想使用你的默认值,如果他们什么都不输入,将会得到一个编译错误,就像输入
add(DefaultValue, DefaultValue)
。也可以使用宏:
x一个一个一个一个x一个一个二个x
这两种解决方案之间最大的区别在于,使用"Option"-al参数时,编写
add(None, Some(4))
是完全有效的,但使用宏模式匹配时,就不能这样做了(这类似于Python的默认参数规则)。你也可以使用一个"arguments"结构和
From
/Into
特征:这种选择显然需要更多的代码,但与宏设计不同的是,它使用类型系统,这意味着编译器错误将对您的库/API用户更有帮助。这也允许用户制作自己的
From
实现,如果这对他们有帮助的话。ej83mcc02#
不,目前还没有。我认为它最终很可能会得到实施,但目前在这一领域还没有积极的工作。
这里采用的典型技术是使用具有不同名称和签名的函数或方法。
n9vozmp43#
不,Rust不支持默认函数参数。你必须用不同的名字定义不同的方法。也没有函数重载,因为Rust使用函数名来派生类型(函数重载要求相反)。
在结构初始化的情况下,可以使用如下结构更新语法:
[on请求,我从重复问题交叉发布了此答案]
kupeojn64#
Rust不支持默认的函数参数,我也不相信它将来会被实现,所以我写了一个proc_macro duang来实现它。
例如:
velaa5lx5#
如果您使用的是Rust 1.12或更高版本,至少可以使函数参数更易于与
Option
和into()
一起使用:ctehm74n6#
另一种方法是将一个带有可选参数的枚举声明为变量,变量可以被参数化,以便为每个选项获取正确的类型。函数可以实现为获取枚举变量的可变长度切片。变量可以是任何顺序和长度。默认值在函数中实现为初始赋值。
输出:
args
本身也可以是可选的。gkl3eglg7#
在前面答案的基础上,请记住,您可以创建与现有变量同名的新变量,这将隐藏以前的变量。如果您不打算再使用
Option<...>
,这对于保持代码清晰非常有用。