Когда узнал, что в С++ можно использовать Юникод в качестве идентификаторов
Подробнее
I I h v' .h+ + ) No Selection 1 #include "^g.h++" 2 #include "g^.h++" 3 4 class A { 5 public: 6 // $ A f, ^ m) : genderC./ % 2 ? : "<r"), dna(f, m) {> 8 9 // <9 V & + void partner) { auto = *this + partner; 12 if «3» ¿|.push_back( v ) ; 14 > 15 16 //+--=- A* operator+(A& partner) { return this->gender != partner.gender ? new A (this->dna, partner.dna) : nullptr; 19 > 20 21 private: V Gender gender; V dna; std:: vector< A *> Eli’ 24
it-юмор,geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор
Еще на тему
2) это h-файл, у него нет main()
И еще скорее всего в других IDE вместо картинок будут прекрасные □□□□
тока в апострофах
Котлин разрешил все кроме этого :(
btw цейлону и котлину систему типов пилил один чувак, тока в цейлоне он ее сделал правильно, а в котлине как попросили
Один вариант, когда тебе нужно заставить программу скомпилироваться и запуститься, не упав. В принципе не важно, что ты при этом напишешь, кучу if'ов, используешь рефлекшен и т.д.
Другой крайний вариант – это когда ты хочешь получить принципиально другой уровень комфорта от языка и стараешься программировать в стиле «если скомилировалось, значит программа правильная». В этом случае ты начинаешь выжимать максимум из системы типов, как можно реже _менять_ значения переменных и состояние объектов, по возможности избегать null'ов, боже упаси никаких instanceof'ов и т.д. В этой ситуации тебе очень не хватает алгебраических типов.
Если тебя утраивает второй подход, можно обсуждать дальше.
В первом варианте я с тобой соглашусь, что вообще не понятно, в чем проблема. Хотя с wildcard'ами ты конечно наврал.
То, что указатель является на самом деле алгебарическим типом только и позволяет писать нам нетривиальные программы. Но есть много случаев, когда этого не хватает. Например, как ты описываешь файловую систему? В ней есть объекты с путем, которые является либо файлом, лило каталогом и все (упрощенно говоря). Как можно описать это на Java'е? Только предложив вернуть два указателя, один из которых указатель на тип File, а другой – указатель на тип Directory. Комбинируя два указателя (которые, напомню, каждый могут иметь специальное значение null), и договорившись, что из них всегда ровно один ненулевой, мы имитируем то, что должно быть выражено гораздо короче:
наш объект либо File, либо Directory и все. Язык должен поддержать это следующим образом:
позволить присваивать в эту переменную только такой тип, либо конкретные перечисленные типы,
дать возможность написать switch, в котором не будет возможности получить null, сразу два значения, class cast и т.д.
при необходимости проследить, что программист написал case'ы по _всем_ подтипам, ничего не забыв и не компилироваться, если исходный алгебраический тип расширили (сузили, поменял).
Такая необходимость очень часто возникает, когда тебе нужно описать некую сложную структуру данных. Например, очень часто всякие деревья с данными так выглядят, особенно AST, но и файловая система – отличный пример.
1. Пример с файловой системой немного не подходит: директория и файл - суть одно и то же, в Java они так и представлены стандартным классом File.
2. Описанный тобой пример сложных структур напоминает паттерн GoF под названием Composite. Те же Collections в Java как раз и задают композитные структуры, могут иметь различное количество элементов, часть коллекций реализуют красно-чёрные деревья/списки с пропусками (skip-list). Для чётко предопределённых списков значений есть структура enum с очень крутыми возможностями по настройке и возможностью использовать в switch-е.
3. Любая переменная ссылочного типа в Java может быть проверена на null несколькими способами, для пущей надёжности существует структура Optional с рядом доп. возможностей.
4. Теоретически, проблема двух ссылок на файл и директорию может быть сведена к одной параметризованной ссылке (generics), т.к. один объект файловой системы он всегда либо файл, либо директория. Описываем интерфейс FileSystemObject, расширяем его через File и Directory, потом при объявлении параметризованного метода можно сделать следующее:
... |T extends FileSystemObject| ReturnType methodName(List|T| fileSystemObjects) {...} // палками "|" заменил угловые скобки, а то браузер их пытается трактовать как теги
И вот уже на уровне кода ты не передашь ничего, кроме наших элементов файловой системы в виде списка в такой метод, компилятор не пропустит другие типы. Да, можно обмануть эту логику, но только сознательно и хорошо зная механизм работы generics.
5. В Java нет понятия указателя, есть ссылочные типы, которые по сути являются просто хранилищем информации о том, где в памяти JVM (конкретно в части памяти - heap) лежат данные описывающие тот или иной объект. Работа со ссылками всегда производится по одному набору правил, без "переключений режима указатель/значение".
В общем: ты меня заинтересовал темой алгебраических типов, но не убедил, что в Java нет возможности легко решить проблему, решаемую алгебраическими типами или создать свой собственный алгебраический тип.
На самом деле все чуть сложнее, но сейчас это не важно.
Если фанат GoF, то посмотри паттерн Visitor (только именно его изложение в GoF, а не вообще). Вот он в точности о том, как сделать алгебраический тип в Java/C++.
Enum – это список значений (одинакового типа). А мне нужем список типов. Понимаешь разницу? И у enum'ов нет строго switch'а, который проверит, что не забыты никакие case'ы.
В целом, я видел на дженериках такое, что не верю уже в фразы "невозможно" в отношении типов в Java.
Спасибо за полезную дискуссию, не часто в нете натыкаешься на кого-то готового пофилософствовать на подобные темы вместо тупого забрасывания шаблонными фразами. Пойду детальнее изучу тему алгебраических типов, мне кажется, я что-то упускаю в твоих словах.
Не очень советую сильно в это углубляться, потому что сейчас алгебраических типов толком нигде и нет (кроме функциональных языков), если только не для общего образования или любопытства.
Единственный способ написать аккуратно, это передавать в какой-нибудь Optional callback, который будут дергать _только_ если указатель ненулевой и передавать его в параметрах. То есть это можно сделать, если не жалко все время новый объект создавать.
В Котлине кажется есть прямая гарантия, что пока ты не проверил указатель на null, _компилятор_ не даст тебе его дернуть.
Но если мы упростим твою идею просто до базового класса FileSystemObject, то вот что с ним получается:
идея системы типов заключается в том, что когда я добавлю третий тип к этим двум, у меня должны перестать компилировать все места, где я раньше рассчитывал на то, что этих типов только два. Это примерно так, как при добавлении третьего метода в интерфейс перестанут компилировать все точки, где реализовано только 2 метода.
ReturnType methodName(List\T/ fileSystemObjects)
ничего бы не изменилось для нашего разговора.
return mPointer.data;
реальный код: проверяем реальный подтип переменной; если это специальное значение null, то крешимся; если оно имеет значение настоящий указатель, то берем по этому адресу значение; третьего не дано.