【问题标题】:Is it possible to destructure the `self` argument of a method?是否可以解构方法的“self”参数?
【发布时间】:2017-09-22 00:30:28
【问题描述】:

我正在尝试找到一种方法来解构方法的 self 参数。根据GitHub comment

根据今天的会议,我们有一个不同的计划来使 self 参数可破坏。使用通用函数调用语法(UFCS #11938),静态方法和实例方法之间没有任何区别——它们都是“关联函数”。此时,任何第一个参数是 self 类型的函数都可以使用方法语法调用,self&self&mut self 只是 self: &Self 的糖,并且可以对 self 参数进行解构正常情况下不使用自糖。

我写了下面的代码,但它并没有像我预期的那样工作,因为所有三个打印函数都可以用作方法。

struct Vector {
    x: i32,
    y: i32,
    z: i32,
}

impl Vector {
    fn print1(self: &Self) {
        println!("{} {} {}", self.x, self.y, self.z);
    }

    // destructure self argument
    fn print2(&Vector{x, y, z}: &Self) {
        println!("{} {} {}", x, y, z);
    }

    // use another name for the first argument
    fn print3(this: &Self) {
        println!("{} {} {}", this.x, this.y, this.z);
    }
}

fn main() {
    let v = Vector{x: 1, y: 2, z: 3};

    Vector::print1(&v); // work
    v.print1();         // work
    Vector::print2(&v); // work
    v.print2();         // not work
    Vector::print3(&v); // work
    v.print3();         // not work
}

print3() 只是用于测试是否可以将self 以外的名称用于方法的第一个参数。

它给出了这个编译错误:

error: no method named `print2` found for type `Vector` in the current scope
  --> 1.rs:27:7
   |
27 |     v.print2();         // not work
   |       ^^^^^^
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: candidate #1 is defined in an impl for the type `Vector`
  --> 1.rs:12:5
   |
12 |       fn print2(&Vector{x, y, z}: &Self) {
   |  _____^ starting here...
13 | |         println!("{} {} {}", x, y, z);
14 | |     }
   | |_____^ ...ending here

error: no method named `print3` found for type `Vector` in the current scope
  --> 1.rs:29:7
   |
29 |     v.print3();         // not work
   |       ^^^^^^
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: candidate #1 is defined in an impl for the type `Vector`
  --> 1.rs:16:5
   |
16 |       fn print3(this: &Self) {
   |  _____^ starting here...
17 | |         println!("{} {} {}", this.x, this.y, this.z);
18 | |     }
   | |_____^ ...ending here

print2()print3() 似乎没有被识别为 Vector 的方法。

  1. 如何解构方法的self 参数?
  2. 根据评论,名字self只是糖。这是否意味着可以将 self 以外的名称用于方法的第一个参数?

【问题讨论】:

  • 第一个参数必须命名为self,如注释中所述。 self 是一个关键字。
  • @kennytm 他说self只是一个糖,那么是不是说第一个参数的名字不一定是self
  • @Laurence:您正在查看的摘录日期为 2014 年 2 月,Rust 1.0 于 2015 年 5 月 15 日发布。在 Rust 历史上看得太远时要小心,因为在 1.0 之前情况发生了很大变化;您提出问题所依据的评论很可能已经过时了。
  • @MatthieuM。是的,这是一个比较老的帖子,但是我没有找到关于这个问题的其他更新的帖子,所以我把它放在这里..
  • @Laurence 而第一个参数必须是 self&self&mut self 才能成为方法,您可以在函数内部进行解构,如下所示:let &Vector{x, y, z} = self;跨度>

标签: rust pattern-matching


【解决方案1】:
  impl Vector {        
    fn print(&self) {
      // destructure self argument
      let Vector { x, y, z } = &self;
      println!("{} {} {}", x, y, z);
    }
  }

【讨论】:

    【解决方案2】:

    这原本打算通过通用函数调用实现,但向后不兼容,因为这意味着fn foo(bar: &Self) 会突然等同于fn foo(self: &Self),这可能会由于突然出现新方法而中断方法调用。

    this github issue comment 中的完整理由

    您可以在函数体中使用let 绑定来解构显式self 参数:

    let &Vector { x, y, z } = self;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      • 2015-06-09
      相关资源
      最近更新 更多