Какова цель типа устройства в Rust?

Rust имеет тип единицы измерения (), тип с одним нулевым значением. Значение этого типа блока также указывается с помощью ().

Какова цель типа единицы и ее стоимости? Это механизм, позволяющий избежать использования нуля (или нуля), как в других языках?

Ответ 1

() является значением типа () и его цель - быть бесполезным.

Все в Rust является выражением, а выражения, которые возвращают "ничто", фактически возвращают (). Компилятор выдаст ошибку, если у вас есть функция без возвращаемого типа, но в любом случае она возвращает что-то отличное от (). Например

fn f() {
    1i32 // error: mismatched types: expected '()' but found 'int'
}

Также есть практическое применение для (). Иногда нам не нужен универсальный тип, и () делает это явным.

Например, Result<(), String> может использоваться как тип возвращаемого значения для функции, которая либо успешно завершается, либо завершается с ошибкой по разным причинам.

Ответ 2

Если вы пришли из C-подобного языка (C, C++, Java и т.д.), Вы можете думать о unit как о void. Это тип, который вы возвращаете, когда не хотите ничего возвращать.

Теоретики типов укажут, что единица не похожа на void, потому что единица имеет ровно 1 значение, тогда как void имеет 0 значений.

На практике объем информации, которую вы можете хранить в обоих типах, одинаков (0 бит), хотя в языках, в которых используется единица измерения, работать лучше, потому что вы можете обращаться с ней так же, как с любым другим значением.

Вы можете сохранить его в переменной, структуре, коллекции или в любом другом месте, где вы можете сохранить значение. Вы можете передать в качестве аргумента или вернуть его в результате. Вы можете создать ссылку на него. И т.п.

Итак, когда это полезно? Главным образом, когда вам все равно, с какой ценностью вы имеете дело. Это означает, что вы можете писать полиморфный/универсальный код, не беспокоясь о том, содержит ли значение, с которым вы работаете, какую-либо информацию, то есть вам не нужен особый случай для хранения реальных данных или ().

Одним из примеров того, где это используется, является HashSet. HashSet<T> фактически реализован в виде тонкой оболочки вокруг HashMap<T,()>. (Карта из универсального типа T в ())