Можно ли сделать деструктурирующее присваивание с аннотациями типов? - PullRequest
1 голос
/ 17 мая 2019

Общий вопрос заключается в том, как выполнить вложенное назначение деструктурирования с помощью аннотаций типов. Я умножаю два f32 значения, но я не уверен, что произойдет, если множественные переполнения. Поэтому я хотел бы назначить их как f64 значения, чтобы предотвратить переполнение.

Этот пример слегка изменен из главы Rust By Example по структурам:

struct Point {
    x: f32,
    y: f32,
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

fn area(rect: Rectangle) -> f64 {
    // Here's where I'd like have type annotations
    // while doing destructuring assignment:
    let Rectangle {
        p1: Point { x: x1, y: y1 },
        p2: Point { x: x2, y: y2 },
    } = rect;

    ((x2 - x1) * (y2 - y1)).abs() as f64
}

1 Ответ

1 голос
/ 18 мая 2019

Приведение не может быть выполнено во время разрушения типа. Это потому, что вы не можете аннотировать тип, который будет содержаться в типе, который вы разрушаете, поэтому он не зависит от вас, а вместо этого от типа, который подвергается деструктурированию. Например:

struct Point {
    x: f32,
    y: f32,
}
let myOtherPoint = Point { x: 0, y: 0 };
let Point {x, y} = myOtherPoint;

Типы x и y определяются типом Point. С другой стороны, это можно изменить в случае кортежей и массивов:

fn main() {
    let [x, y, z]: [f32; 3] = [1.2, 2.3, 3.4];
    let (x, y, z): (usize, f32, String) = (1, 2.3, "3.4".into());
}

Это в основном из-за аннотаций типов, необходимых для кортежей при написании сигнатур функций:

fn foo((a, b, c): (usize, f32, String)) {}

Но это только потому, что кортежи сами по себе не являются именованными типами, поэтому существует необходимость именовать кортеж, аннотируя тип. С другой стороны, struct s и enum s названы и поэтому разрушаемы.


Решение вашей конкретной проблемы описано в теле, а не в заголовке:
Используйте отдельную переменную с затенением, чтобы сохранить удобство использования. Также обратите внимание, что типы с плавающей запятой (f32 и f64) не могут быть переполнены ( Они имеют бесконечность ), только целые числа ([u, i][size, 8, 16, 32, 64, 128]).

fn area(x: Rectangle) -> f64 {
    // Here's where I'd like have type annotations
    // while doing destructuring assignment:
    let Rectangle {
        p1: Point { x: x1, y: y1 },
        p2: Point { x: x2, y: y2 },
    } = rect;

    let (x1, x2, y1, y2) = (x1 as f64, x2 as f64,
                            y1 as f64, y2 as f64);

    ((x2 - x1) * (y2 - y1)).abs()
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...