Rustでデフォルトの引数を使用して関数を作成することは可能ですか?
fn add(a: int = 1, b: int = 2) { a + b }
Rustでデフォルトの引数を使用して関数を作成することは可能ですか?
fn add(a: int = 1, b: int = 2) { a + b }
Option
して明示的に渡す必要がありNone
ます。
回答:
いいえ、現在はありません。最終的には実装される可能性が高いと思いますが、現時点ではこの分野での活発な作業はありません。
ここで採用されている典型的な手法は、名前とシグネチャが異なる関数またはメソッドを使用することです。
デフォルトの引数はサポートされていないため、を使用して同様の動作を得ることができます Option<T>
fn add(a: Option<i32>, b: Option<i32>) -> i32 {
a.unwrap_or(1) + b.unwrap_or(2)
}
これにより、デフォルト値と関数を(すべての呼び出しではなく)1回だけコーディングするという目的が達成されますが、もちろん、入力する必要はありません。関数呼び出しはのようadd(None, None)
になりますが、視点によっては気に入るかどうかはわかりません。
コーダーが選択を忘れる可能性があるため、引数リストに何も入力していない場合、ここでの大きな利点は明示性にあります。呼び出し元は、デフォルト値を使用することを明示的に言っており、何も入力しないとコンパイルエラーが発生します。入力と考えてくださいadd(DefaultValue, DefaultValue)
。
マクロを使用することもできます。
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);
2つのソリューションの大きな違いは、「Option」-al引数を使用すると、書き込むことは完全に有効ですadd(None, Some(4))
が、マクロパターンマッチングを使用する場合はできません(これはPythonのデフォルトの引数ルールに似ています)。
「引数」構造体と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
が役立つ場合は、ユーザーが独自の実装を行うこともできます。
いいえ、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);
}
[リクエストに応じて、重複した質問からこの回答をクロスポストしました]
Rustはデフォルトの関数引数をサポートしておらず、将来実装されるとは思わない。そこで、マクロ形式で実装するためにproc_macroduangを作成しました。
例えば:
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);
}
後で錆1.12以上を使用している場合は、少なくともメイク関数の引数より簡単にして使用することができます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);
}
別の方法は、オプションのparamsをバリアントとして列挙型を宣言することです。これは、各オプションに適切な型をとるようにパラメーター化できます。この関数は、列挙型バリアントの可変長スライスを取得するように実装できます。それらは任意の順序と長さにすることができます。デフォルトは、初期割り当てとして関数内に実装されます。
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