【翻译】Rust中函数的参数默认值

问题:

Default function arguments in Rust

Rust中函数的参数默认值


Is it possible in Rust to create a function with a default argument?

在Rust中创建一个带默认参数的函数可能么?

fn add(a: int = 1, b: int = 2) { a + b }

评论:

#6973 contains several work-arounds (using a struct).

#6973 包含了一些变通方法(使用一个结构体)。


In 2020, how do you can code it?

在2020年,你怎么样能够编写这样的代码?


@puentesdias The accepted answer is still the correct answer. There is no way to do it in Rust, and you have to either write a macro, or use Option and explicitly pass None. 

@puentesdias 接受的的回答仍然是正确的答案。在Rust中没有办法这样做,你要么写一个宏,要么使用Option并显式的传递None。


回答1(accepted)(up 55):

No, it is not at present. I think it likely that it will eventually be implemented, but there’s no active work in this space at present.

不,现在它是不能的。我认为最终可能会实现它,但是现在在这个领域内是不能工作的。


The typical technique employed here is to use functions or methods with different names and signatures.

这里使用的是经典技术,使用函数或者方法时带不同的名字和函数定义。


评论:

@ner0x652: but note that that approach is officially discouraged. 

@ner0x652:但是注意这种做法官方是不鼓励的。


@ChrisMorgan Do you have a source for that being officially discouraged? 

@ChrisMorgan 对于官方不鼓励这个说法你有出处么?


@JeroenBollen The best I can come up with in a couple of minutes’ searching is reddit.com/r/rust/comments/556c0g/…, where you have people like brson who was the Rust project leader at the time. IRC might have had more, not sure.

@JeroenBollen 我能在几分钟内查询到的最好的是reddit.com/r/rust/comments/556c0g/…,这里有像brson这样的人,他是当时Rust项目的负责人,IRC可能会有更多,不确定。


回答2(up 109):

Since default arguments are not supported you can get a similar behavior using Option<T>

因为默认参数是不支持的,你可以使用Option<T>得到相似的行为。

fn add(a: Option<i32>, b: Option<i32>) -> i32 {

    a.unwrap_or(1) + b.unwrap_or(2)

}

This accomplishes the objective of having the default value and the function coded only once (instead of in every call), but is of course a whole lot more to type out. The function call will look like add(None, None), which you may or may not like depending on your perspective.

这个完成了对象有默认值,并且函数仅仅编码一次(代替每一次调用),当然很多东西要打印出来。函数调用将看起来像add(None, None),你喜欢还是不喜欢取决于你的观点。


If you see typing nothing in the argument list as the coder potentially forgetting to make a choice then the big advantage here is in explicitness; the caller is explicitly saying they want to go with your default value, and will get a compile error if they put nothing. Think of it as typing add(DefaultValue, DefaultValue).

如果你看见在参数列表打印不出任何东西,那是因为编码者可能是忘记做一个选择,那么这里一个大的优势是显而易见的;调用者需要明确的说他们带着你的默认值运行,如果他们什么都没有输入就会得到一个编译错误。把它想象成打印add(DefaultValue, DefaultValue)。


You could also use a 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);

The big difference between the two solutions is that with "Option"-al arguments it is completely valid to write add(None, Some(4)), but with the macro pattern matching you cannot (this is similar to Python's default argument rules).

两种解决方案有非常大的不同,带“Option”参数方法写成add(None, Some(4))是完全有效的,但是宏匹配方法你是不能的(这个和Python的默认参数规则相似)。


You could also use an "arguments" struct and the From/Into traits:

你也可以使用一个“参数”结构体和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)));

}

This choice is obviously a lot more code, but unlike the macro design it uses the type system which means the compiler errors will be more helpful to your library/API user. This also allows users to make their own From implementation if that is helpful to them.

这个选择很明显需要更多的代码,但是不像宏设计,它使用系统打印,意味着编译器报错将会对你的库/API使用者有更多帮助的。这也允许使用者做他们自己的From实现,如果对它们有用的话。


评论:

this answer would be better as several answers, one for each approach. i want to upvote just one of them

这个回答最好有好几个答案,每一个方法对应一个。我只支持它们中的一个。


回答3(up 57):

No, Rust doesn't support default function arguments. You have to define different methods with different names. There is no function overloading either, because Rust use function names to derive types (function overloading requires the opposite).

不能,Rust不支持函数默认参数。你不得不使用不同的名字来定义不同的方法。也没有方法重载,因为Rust使用函数名字来派生类型(函数重载要求正好相反)


In case of struct initialization you can use the struct update syntax like this:

在结构体初始化的情况下,你可以使用结构体更新语法,如下:

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 request, I cross-posted this answer from a duplicated question]

应要求,我从一个重复的问题中把这个回答跨帖贴上来。


评论:

This is a very useable pattern for default arguments. Should be higher up

这个对于默认参数是非常有用的模式。应该获得更高的支持。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容