Информация об изменениях

Сообщение Re[12]: Опциональные типы от 03.03.2017 17:16

Изменено 03.03.2017 17:35 vdimas

Re[12]: Опциональные типы
Здравствуйте, D. Mon, Вы писали:

DM>Тут переменные a и b ссылаются на один объект в памяти, это переменные ссылочного типа.


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

В твоём примере a и b — это не ссылочный тип, это специальный тип переменной объектного типа.
Устроена эта переменная с т.з. системы типов примерно так же, как Box<> в Rust.

Для пущего понимания смотри в модуль Array:

val make : int -> 'a -> 'a array
Array.make n x returns a fresh array of length n, initialized with x. All the elements of this new array are initially physically equal to x (in the sense of the == predicate). Consequently, if x is mutable, it is shared among all elements of the array, and modifying x through one of the array entries will modify all other entries at the same time.


Правильно ли я понимаю выделенное, что мутабельная переменная ВСЕГДА имеет ссылочную семантику?
То бишь, сама-то ссылка получается иммутабельная, верно?
А время жизни значения по ссылке обслуживается по GC.
Вот и весь трюк.

Учите матчасть, как грится.
(Сам я первый раз в жизни на это посмотрел — сплошное ЧТД )


DM>Мы вызываем метод, мутирующий объект b


Именно так.
Я тут Владу в соседнем сообщении объяснял:

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

Тебе же специально дали иммутабельный по-умолчанию Nemerle, чтобы ты эффективно боролся именно с подобного рода проблемами — не создавал неинициализированных значений. И тут ты такой — а нате вам протаскивание проблемы прямо в вашу иммутабельность.

http://www.rsdn.org/forum/philosophy/6709456.1

Я говорил о том, что ссылочный тип — это такой тип, который хранит в себе не само значение, а индекс/ключ другого значения.
И единственная возможность избежать невалидного поведения — это рассматривать этот индекс как иммутабельный, т.е. требующий инициализации при объявлении.

Так вот, в твоём oCaml этот самый индекс может быть присвоен переменной лишь однажды.
Даже если переменная якобы мутабельна (медитировать над выделенным выше).

Именно поэтому Box<> в Rust описан как некая структура, внутреннее поле-указатель которого иммутабельно, т.е. присваивается лишь однажды.


DM>Не выйдет, как ни старайся, в языке Окамл ссылки не бывают нулевыми и объекты нуллами.


Индекс не обязан быть 0-м, чтобы быть невалидным.
Просто в OCaml работает GC, и пока на объект есть ссылка, он будет жить.
Вот и весь фокус, повторюсь.


DM>Пример третий: Раст. Там есть ссылки вроде &T, это тоже ссылочный тип, тоже не включает null. Там есть Box<T> ("A pointer type for heap allocation." — первая же строка в описании), который хоть и описан как struct


Так почему он "хоть и описан как srtuct"? ))


DM>на самом деле имеет специальную поддержку со стороны компилятора (см. ключевые слова box, owned_box и пр.) и фактически является указателем с дополнительным поведением. И он тоже всегда ненулевой.


Фактически он является чем описан — структурой.
Аналогом в С++ являются известные тебе умные указатели, которые вводят гарантии сугубо прикладного типа, не даваемые системой типов языка. Т.е., другим способом было бы невозможно выразить вот это "дополнительное поведение".

Смотрю, в Rust умных указателей более одного, например есть slice.
Такой же "умный указатель" с семантикой ссылочного типа, но это НЕ ссылочный тип.
Всё прям как в С++. ))

А в oCamle получается не строгая система типов, а помойка, коль они с мутабельными переменными производят описанный трюк с лишним уровнем косвенности.


DM>Короче, давай засунь null в переменную объектного типа в окамле, в &i32 в Расте и в String в Котлине. Или GTFO.


1. Rust запрещает aliased mutable reference.
Объяснять — почему?
Или уже догадался?
Потому что алиас может стать невалидным в какой-то момент, если "кто-то" грохнет память по той же самой ссылке.

2. Таки в unsafe можно творить что угодно:
fn index(idx: usize, arr: &[u8]) -> Option<u8> {
    if idx <= arr.len() {
        unsafe {
            Some(*arr.get_unchecked(idx))
        }
    } else {
        None
    }
}

Это пример ошибки из доки, в правильной программе должно быть сравнение на строгое '<'.
В итоге, легко получить невалидную ссылку.
ЧТД.


V>>Разве тебя не впечатлило, что я еще в глаза не видя этого Rust сразу сказал, где у тебя ошибка?

DM>У меня что-то с глазами сегодня. Я что-то не вижу ошибки, извини.

Ты ошибся в утверждении, что Box<> — это ссылочный тип.
На самом деле в системе типов языка это лишь некая структура — smart pointer.


V>>Процитированное ты не переплюнешь вааще никак, бо только языки с поддержкой зависимых типов умеют контролировать строгость указателя на уровне типов.

DM>Выше три примера, где языки без зависимых типов именно это и делают.

