Re[8]: Опциональные типы
От: vdimas Россия  
Дата: 22.02.17 20:17
Оценка: :)))
Здравствуйте, D. Mon, Вы писали:

V>>А если ты имел ввиду, что "ссылочность" значения прячется от системы типов, то ты в этом случае НЕ можешь рассуждать о ссылочном типе — это будет просто некая тонкость реализации.

DM>Ничего не понял тут.

Например, если значение по ссылке нельзя изменять и ссылка не может быть нулевой, то семантика такого ссылочного типа ничем не отличается от value-типа.

А семантика у ссылочного типа одна — это хранить в себе т.н. "индекс" (или ключ) некоего значения.
Прикладное применение — организация абстракций, — работаем со значением не напрямую, а через индекс/ключ.

Если язык Rust контролирует значение этого индекса через систему типов, то поздравляю — это зачатки зависимых типов в языке.
А если нет, то это не ссылочный тип.


DM>Еще раз: что именно у тебя здесь означает Т+1?


Тоже, что у тебя — сумма типов, т.е. алгебраик {A t:T | B}, где A и B произвольные идентификаторы, например Just и Nothing.


V>>Правда, в этом случае не нужен промежуточный Box<T>, т.е. достаточно лишь Option<T>, не?

DM>Для чего достаточно?

Для семантики Option<Box<T>>.
Это твои слова?

Например, в Расте Box<T> и Option<Box<T>> представлены в памяти одинаково

Ты в них уверен?
Просто я залез, таки, в доку к Rust и вижу:
pub enum Option<T> {
    None,
    Some(T),
}

Обычный алгебраик, но как он реализован в Rust?

Есть же куча способов, например :
struct OptionHolder {
    TypeId discriminator_;    // или int discriminator_
};

struct None : OptionHolder {};

template<typename T>
class Some : OptionHolder { T value_; };

struct Option { OptionHolder * value_; };


— никакого null, значение None будет представлено ссылкой на единственное значение.

Но да, учитывая возможность оптимизации именно такого сценария, когда у нас сумма из двух типов, причем, один из них представлен единственным значением, то кодируем это единственное значение через null, и тогда Some(T) будет хранится в памяти как T*, а None будет просто 0.

Точно ли Rust умеет оптимизировать такие сценарии до описанного?

Потому что вот с таким определением:
pub enum Option2<T> {
    None,
    None2,
    Some(T),
}

уже такой фокус не получится.


DM>Это разные вещи получатся с разным поведением и разным представлением в памяти.


Ты же выше писал, что Option<Box<T>> и Box<T> имеют одинаковое представление?


V>>Ссылочный тип по-определению — это зависимый тип.

V>>Тот самый, угу.
V>>Т.е., тип, зависящий от значения:
V>>* валидный адрес — тип T
V>>* нулевой адрес — тип None.

DM>Стоп-стоп, во-первых у тебя тут Т уже что-то другое начал обозначать.


Почему "другое"?
T — это тип некоего значения по адресу.


DM>Во-вторых, ссылочный тип не обязательно содержит null, я ж об этом говорю. См. тот же Котлин или Раст.


Ссылочный тип обязательно содержит.

Я, таки, посмотрел на Rust только что.
Так вот, Box<T> — это НЕ ссылочный тип ни в одном из мест. Ты меня обманул. ))
Это почти точный аналог моего Strong<T>, который я давал выше.

Вот тебе твой растовский Box<T>, переписанный на Шарпе:
    // ссылочный тип-указатель
    class Ptr<T> where T : struct {
        public T Value;
    }

    // тип-обертка над ссылочным типом, хранящим value-тип
    struct Box<T> where T : struct {
        public Ptr<T> Value { get; private set; }

        public Box(T value) {
            Value = new Ptr<T> { Value = value };
        }
    }

    // тип-обертка над обычным ссылочным типом
    struct Strong<T> where T : class {
        public T Value { get; private set; }

        public Strong(T value) {
            if(value == null) throw ...;
            Value = value;
        }
    }

Обрати внимание на struct Box и struct Strong.
Оба типа хранят внутри себя ссылочный тип, но сами НЕ являются ссылочным типом.
Итого, гарантии соблюдаются не на уровне системы типов, а сугубо на прикладном.
Обрати внимания, что в моём случае невозможно добиться того, чтобы значение (Value) у Box или у Strong было равно null.
В Rust аналогично.


DM>Ну вот есть ссылочный тип string в условной джаве или шарпе.

DM>Мы можем написать string s = null;

Можем.


DM>Теперь напиши Option<string> по твоей задумке, да так, чтобы получилось T + 1, а не T.


String в дотнете и джаве — он уже является Option изкаробки, как любой настоящий ссылочный тип.
Если нужен тип, который достоверно не будет nullable, то используй Strong<string>.
Этот Strong<string> можно создать лишь однажды, а потом передавать м/у методами, распространяя однажды полученную гарантию.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.