返回介绍

5.1 定义

发布于 2024-10-13 11:25:29 字数 3070 浏览 0 评论 0 收藏 0

使用 fn 定义,参数和返回值须标注类型。

  • 以逗号分隔多个参数。
  • -> 指示返回值类型。
  • 以元组返回多个值。
  • Result<T, E> 返回正确或错误值。
  • 支持函数嵌套(nested)。
  • 支持匿名函数和闭包(closure)。
  • 不支持重载(overload)。
  • 不支持变参(以 macro 实现)。
  • 不支持默认值(以 Option<T> 实现)。

可用 return 提前返回,或以表达式作为结束。

隐式返回最后一个表达式值。执行流的最后一行,不一定是函数代码的最后一行。即便没有返回值定义,也隐式返回 unit

函数定义的参数为形参,调用时传递的是实参。多数语言实现上,将实参(argument)复制为形参(parameter)。形参等同于函数内部定义的变量,但内存位置未必在该函数栈帧内。优先使用寄存器传输。超出则由调用方提供形参和返回值内存,以 RDI/RSI 传递地址。

fn add(x: i64, y: i64) -> i64 {
  if x < 0 {
    return -1;
  }

  let z = x + y;
  z           // 不能以分号结束,那就成了语句。
}

fn main() {
  assert_eq!(add(-10, 2), -1);
  assert_eq!(add(1, 2), 3);  
}
fn set(mut x: i64) {  // 形参 x 可变: let mut x
  x = 200;
}

fn main() {
  let x = 0i64;
  set(x);
}
fn inc(x: &mut i64) {   // 可变引用: 目标可变。
  *x += 1;
}

fn main() {
  let mut x = 10i64;
  inc(&mut x);
  assert_eq!(x, 11);
}

函数是第一类对象。可赋值,或作为参数或返回值。

fn add(x: i32, y: i32) -> i32 {
  x + y
}

fn main() {
  let f: fn(i32, i32) -> i32;
  f = add;

  assert_eq!(f(1, 2), 3);
}
type F = fn(i32, i32) -> i32;  // 别名,更易读和维护!

fn test() -> F {
  fn add(x: i32, y: i32) -> i32 {
    x + y
  }

  return add;
}

fn main() {
  let add = test();
  assert_eq!(add(1, 2), 3);
}

参数默认值

利用 Option<T> 实现参数默认值。

Some(T)None 两个成员。可用 is_noneis_some 等方法进行判断。

fn inc(x: Option<i32>) -> i32 {
  
  // 完整方式。
  let a = match x {
    Some(v) => v,
    None => 100,    // 默认值
  };

  a + 1
}


fn main() {
  assert_eq!(inc(Some(123)), 124);
  assert_eq!(inc(None), 101);  
}
fn inc(x: Option<i32>) -> i32 {
  
  // 简略方式。
  let a = x.unwrap_or(100);
  
  a + 1
}
fn inc(x: Option<i32>) -> i32 {
  if let Some(a) = x { 
    return a + 1 
  }
  
  101
}

多返回值

以元组打包需要返回的多个值。

fn test() -> (i32, f32) {
  (1, 1.2f32)
}

fn main() {
  let (i, f) = test();

  assert_eq!(i, 1);
  assert_eq!(f, 1.2f32);
}

还可以用 Result<T, E> 实现类似 Golang (result, error) 返回值。

包含 OkErr 两个成员。有关错误处理,详见后续章节。

fn test(x: i32) -> Result<i32, &'static str> {
  match x {
    x if x > 0 => Ok(1),
    _ => Err("error"),
  }
}


fn main() {
  let r = test(-1);
  match r {
    Ok(v) => println!("ok: {:?}", v),
    Err(e) => println!("err: {:?}", e),
  }
}

嵌套函数

嵌套函数无法使用外层变量。

用闭包实现该功能。

fn main() {
  let x = 1;

  fn test() {
    println!("{}", x);
             ^ can't capture dynamic environment in a fn item
  }

  test();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文