Ты плаваешь во всех 3-х, что смешно.
Я их в глаза до этого спора не видел, а уже разбираюсь в их системе типов и внутреннем устройстве лучше тебя.
Как так?


V>>Почитал далее — всё ясно. Они разнесли nullable и non-nullable ссылочные типы по ТИПАМ, а не по значениям одного и того же типа.

V>>ЧТД. Нубы. Ниасилили ЗТ. ))
DM>Это я тут должен говорить ЧТД и называть тебя нубом. Ибо тут именно ты сел в лужу.

Ты можешь называть что угодно чем угодно.
Пока что лишь ты путал ссылочный тип с его эмуляцией на типах-значениях.


V>>Потому что T+1 != T+1+1

V>>Дальше озвучивать или уже догадался?
DM>Ты опять вперед забегаешь. Давай сперва начало: Option<T> — это не тип, это конструктор типа, функтор, шаблон типа, генерик (выбери знакомое слово). Покажи, где джавский или шарповый string это генерик.

Таак, что у нас тут? ))
"Генерик"... — вообще не при чём.
Никто не мешает делать "строгие" реализации OptionalString и т.д.

"Конструктор типа"... — это некий параметрического тип + мн-во его типовых переменных.

"Покажи, где джавский или шарповый string это генерик"... — вообще мимо.
Эдаким "генериком" у нас является "null", который приводится и к string и к любому другому типу объекта.

Блин, я вижу ВСЕ знакомые слова, но не вижу смысла во всём сказанном. ))

Кароч, плевать на то, что Option<T> — это генерик. Это не принципиально ни разу.
Намек был на то, что в С++ можно оперировать типами T*, T**, T*** и везде прекрасно работает nullptr, а в C# — нельзя.
Для таких вещей надо создавать уже некую прикладную структуру.
Можно Optional<T>, а можно так:
class Box<T> { public T Value; }


DM>Там плохие, неправильные определения. Они не описывают ссылочных типов как минимум в трех упомянутых выше языках.


Они описывают в Rust.
В oCaml было обнаружено того хуже — получили ссылочную семантику на простых мутабельных значениях.


DM>Давай еще подкину:

DM>4) &int в С++

Ссылка может быть невалидной.


DM>5) ref int в D


Аналогично.


DM>Ссылочные типы? Еще как ссылочные. Содержат null / None / Nothing ? Нет.


// C++
bool isNull(int & x) { return !&x; }

int * a = NULL;
int & b = *a;
cout << isNull(b) << endl;


Лень сегодня еще и на D смотреть, но вангую, что там можно так же.
Re[12]: Опциональные типы
Здравствуйте, D. Mon, Вы писали:

DM>Тут переменные a и b ссылаются на один объект в памяти, это переменные ссылочного типа.


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

В твоём примере a и b — это не ссылочный тип, это специальный тип переменной объектного типа.
Устроена эта переменная с т.з. системы типов примерно так же, как Box<> в Rust.

Для пущего понимания смотри в модуль Array:

val make : int -> 'a -> 'a array
Array.make n x returns a fresh array of length n, initialized with x. All the elements of this new array are initially physically equal to x (in the sense of the == predicate). Consequently, if x is mutable, it is shared among all elements of the array, and modifying x through one of the array entries will modify all other entries at the same time.


Правильно ли я понимаю выделенное, что мутабельная переменная ВСЕГДА имеет ссылочную семантику?
То бишь, сама-то ссылка получается иммутабельная, верно?
А время жизни значения по ссылке обслуживается по GC.
Вот и весь трюк.

Учите матчасть, как грится.
(Сам я первый раз в жизни на это посмотрел — сплошное ЧТД )


DM>Мы вызываем метод, мутирующий объект b


Именно так.
Я тут Владу в соседнем сообщении объяснял:

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

Тебе же специально дали иммутабельный по-умолчанию Nemerle, чтобы ты эффективно боролся именно с подобного рода проблемами — не создавал неинициализированных значений. И тут ты такой — а нате вам протаскивание проблемы прямо в вашу иммутабельность.

http://www.rsdn.org/forum/philosophy/6709456.1

Я говорил о том, что ссылочный тип — это такой тип, который хранит в себе не само значение, а индекс/ключ другого значения.
И единственная возможность избежать невалидного поведения — это рассматривать этот индекс как иммутабельный, т.е. требующий инициализации при объявлении.

Так вот, в твоём oCaml этот самый индекс может быть присвоен переменной лишь однажды.
Даже если переменная якобы мутабельна (медитировать над выделенным выше).

Именно поэтому Box<> в Rust описан как некая структура, внутреннее поле-указатель которого иммутабельно, т.е. присваивается лишь однажды.


DM>Не выйдет, как ни старайся, в языке Окамл ссылки не бывают нулевыми и объекты нуллами.


Индекс не обязан быть 0-м, чтобы быть невалидным.
Просто в OCaml работает GC, и пока на объект есть ссылка, он будет жить.
Вот и весь фокус, повторюсь.


DM>Пример третий: Раст. Там есть ссылки вроде &T, это тоже ссылочный тип, тоже не включает null. Там есть Box<T> ("A pointer type for heap allocation." — первая же строка в описании), который хоть и описан как struct


Так почему он "хоть и описан как srtuct"? ))


DM>на самом деле имеет специальную поддержку со стороны компилятора (см. ключевые слова box, owned_box и пр.) и фактически является указателем с дополнительным поведением. И он тоже всегда ненулевой.


Фактически он является чем описан — структурой.
Аналогом в С++ являются известные тебе умные указатели, которые вводят гарантии сугубо прикладного типа, не даваемые системой типов языка. Т.е., другим способом было бы невозможно выразить вот это "дополнительное поведение".

Смотрю, в Rust умных указателей более одного, например есть slice.
Такой же "умный указатель" с семантикой ссылочного типа, но это НЕ ссылочный тип.
Всё прям как в С++. ))

А в oCamle получается не строгая система типов, а помойка, коль они с мутабельными переменными производят описанный трюк с лишним уровнем косвенности.


DM>Короче, давай засунь null в переменную объектного типа в окамле, в &i32 в Расте и в String в Котлине. Или GTFO.


1. Rust запрещает aliased mutable reference.
Объяснять — почему?
Или уже догадался?
Потому что алиас может стать невалидным в какой-то момент, если "кто-то" грохнет память по той же самой ссылке.

2. Таки в unsafe можно творить что угодно:
fn index(idx: usize, arr: &[u8]) -> Option<u8> {
    if idx <= arr.len() {
        unsafe {
            Some(*arr.get_unchecked(idx))
        }
    } else {
        None
    }
}

Это пример ошибки из доки, в правильной программе должно быть сравнение на строгое '<'.
В итоге, легко получить невалидную ссылку.
ЧТД.


V>>Разве тебя не впечатлило, что я еще в глаза не видя этого Rust сразу сказал, где у тебя ошибка?

DM>У меня что-то с глазами сегодня. Я что-то не вижу ошибки, извини.

Ты ошибся в утверждении, что Box<> — это ссылочный тип.
На самом деле в системе типов языка это лишь некая структура — smart pointer.


V>>Процитированное ты не переплюнешь вааще никак, бо только языки с поддержкой зависимых типов умеют контролировать строгость указателя на уровне типов.

DM>Выше три примера, где языки без зависимых типов именно это и делают.

Ты плаваешь во всех 3-х, что смешно.
Я их в глаза до этого спора не видел, а уже разбираюсь в их системе типов и внутреннем устройстве лучше тебя.
Как так?


V>>Почитал далее — всё ясно. Они разнесли nullable и non-nullable ссылочные типы по ТИПАМ, а не по значениям одного и того же типа.

V>>ЧТД. Нубы. Ниасилили ЗТ. ))
DM>Это я тут должен говорить ЧТД и называть тебя нубом. Ибо тут именно ты сел в лужу.

Ты можешь называть что угодно чем угодно.
Пока что лишь ты путал ссылочный тип с его эмуляцией на типах-значениях.


V>>Потому что T+1 != T+1+1

V>>Дальше озвучивать или уже догадался?
DM>Ты опять вперед забегаешь. Давай сперва начало: Option<T> — это не тип, это конструктор типа, функтор, шаблон типа, генерик (выбери знакомое слово). Покажи, где джавский или шарповый string это генерик.

Таак, что у нас тут? ))
"Генерик"... — вообще не при чём.
Никто не мешает делать "строгие" реализации OptionalString и т.д.

"Конструктор типа"... — это некий параметрический тип + мн-во его типовых переменных.

"Покажи, где джавский или шарповый string это генерик"... — вообще мимо.
Эдаким "генериком" у нас является "null", который приводится и к string и к любому другому типу объекта.

Блин, я вижу ВСЕ знакомые слова, но не вижу смысла во всём сказанном. ))

Кароч, плевать на то, что Option<T> — это генерик. Это не принципиально ни разу.
Намек был на то, что в С++ можно оперировать типами T*, T**, T*** и везде прекрасно работает nullptr, а в C# — нельзя.
Для таких вещей надо создавать уже некую прикладную структуру.
Можно Optional<T>, а можно так:
class Box<T> { public T Value; }


DM>Там плохие, неправильные определения. Они не описывают ссылочных типов как минимум в трех упомянутых выше языках.


Они описывают в Rust.
В oCaml было обнаружено того хуже — получили ссылочную семантику на простых мутабельных значениях.


DM>Давай еще подкину:

DM>4) &int в С++

Ссылка может быть невалидной.


DM>5) ref int в D


Аналогично.


DM>Ссылочные типы? Еще как ссылочные. Содержат null / None / Nothing ? Нет.


// C++
bool isNull(int & x) { return !&x; }

int * a = NULL;
int & b = *a;
cout << isNull(b) << endl;


Лень сегодня еще и на D смотреть, но вангую, что там можно так же.