- Возможность вернуть более одного результата из функции.
- Дефолтные значения примитивных полей обязать объявлять явно. Модификатор «static» из языка убрать, в качестве static — дефолтный экземпляр, доступный по ссылке на типизированный null. Называть это всё «экземпляром по умолчанию». Возможность модификатора «abstract» для полей, что будет означать как невозможность создать экземпляр класса, так и необходимость задания дефолтного значения этого поля в потомке класса.
- Для «protected», «default» и «public» полей автогенерация сеттеров и геттеров компилятором, без автогенерации видимых сорцов, но с возможностью их перегрузки, «private» убрать из языка, поскольку «сами» поля все и так будут «private» без возможности перегрузки. Добавить «local» — об этом в пункте 8.
- Автогенерация public интерфейсов из всех «public» полей класса, а также новый тип protected и.д. интерфейсов из соответствующих модификатору полей. Типы классов сравниваются по хеш-коду, который будет сгенерирован именами поля, именами аргументов, типами и возвращаемыми значениями, поскольку вероятность совпадения всего этого незначительна и может быть обнаружена во время компиляции с предупреждениями.
Таким образом, больше не нужен «interface» как таковой, только «class», «abstract» — лишь инструкция, запрещающая создание экземпляра. По поводу множественного наследования — в следующем пункте 5. - Добавление правил слияния для «extends». Явно указывать предка для всех конфликтующих полей, которые будут неотличимы от методов, об этом в пункте 8. В результате, объект будет наследовать код и реализовывать все родительские типы. Типы, которые не полностью сохранились в результате мержа — просто исчезают из формальных предков, оставляя код, но создавая ошибку компиляции при попытке ненадлежащего использования объекта.
- Динамические типы. Темплейты как в Си, а не как женериксы в Java. Типизация не пострадает от этого, поскольку динамические типы не могут быть непосредственно использованы в сорцах, но могут использоваться во всех случаях, когда используются базовые типы или рефлексия или темплейты, в которых также не сложно организовать перепланировку расширением типа инстанса прямо runtime, сужение — запретить.
- Подметоды как в Паскале.
- Все методы это полноценные дефолтные экземляры внутренних классов и неотличимы от полей. Для этого конструктор класса вернет значение. Конструктор класса будет телом метода по умолчанию, который будет создан во время компиляции, в соответствии с пунктом 2 «экземпляры по умолчанию». Больше не понадобятся специальные ссылки на метод, как в Java 8. Ссылка на метод будет означать ссылку на объект.
Вызов метода и создание временного объекта только для вызова внутреннего метода становятся идентичными, все это может быть оптимизировано компилятором как простой вызов метода. С другой стороны, создание «метода» оператором «new», для последующих манипуляций ссылкой на него, означает создание нового экземпляра «класса». Присвоение полю ссылки на функцию — прямо через имя метода без скобок, значения функции — со скобками и аргументами в них. Поля с модификатором «local» не сохраняются между вызовами методов.
Все одинаковые методы с различными наборами аргументов обязать группировать в подкласс, чтобы неповадно было замусоривать внешний класс. Дефолтные поля такого подкласса становятся, соответственно, не абсолютно статичными, а статичными относительно внешнего класса. За исключением случая, когда сам внешний класс — дефолтный экземпляр. - Вместо «try»-«catch» также методы, «throws» идентифицирует разрешённый тип вызывающего метода, «throw» делает goto на метод обработчика, срезая callstack, а сами методы-обработчики ничем не отличаются, возврат из них осуществляется в обычном порядке, но, так получается, что в один из предыдущих вызывающих методов. Соответственно, вызывается обработчик на ближайшем уровне иерархии, как это происходит с try-catch. Таким образом, чтобы в случае exception перескочить через некий код, следующий за неким методом, нужно этот код, с этим неким методом в начале, поместить в подметод-класс, в котором перегрузить нужные обработчики. Такой подход существенно укоротит длинноватые, мягко говоря, методы реальных проектов на Java.
«finally» сделать довеском к методу в конце, чтобы без лишних скобок. - Новый оператор для runtime шифрования всяких примитивов и массивов примитивных полей и String и сжатия их в памяти для последующего извлечения их с ключом доступа, оптом для всего экземпляра класса. Чтобы прямо хотелось распаковать-использовать-упаковать в одном методе, а не чесалась голова «как это лучше сделать».
- Массивам нужен контроль границ только во время записи, и я бы дал возможность читать напрямую из памяти без контроля границ массива. Таким образом, учитывая наличие System.arraycopy, контроль границ массива будет осуществляться без ущерба для производительности. Поскольку, большинство дополнительных вычислений чаще всего выполняются во время записи, и, по сравнению с ними, сама запись не занимает много времени.
- Предоставление дополнительной базовой альтернативы синхронизации блокировщиками — самый простой метод в классе Thread, который отправляет кастомные сообщение другим Thread, и метод, через который можно получить кастомные сообщения из других Thread. Кроме того, в методе «run» объекта Runnable, который передается в Thread, требовать явно вызывать метод, прерывающий поток, и, чтобы без этого была ошибка компиляции. Также, добавить метод, который запускает пользовательские события Runnable из других потоков, принимает-отправляет сообщения каждый раз после этого прерывания. Все это принципиально ничего не меняет, но упростит поточно-ориентированную разработку в 90% случаев. Особенно в тех случаях, когда разработка идет на скорую руку, а это большинство реальных случаев.
- Фактически, граф всех объектов в памяти всегда имеет только примитивные типы, массивы или null или ссылку на нечто нативное на всех своих вершинах. Будет очень полезен базовый инструмент, который может сохранять весь этот граф в любой текстовой форме. Большие массивы примитивов могут храниться отдельно, маленькие — закодировать inline. Плюс версия виртуальной машины и — поехали, такая структура может быть восстановлена ??в памяти.
- Полезный инструмент для поиска любых объектов в графе объектов по заданным критериям с учетом модификаторов доступа, по типу простого SQL. Эта задача значительно упрощается с помощью пунктов 1…9. Таким инструментом можно не только упростить иерархию объектов, но и организовать различные тесты и контроль допустимых значений и попытаться догнать Пролог.
Комментарии (98)
0xf0a00
06.02.2019 17:02-1Для «protected», «default» и «public» полей автогенерация сеттеров и геттеров компилятором, без автогенерации видимых сорцов, но с возможностью их перегрузки.
Было бы круто. А если бы делфишный property осилили так и вообще молодцы были бы.mtk0xf Автор
06.02.2019 20:36Глянул делфишные проперти — чего-то там много букв и надо думать, а думать на жаре больно. Кто его знает, может быть вы и правы, не могли бы вы подробнее описать в чём их суть и что она привносит?
khim
06.02.2019 20:55Возможноcть не писать бесконечные геттеры и сеттеры в Java-стиле. Они же есть и в C#.
Property — это такое псевдополе класса при попытка записи в которое вызывается соотвествующая функция, а при попытке чтения — другая (в частном случае одной из них может не быть, тогда чтение или запись осуществляются «напрямую»).
В Java вам на каждую переменную нужно создавать две функции, чтобы было «по феншую». Геттер и сеттер. Даже если эти функции ничего не делают с переменной, просто кладут её в поле класса и вынивают из него.
Дальше — бесконечные автогенераторы и прочая мура.
В C# (и, как прародителя, но не изобретатели, этой фичи, в Delphi) вы просто объявляете переменнуюpublic
— и… всё. А если позже оказывается, что всё-таки нужно что-то делать при изменения поля — то вместо этого поля заводится property.
Это лучше вашего предложения более естественным синтаксисом. Ну можноwindow.width = 125;
выглядит понятнее, чемwindow.setWidth(125);
mtk0xf Автор
06.02.2019 21:06У меня была мысль, что поля можно модифицировать и читать напрямую из родного класса, благо классы должны получаться малюсенькими, т.е. синтаксис присваивания уже занят и, если его использовать, то уже надо что-то придумывать для родного сеттера и геттера. Кроме того, у мне была мысль, что все поля private, т.е. в наследниках доступны только сеттеры и геттеры, а пишутся и читаются только свои. Поля с именами, идентичными таким же в предке, я бы не давал делать, это в Яве чего-то мешающая ерунда какая-то.
Throwable
07.02.2019 16:48С присваиванием все просто — доступ к полю приоритетнее, и тогда ничего из уже написанного не сломается. И даже хрен с ним уж с присваиванием — пусть так и оставят setXXX(). Главная задача пропертей — это добавить сахорочку и уменьшить бойлерплейт на этапе определения объекта. Потому как более чем в 99% случаем все ваши геттеры-сеттеры — это тупо автогенерация доступа к полю. Для всех остальных случаев оставить обычный фолбэк в геттеры-сеттеры.
Сейчас для создания одного! свойства в Java приходится писать его имя 7-12 раз, его тип 3 раза, 2-3 раза повторяющийся джавадок и в общей сложности используя 19+ слов. Это есть настоящий идиотизм.
Кроме того, я устал от классов и хочу, чтобы все было интерфейсом, и чтобы проперти можно было описывать и там.
mtk0xf Автор
07.02.2019 18:11Дело в том, что тут вообще не Ява обсуждается, даже не типа того, что Ява это далеко не Си, а ещё дальше. По всей видимости, абсолютное большинство не понимает сути написанного, но статья получилась случайно и я был очень ограничен во времени, когда писал, хотя, с другой стороны, даю гарантию, что продумывал эту парадигму много лет и могу ответить-скорректироваться по существу.
В парадигме и есть всё как бы интерфейс. Точнее, типизированый объект, для которого список интерфейсов отслеживается виртуальной машиной, механизм описан в пункте 4. В парадигме вообще нет ничего кроме единственной конструкции со скобками. Ни классов, ни методов, ни явных интерфейсов, но объекты типизированы и морды у них вполне абстрактные. Плюс, Си образная внутренность метода, в которой уже есть и поля и прямое присваивание и прямое считывание того, что доступно для данных операций внутри этого маленького объекта. Просто, в этот метод затесались другие методы как в Паскале, ну и не local переменные можно конечно вынести в шапку. «throws» просто идентифицирует тип вызывающего метода чтобы в случае exception срезать стек даже без создания нового объекта и без выделения памяти (в случае outOfMemory смешно, да?), а в методе-обработчике этого exception об этом throw и срезаниии узнают только косвенно из аргументов, дальше — нормальное возвращение в вызывающий метод своего «класса». Этот обработчк — тоже просто метод, который принимает какие-то аргументы и сообщения.
Вот выдержка из текста обсуждения по поводу пропертей:
«Представляете, как выглядит текст такой программы? Он совершенно не похож на то, что в Delphi и Java и в C++. Он — что-то типа Лиспа, очень малое соотношение числа строчек кода к числу типов. Фактически, нижнему по иерархии классу чаще всего придётся работать с единственным полем. Поскольку, класс-метод, который уже что-то делает вразумительное, скорее всего будет внешним. В таком случае, разве, одних внутренних же методов не достаточно (без своих полей вовсе)? ».
«Больше всего памяти занимают массивы. Логика это такая вещь, которая памяти не потребляет и чем больше будет ООП, связанного с логически важными переменными, тем лучше. Это основное.
Ньюанс, мало влияющий на основное, но, всё же: в современных проектах на Java и так все поля спрятаны private и, хотя не все из них имеют геттеры и сеттеры, но, очень часто — большинство. Неявную же автогенерацию set/get легко оптимизировать простым флагом для случая отсутствия явно объявленного метода. Доступ виртуальной машины к полям класса и так не прост, это вам не доступ по адресу.»mtk0xf Автор
07.02.2019 19:14Пункт 2 кому-то был непонятен. Вместо статичных классов и полей — объекты по умолчанию. Внутренние объекты по умолчанию, таким образом, будут как бы статичными только для себя, по отношению к своему внешнему классу, т.е., если внешний класс сам статичный и так до первого предка, то — статичные абсолютно. Т.е., при запуске создаются полные статичные структуры и больше ничего, которые можно клонировать либо оператором new, либо вызывать как обычные методы, если ссылки на объект не нужны. Все не-local поля, при этом, разумеется, создавать тоже как local, считывая значения по умолчанию, ссылки-то не нужны. Таким образом, «конструктор» выделяет память для всех своих переменных, что ежу понятно, а когда дёргает поля внешнего класса — не выделяет память, что тоже ежу понятно. Для того он их дёргает, чтобы быть в связке с состоянием внешнего «метода-класса». Таким образом, из внешнего класса можно считать дефолтные значения любого внутреннего класса — они получаются как бы статичными для самих себя (см начало).
По поводу NPE: «аbstract» модификатор полю означает NPE при попытке считать дефолтное и невозможность создать экземпляр содержащего класса без явного задания этого поля. При попытке считать ссылки на явно не инициализированные объекты — доступ к дефолтному объекту этого типа, а все примитивы обязаны либо явно инициализироваться, либо объявляться abstract.
tuxi
06.02.2019 21:09-1Это лучше вашего предложения более естественным синтаксисом. Ну можно window.width = 125; выглядит понятнее, чем window.setWidth(125);
public void setAnything(Object mayBeNull) throws IllegalArgumentException { if (mayBeNull == null) throw new IllegalArgumentException("Everything you can imagine is real (c) Pablo Picasso"); this.canNotBeNull = mayBeNull; }
mtk0xf Автор
06.02.2019 21:19а что можно написать вместо этого, если нужно проверить на nil?
tuxi
06.02.2019 21:24В парадигме «window.width = 125», на null придется проверять вне модифицирующего метода. Инкапсуляции не станет. И наступит хаос…
PS: причем null это еще не самое страшное. Вот классический пример из википедии
то есть ексепшена в будущем от использования null не будет, зато влегкую может быть нарушена бизнес логика при obj.hours = 25 или obj.hours = -12public void setHours(int hours) { if ((hours >= 0) && (hours < 24)) this.hours = hours; }
khim
06.02.2019 21:38Хаос наступает, если большинство указателей могут быть указателями на
null
.
В C++ для этого есть ссылки. В Kotlin — nullable классы. А в Java — да, хаос. Но не из-за properties, а из-за того, что в любую дырку можноnull
засунуть, а потомпыль глотатьexception'ы ловить.tuxi
06.02.2019 21:42я чуть позже привел пример с примитивами
khim
06.02.2019 22:05Ваш «пример с примитивами» как раз легко обрабатывается с помощью
properties
. Они как раз для подобных случаев и нужны.mtk0xf Автор
06.02.2019 22:19Мне нравится однозначность в языках, это когда то, что ты видишь, то и делается. А не как в Си++ в котором можно перегрузить вообще всё так что не поймёшь на каком языке написано. Это перебор. Когда сеттер это сеттер, то после любого копипаста никаких скрытых синтаксических изменений не будет. Что если я из внешнего класса скопирую во внутренний это присвоение, которое раньше было сеттером, и наоборот. Это очень неудобно с моей точки зрения.
khim
06.02.2019 22:36Когда сеттер это сеттер, то после любого копипаста никаких скрытых синтаксических изменений не будет.
Вот только потом возникает желание эти сеттеры наавтогенерировать и получаем «те же яйца, вид сбоку» — только ещё и хуже читабельность.
Что если я из внешнего класса скопирую во внутренний это присвоение, которое раньше было сеттером, и наоборот.
А это тут вообще причём?properties
всегда действуют.mtk0xf Автор
06.02.2019 22:47В методе который дёргается снаружи можно проверять всё что угодно и делать всё что угодно вплоть до логирования. Внутри класса, если класс маленький, нужен прямой доступ к переменной, а если класс большой, то лучше запасаться консервами в ожидании ядерной зимы. Не так?
khim
06.02.2019 22:53Если вы используете
property
то у вас вызывается один и тот же код всегда.mtk0xf Автор
06.02.2019 23:22Т.е, как, всё-таки, это может уживаться с работой изнутри родного класса? Тут по существу вложенные методы просто, очень маленькие классы. Проперти у меня из памяти конечно выветрились, но большие такие классы Делфи я помню, поскольку даже Паскаль не мой первый язык. Там обычно, да и в Яве сейчас очень и очень часто, такая большая сарделька которая понятно как образовалась — люди ночами не спали домой убежать мечтали а их тимлид не пускал. В таких условиях польза от пропертей очевидна, я в таких классах даже локальные копии всегда в методе устраиваю, чтобы потом слить всё что надо, а тут я попытался уйти от этой истории. Тут куча мелких вложенных классов как в Лиспе что ли.
mtk0xf Автор
06.02.2019 22:10В каком будущем, это о чём? В Яве сейчас есть. Каким образом стало «obj.hours = 25 или obj.hours = -12»? И каким образом бизнес логика, явно заданная вот этим вот сеттером, может быть нарушена, если null будет иметь дефолтное значение? С моей точки зрения, если часы обнулятся по дефолту, то это лучше всего остального. Так ведут себя любые часы.
По поводу первого — так я и не спорю, мне сеттеры и проверки на null очень даже нравятся когда такие проверки нужны.tuxi
06.02.2019 22:31Ну если не нравится пример с часами, замените их на myBankDepositAmount и присвойте ему -USD100500,00 :)
mtk0xf Автор
06.02.2019 22:41А о чём вообще речь?
khim
06.02.2019 22:43О том, что кто-то пытается обсуждать проблему
properties
не имея ни малейшего представления о том, как они работают…tuxi
06.02.2019 22:49Я не очень понимаю профита от модели property в дельфи. Например, как я сообщу внешнему миру, что полученные данные не валидны? Не молча проигнорирую, а именно «кину наверх» ошибку с внятным описанием/типом?
khim
06.02.2019 22:54Так же, как и в случае с сеттерами в Java. Exceptions никто не отменял.
tuxi
06.02.2019 23:11И как по вашему будет визуально выглядеть такой код? Я честно не понимаю, почему try { obj.amount = 100 } catch () {} более читабельный нежели чем try { obj.setAmount(100) } catch () {}
Второе: если я правильно помню, в дельфи остались те же самые геттеры и сеттеры. То есть мы можем реализовать изменение значения поля обьекта двумя путями, верно? Вы считаете это повышает читабельность кода?khim
07.02.2019 00:25То есть мы можем реализовать изменение значения поля обьекта двумя путями, верно?
Неверно.
Вы считаете это повышает читабельность кода?
Да. Именно потому что вы не можете присвоить значение полю иначе, как черезproperty
(даже методами внутри класса) вы можете быть уверены в том, что инварианты, связанные с этими полями всегда сохраняются.mtk0xf Автор
07.02.2019 02:09Всё же в Delphi property присущи только классу, а не подпрограммам. Мне же хотелось как раз уйти от такой объектной модели. Property наверное очень полезны, но вот как будто абсолютно очевидно, что внутри очень маленьких классов они абсолютно излишни. Кто знает, кто знает
khim
07.02.2019 02:21Если вы хотите узнать как использовать проперти — ну загляните, наконец, в учебник.
Да, вы можете сделать так, чтобы был «задний быстрый» проход. Нет, делать так не следует.
Copy-Paste смысл ваших опереаций не поменяет. И проверки при переносе куда ниоткуда не возникнут.mtk0xf Автор
07.02.2019 02:46По вашей ссылке написано ровно то, о чём я написал сообщением назад. В остальном, причём здесь синтаксис Делфи? Как это будет с точки зрения процессора, виртуальной машины? От простой мысли, что, скорее всего, в изложенной мною модели это избыточно и неудобно, вы прячетесь как чёрт от ладана, хотя уже можно было формализовать всё, что угодно. Чувак за время нашего с вами общения уже написал двадцатую часть javaScript, а мы топчемся на месте. Так работать нельзя. Не хочу я работать так. Ни с кем, и хорошо, что я с вами ещё не работаю, а жаль, что придётся — если не с вами, то с кем-то таким же, придётся вас гипнозом менять. Вы поддаётесь гипнозу? Что на вас действует? Жёлтые штаны?
NeocortexLab
07.02.2019 14:29То же, что и на вас — лекции профессора Савельева. Киньте ему ссылок. Он въедет в тему и изменит парадигму мышления. 146%!
mtk0xf Автор
07.02.2019 14:31Для начала вам придётся увязать нечто из этих лекций с тем, что тут. Понимаете, что мне не нравится и вашем посте также — ссылки на какую-то сакральную информацию. Информацию нужно уметь презентовать, увзязывая с интересом слушателей. Иначе это баг мышления.
NeocortexLab
07.02.2019 14:36А что здесь — типичное поведение среднестатистического мозга — упорство и нежелание принимать новое, т.к. оно порождает кучу «ненужной» работы — «ведь и так всё бегает, не надо трогать же, не упадёт». Экономим энергию, не вчитываемся, ставим минус просто потому, что сегодня настроение плохое и вообще — о чём этот автор пишет? ой, тут надо подумать, да ещё и много… какое хамство! минус в карму, быстро, решительно, сжечь до тла-а-а! а потом можно пить кофе с 5 ложками сахара — порадовать своего многоклеточного жителя черепушки с прожилками выгоревших навсегда нейронов.
tuxi
07.02.2019 10:56Все же я плохо помню парадигму пропертей в дельфи, но если она точно подразумевает невозможность создания дублирующих явных геттеров и сеттеров, а также возможность указать только read или только write, плюс можно будет красиво и читабельно оформить в сигнатуре несколько эксшепшенов с разными «типами», то почему бы и нет.
Но все же хотелось бы взглянуть на то, как это могло бы выглядеть на примере. Что то мне подсказывает, что простых красивых конструкций мы не получим.0xf0a00
07.02.2019 12:34TSomeClass=class(Tobject) FStr: string; FAStr: array of string; procedure SetStr(A: string); function GetStrByIndex(I: Integer): string; public PStr: string; property AStr[I: integer]: string read GetStrByIndex; property Str: string read FStr write SetStr; end; { TSomeClass } function TSomeClass.GetStrByIndex(I: Integer): string; begin Result:=FAStr[I]; end; procedure TSomeClass.SetStr(A: string); begin Self.FStr:=A; end;
Вот простой пример использования property. Что вам конкретно не понятно или смущает в этом механизме?mtk0xf Автор
07.02.2019 13:19На самом деле, так получилось, что я property использовал 15-20 лет назад в Delphi и мне сразу показалось, что в изложенной мной модели это обыгрывается всё тем же внутренним методом, поскольку внутри этого маленького «метода-класса» все филды — private. Что может быть проще? Так или не так?
Поскольку, за основу я взял труп Java и final не убирал, то, в итоге, объявить final «класс-поле» и филд внутри, примитивный или опять ссылку — не проблема.
Перегружать синтаксис присваивания мне кажется неуместным тут. Это всё же методы, а внутри них — всё же настоящие присваивания своим филдам.
Просто, ваше замечание по существу было одно и первых и в такой категоричной форме, что хотелось услышать расширенный комментарий в контексте обсуждаемой темы, а не в контексте Java или Delphi. Потому что property есть не только в Delphi, да и Delphi за много лет мог поменяться, и вообще, мало ли кто и что может придумать.0xf0a00
07.02.2019 13:33Для «protected», «default» и «public» полей автогенерация сеттеров и геттеров компилятором, без автогенерации видимых сорцов, но с возможностью их перегрузки.
Вы попросили возможность писать напрямую в переменные + возможность перегрузки автосгенерированных методов и на этом все. Но property это не просто перегрузка метода присвоения, это и возможность ограничить только чтение или только запись в переменную на уровне компилятора, возможность забрать/записать переменную из массива/списка по индексу.
Полный список возможностей в примере
1.Property Name : Type read Getter|nodefault; 2.Property Name : Type write Setter; 3.Property Name : Type read Getter write Setter; 4.Property Name : Type Index Constant read Getter {default : Constant|nodefault;} {stored : Boolean}; 5.Property Name : Type Index Constant write Setter {default : Constant|nodefault;} {stored : Boolean}; 6.Property Name : Type Index Constant read Getter write Setter {default : Constant|nodefault;} {stored : Boolean}; 7.Property Name[Index : IndexType] : BaseType read Getter {default;} 8.Property Name[Index : IndexType] : BaseType write Setter; {default;} 9.Property Name[Index : IndexType] : BaseType read Getter write Setter; {default;} 10.Property Name : Type read Getter implements Interfaces...; 11.Property Name; // Повторно объявленное свойство базового класса 12.Property Name : Type; // Только Dispinterface 13.Property Name : Type readonly; // Только Dispinterface 14.Property Name : Type writeonly; // Только Dispinterface
mtk0xf Автор
07.02.2019 13:49Тут ньюанс в пункте 8 статьи. Представляете, как выглядит текст такой программы? Он совершенно не похож на то, что в Delphi и Java и в C++. Он — что-то типа Лиспа, очень малое соотношение числа строчек кода к числу типов. Фактически, нижнему по иерархии классу чаще всего придётся работать с единственным полем. Поскольку, класс-метод, который уже что-то делает вразумительное, скорее всего будет внешним. В таком случае, разве, одних внутренних же методов не достаточно (без своих полей вовсе)?
Может быть, есть смысл как-то дополнительно информировать пользователей класса о чём-то?khim
07.02.2019 14:33Фактически, нижнему по иерархии классу чаще всего придётся работать с единственным полем.
Цель какая? Сделать из Xeon'а Arduino? Вы не забываете, что одно обращение в память занимает столько же времени, сколько 300-400 арифметических операций (нет, тут нет ошибки в нулях). Ну и про потребление памяти на вот-это-вот-всё тоже не стоит забывать. А то Electron получится.mtk0xf Автор
07.02.2019 15:09Категорически не согласен. Больше всего памяти занимают массивы. «Property» (в общем смысле) это такая вещь, которая памяти не потребляет и чем больше будет ООП, связанного с логически важными переменными, тем лучше.
tuxi
07.02.2019 14:21Обсуждение возникло из предпосылки «Возможноcть не писать бесконечные геттеры и сеттеры в Java-стиле.»
«Или я чего то не понимаю, или одно из двух», но в приведенном выше примере количество текста не меньше, нежели чем в классическом варианте getA(), setA(String A)
И как будут выглядеть проверки для сеттера и пробрасывание наверх 1...n эксепшенов?mtk0xf Автор
07.02.2019 14:50а. У меня обсуждение возникло из пункта 3 статьи выше. В этом пункте самые примитивные сеттеры и геттеры я уже убрал автоматизацией с возможностью перегрузки для чего-то более сложного, тем самым, бесконечными они быть перестали. Причём, автоматизировано было даже NPE, пунктом 2. Потому что достаточно обернуть поле одноимённым «классом» и добавить полю модификатор abstract. Ни присвоить абстрактному полю «статичное, по умолчанию» значение (пункт 2 и пункт 8.3), ни создать объект для присвоения без явного объявления значения — не получится. Попытка обращения к этому abstract полю по ссылке на содержащий его дефолтный объект — тоже NPE, этого я не убирал.
б. Наверное, это может быть удобно для больших Ява классов тем, что дисциплинирует и не даёт возможность обходить сеттеры и геттеры, но я не хочу тут разбираться с другими парадигмами без связи с той парадигмой, которая изложена в статье.
в. Проверки абcолютно так же, как в Java, если понадобятся. Ексепшены описаны в пункте 9. Когда я статью писал, я старался думать как раз ну уровне процессора и виртуальной машины, а не просто поток мыслей выкладывал, как кому-то могло показаться.khim
07.02.2019 15:19В этом пункте самые примитивные сеттеры и геттеры я уже убрал автоматизацией с возможностью перегрузки для чего-то более сложного, тем самым, бесконечными они быть перестали.
От того, что вы их не видите — они бесконечными быть не перестали. Они по-прежнему отжирают память и время исполнения (да, конечно, JIT-компилятор может с ними бороться, но во время запуска и остановки приложений — а это больное место Java вообще — всё это вылазит).
Что вы там убрали пунктом 2 — я, если честно, не понимаю, по-моему вы просто заменили хорошо видимую проблему, на ошибку в логике программы — что добром не кончается.
Когда я статью писал, я старался думать как раз ну уровне процессора и виртуальной машины, а не просто поток мыслей выкладывал, как кому-то могло показаться.
Если бы вы обращали внимание на процессор и виртуальную машину — то хотя бы приблизительно прикинули сколько будут стоить все ваши «улучшения».
Если вам нужен язык в 10 раз более прожорливый по памяти и в 100-1000 раз медленнее — то таких уже есть. Много. Разных.mtk0xf Автор
07.02.2019 16:01Вы повторились, не ответив на моё сообщение «Категорически не согласен». Немного перефразирую. Больше всего памяти занимают массивы. Логика это такая вещь, которая памяти не потребляет и чем больше будет ООП, связанного с логически важными переменными, тем лучше. Это основное.
Ньюанс, мало влияющий на основное, но, всё же: в современных проектах на Java и так все поля спрятаны private и, хотя не все из них имеют геттеры и сеттеры, но, очень часто — большинство. Неявную же автогенерацию set/get легко оптимизировать простым флагом для случая отсутствия явно объявленного метода. Доступ виртуальной машины к полям класса и так не прост, это вам не доступ по адресу.
Т.е., ваше утверждение о прожорливости и медленности такой модели пока не доказано.mtk0xf Автор
07.02.2019 16:06Кроме того, в пункте 11 предложено читать массивы напрямую из памяти без проверок. Вы представляете, какой прирост производительности с этим может быть связан в проектах, манипулирующих массивами данных, ещё и во всяких циклах?
mtk0xf Автор
07.02.2019 16:31«Не доказано» это мягко сказано. Вообще, не понятно, как человек, претендующий на опыт в программировании, может делать такие порядковые ошибки в оценках («10, 100, 1000»), не понимать, на что в проектах уходит память со времён malloc. Либо он сильно ангажирован и работа с ним невозможна, либо он не имеет достаточного опыта в разработке.
Опять же, риторика. Вы весьма невежливо сообщили, что не понимаете нечто в пункте 2, намекнув на некую логическую ошибку. Логическая ошибка это противоречие, на которое нужно указать явно, иначе непонятно, что конкретно нужно уточнять. Указать на противоречие можно помощью цитирования предположительно противоречащих друг другу утверждений собеседника — это самый простой способ. Иначе, утверждение «всё, что там написано — логическая ошибка» будет называется ложным.
khim
07.02.2019 15:05«Или я чего то не понимаю, или одно из двух», но в приведенном выше примере количество текста не меньше, нежели чем в классическом варианте getA(), setA(String A)
Все приведённые примеры описывают редкий случай, когда геттеры/сеттеры и/илиproperty
реально нужны.
В случае если они не нужны — вы заводитеpublic
поле — и всё. Вот совсем всё.
Потребуется обработка или контроль доступа — заведётеproperty
. А поскольку любой, заведённый вамиproperty
делает нетривиальную обработку — то «автогенерация сеттеров и геттеров компилятором» ну нужна. От слова совсем.
Безproperty
вы этого сделать не можете, так как код из «window.width = 125» в «window.setWidth(125)» автоматически не превратится.mtk0xf Автор
07.02.2019 15:23Обращение к паблик полям убивает полиморфизм на корню. Поля в изложенной парадигме private автоматом без объявлений, и в стандарте Java не случайно тоже private.
Контроль доступа потенциальный или явный нужен всегда для внешних обращений и никогда для внутренних, в случае методов. Контроль доступа к локальной переменной метода это наверное даже вообще абсурд, мне уже так хочется это называть. Пунктом 1 статьи идёт возможность возвращения более одного результата вычислений. Формально это не сделано, но фактически не-local поля в этой парадигме и выступают таковыми результатами, по совместительству с композицией.
Поэтому, ваше утверждение что "«автогенерация сеттеров и геттеров компилятором» ну нужна" кажется мне верным только если не исправлять опечатку «ну»
0xf0a00
07.02.2019 15:07getA не будет если вам нужно просто значение переменной FStr, потому что указано read FStr
property Str: string read FStr write SetStr;
Отличается тем что мне еще PStr надо обязательно get и set написать итого вместо 4 я написал один, и только потому что мне нужна была проверка.
Но вся прелесть в том что при прямом доступе к переменным я могу и писать как в Java (set/get все приватное) или через доступ напрямую… или же сочетать оба подхода с помощью property.
А чем будет отличаться обработка ошибок в неявно вызываемом методе от обработки ошибок в любом другом коде?
tuxi
06.02.2019 22:43О том, что я могу реализовать любой механизм защиты от поступающих данных при использовании сеттера и мне не придется его дублировать. Я не позволю какому нибудь скедулеру запуститься в некорректное время. Я обеспечу целостность и адекватность поведения того кода, который я реализовал в своем классе.
khim
06.02.2019 22:42property
диагностирует ошибку и всё, в чём проблема?
P.S. По крайней мере стало понятно почему никто не хочет ничего тут всерьёз обсуждать. Когда об «революции», то есть изобретении нового языка начинает рассуждать кто-то, кто вообще кроме Java ничего не видел — это не смешно. Это грустно.mtk0xf Автор
06.02.2019 22:56Да я вообще маньяк порассуждать, я просто не могу строчить чаще чем раз в пять минут, а скоро меня заминусуют непонятно за что непонятно кто и раз в час только смогу:) Я правда вот так думаю, как там написал. Конструкции что-то диагностирующие наверное гуд, но сеттеров то они не отменяют, пока я не вижу способов как properties могут отменить сеттеры. Кроме того, я, зная себя, буду в сеттерах дублировать все проверки, если сеттеры понадобятся для чего-то ещё, такой я тормоз. Вообще, сильная стороны Java в том, что она для тормозов. Даже тысяча тормозов могут за очень много денег поддерживать очень тормознутый проект, и это реальная сила потому что многие компании имеют деньги, но не имеют гениев в своём штате. Революция устроил не я, а интервьювер, которому мне всё это в черновом варианте на английском пришлось строчить. Вот и вошёл во вкус.
Т.е, главный вопрос, который мне неясен. Как большое количество проверок может уживаться с работой с полем изнутри родного класса? В сеттере-то много всего, не будешь же это всё каждый раз проверять, особенно если у тебя по существу вложенные методы просто, а не большие объекты со словарями полей
mtk0xf Автор
06.02.2019 23:36Что же до дефолных значений, то и 0 денег по дефолту никого не обидит, если код вдруг начнёт кодить бывший гений после автокатастрофы. Тем более что в Яве int как назло неявно ноль по дефолту, я же как раз предлагаю уйти от этого неочевидного но вероятного — как раз задать явно этот нужный банку NPException по дефолту, архитектор-то у проекта был до автокатастрофы. В остальной куче проектов, в 99%, в которых просто зайчик на экран не успел подпрыгнуть и от того null, все эти важности совершенно ни к чему, они сильно тормозят и отнимают время. Даже для банков такая щепетильность не везде хороша. Видел я эти бесконечные
Exceptions по любому поводу в Грузинских банкоматах.
kzhyg
06.02.2019 17:02-1> Неопределённое поведение вместо NPE
На этом месте я прослезился. Отличный пятничный пост.mtk0xf Автор
06.02.2019 20:02>Неопределённое поведение вместо NPE
Ну так по дефолту же всё требуется задавать и тоже инструменты есть чтобы не дать не задавать, не говоря у же о самих NPE, которые никто не мешает создать и использовать проекту во благо. Просто, по моему опыту, 90% этих NPE от того, что забыли инициализировать какие-то дефолты.
stranger_shaman
06.02.2019 17:49Да это же описание языка Scala и модели акторов
mtk0xf Автор
06.02.2019 19:46+1Это круто, статья не пропала даром, придёться изучать Scala — найду либо отличия, либо язык, на котором хочу писать.
khim
06.02.2019 19:51Это описание чего угодно, только не Java.
Один из лучших способов убить любой язык программирования — выпустить новую версию, несовместимую с существующим кодом.
Кажется самое страшное, что случалось с распространёнными языками — это переход от python2 к python3.
Visual Basic (переход от классической версии к Visual Basic .NET) — это не совсем то: после ~15 лет «клинической смерти» (когда программисты, пользовавшиеся классику уже ушли, а новых ещё было мало) он снова начал набирать популярность… Но это уже другие разработчики, они решают совсем другие задачи…mtk0xf Автор
06.02.2019 19:55-2Лучший способ убить мой мозг это не понимать моих и так дурацких шуток.
GBK
06.02.2019 23:45Если столько можно сделать улучшений, то почему бы не сделать новый язык?..
mtk0xf Автор
07.02.2019 00:21Тоже считаю, что очевидный прогресс велосипедной техники невозможен без изобретений. Вкладывайтесь, я освою. Вообще, сторонние фреймворки хороши до определённого момента, после они очевидно тормозят развитие, но от них уже не отказаться. Любой большой проект уже содержит в себе новую семантику и свой фреймворк, иначе ему не стать большим, либо стать большим за нереальные деньги, видел я такой — собирается сутки. Тысяча кодеров по чуть-чуть копаются в меркуриале. Сколько это всё стоит мне страшно себе представить. Красота природы в том, что мне после этого проекта достался по наследству визуально очень похожий и по схожей тематике, но по началу я кодил его… один бедняжка. Т.е., по множеству функций, которые юзер дёргал, с первого взгляда он был не намного проще того гигантского. Конечно, это только с первого взгляда, но я был в начале и в конце лавины и это впечатляет. Технологии и в первом и во втором практически идентичные. Ява это очень солидный язык.
konsoletyper
07.02.2019 12:50Модификатор «static» из языка убрать, в качестве static — дефолтный экземпляр, доступный по ссылке на типизированный null.
Какова практическая необходимость такого изменения? Вон, люди в Kotlin наоборот плюются от отсутствия static.
Типы классов сравниваются по хеш-коду, который будет сгенерирован именами поля, именами аргументов, типами и возвращаемыми значениями,
Т.е. структурная типизация как в go и typescript вместо существующей номинативной? А зачем?
Таким образом, больше не нужен «interface» как таковой, только «class», «abstract» — лишь инструкция, запрещающая создание экземпляра
Да, но как тогда вы в методе будете указывать, что переданный параметр должен обладать такими-то свойствами? Для этого нужно будет вводить синтаксис для описания анонимного типа-структуры. А потом и тайпалиасы прибегут (что и будет аналогом интерфейсов). Я кстати ещё молчу про перфоманс instanceof/checkast. Ну и да, это не просто языковое изменение, тут JVM придётся выкинуть.
Добавление правил слияния для «extends».
Ага, т.е. множественное наследование реализаций? А как будет реализовываться vtable? Через ужасные трюки как в C++, с нескольми указателями на vtable в каждом инстансе? С неизбежным ростом размера заголовка объекта? А как при этом обеспечивать identity equality?
Динамические типы. Темплейты как в Си, а не как женериксы в Java
И как это будет работать с variance? Изобретать неявные преобразования, как в C++?
Больше не понадобятся специальные ссылки на метод, как в Java 8. Ссылка на метод будет означать ссылку на объект.
Простите, а как при ссылке на overloded-метод должен резолвиться метод с конкретной сигнатурой?
Чтобы прямо хотелось распаковать-использовать-упаковать в одном методе, а не чесалась голова «как это лучше сделать».
Практика показывает, что голова начнёт чесаться при решении задачи каскадной упаковки, а именно где остановиться и как это правило сформулировать.
Массивам нужен контроль границ только во время записи, и я бы дал возможность читать напрямую из памяти без контроля границ массива.
Чтение за границами массива — это в 99% случаев не то, чего мы реально хотели, а значит — ошибка. Одним из принципов дизайна Java является fail fast, что, исходя из моего опыта (и из чужого опыта — тоже), является благом. Проблема производительности решается в данном случае JIT-компилятором, который может сделать range analysis и доказать, что проверка не нужна. Они, конечно, слабоваты эти range-анализы, но на практике если у вас такой сложный код, что в нём сложно что-то доказать, то в нём и проверка на выход за границу массива не будет узким местом.
mtk0xf Автор
08.02.2019 00:431.
Какова практическая необходимость такого изменения? Вон, люди в Kotlin наоборот плюются от отсутствия static.
static не исчезает, он становится неотличим от дефолта. Вместо статичных классов и полей — объекты по умолчанию. Внутренние объекты по умолчанию, таким образом, будут как бы статичными только для себя, по отношению к своему внешнему классу, т.е., если внешний класс сам статичный и так до самого внешнего, то — статичные абсолютно.
2.Т.е. структурная типизация как в go и typescript вместо существующей номинативной? А зачем?
Высчитывать уникальный код множества ключей vtable, это собственный тип. Ключи из сигнатур, у нас же только методы. Значение — структуры объектов композиции. Полный тип класса — хэштаблица предков и своего типа, значение — структура, описывающая наследуемый объект, см. дальше. Т.е., в обоих таблицах value это ссылки на структуры, описывающие конкретные объекты. Классов на этом уровне просто нет. Методы — адрес в этой структуре. До оптимизаций один адрес, т.к. перегружаемые методы в vtable.
3.Да, но как тогда вы в методе будете указывать, что переданный параметр должен обладать такими-то свойствами? Для этого нужно будет вводить синтаксис для описания анонимного типа-структуры. А потом и тайпалиасы прибегут (что и будет аналогом интерфейсов). Я кстати ещё молчу про перфоманс instanceof/checkast. Ну и да, это не просто языковое изменение, тут JVM придётся выкинуть.
В языке аргумент это просто примитив либо название метода, который класс по совместительству. Там нет ничего кроме классов, они же — методы с фигурными скобками. Для машины аргумент это ссылка на структуру объекта, в которой 1: vtable, в котором хеши из сигнатур (у нас же только методы) и значение-ссылка на такую же структуру другого объекта; 2: хэштаблица из хешей (2) предков и себя самого; и 3: адрес метода. instanceof просто ищет хеш во второй таблице.
JVM — не важно, я писал о языке вообще.
4.Ага, т.е. множественное наследование реализаций? А как будет реализовываться vtable?
Не совсем множественное наследование. vtable состоит из key — хешкода сигнатуры метода, и value — ссылки структуру, описанную в (3), где есть и тело метода и такой же vtable и т.д. до победы. Т.к. в языке нет ничего кроме методов, они же классы. Как это заполнить? В случае конфликта требовать явно указать источник, а в случае некомплекта какого-то из предков — тип убрать из списка предков (2), но часть кода повторно использовать, т.е. оставить. equality — понятно уже как?
5.Простите, а как при ссылке на overloded-метод должен резолвиться метод с конкретной сигнатурой?
Прямо по хешу сигнатуры метода из vtable. И есть куда оптимизировать простые случаи.
6.Практика показывает, что голова начнёт чесаться при решении задачи каскадной упаковки, а именно где остановиться и как это правило сформулировать.
Просто свои приватные массивы и примитивы, они же лежат по адресу без всяких vtable. Чужие не надо. В пункте 13 даже есть заделка, но для этого и она наверное медленная.
Чтение за границами массива — это в 99% случаев не то, чего мы реально хотели, а значит — ошибка. Одним из принципов дизайна Java является fail fast, что, исходя из моего опыта (и из чужого опыта — тоже), является благом.
Ну, это вопрос философский. Я описал именно то, что хотел бы видеть. Мусор можно и в своём массиве найти. Чтение своей памяти это первый способ рефлексии, ну а ценные данные шифровать надо.mtk0xf Автор
08.02.2019 01:29Изобретать неявные преобразования, как в C++?
Используется обыкновенный класс с абстрактными полями, по тому же самом принципу. Можно его даже подзаполнить, если хочется. Поскольку есть динамические типы, расширяем подходящий объект этим «темлейтом» и абстрактные методы радостно становятся неабстрактными. Просто этот «темплейт» попадает в хештаблицу предков. Т.е., даже никакого механизма специального не надо. Так получается потому, что из языка всё повыкинули.
konsoletyper
08.02.2019 12:11Честно говоря, ответа ни на один вопрос я не получил.
Какова практическая необходимость такого изменения? Вон, люди в Kotlin наоборот плюются от отсутствия static.
static не исчезает, он становится неотличим от дефолта. Вместо статичных классов и полей — объекты по умолчанию. Внутренние объекты по умолчанию, таким образом, будут как бы статичными только для себя, по отношению к своему внешнему классу, т.е., если внешний класс сам статичный и так до самого внешнего, то — статичные абсолютно.Во-первых, тут вы оперируете слишком большим количеством терминов, которые мы с вами не согласовали (объекты по-умолчанию, внутренние объекты). Можете более подробно описать эти особенности дизайна вашего языка? Объекты по-умолчанию это что-то вроде object в Kotlin? Т.е. есть сущность "объект" а есть — "класс". Или всё является классом? Тогда каким образом конструируются объекты по-умолчанию для классов, у которых нет конструкторов без параметров. Во-вторых, вопрос был в том, зачем избавляться от static.
Т.е. структурная типизация как в go и typescript вместо существующей номинативной? А зачем?
На что получил что-то про особенности реализации, которые, увы, не зная всех особенностей вашего замысла, понять практически невозможно (предлагаю всё-таки для конструктивного общения описать дизайн языка, с bnf и операционной семантикой, хотя бы в очень нестрогом виде).
А вопрос-то был про то, зачем вам в языке структурная типизация вместо номинативной. В чём вы видите преимущества первой перед второй?
Да, но как тогда вы в методе будете указывать, что переданный параметр должен обладать такими-то свойствами? Для этого нужно будет вводить синтаксис для описания анонимного типа-структуры. А потом и тайпалиасы прибегут (что и будет аналогом интерфейсов).
В языке аргумент это просто примитив либо название метода, который класс по совместительству. Там нет ничего кроме классов, они же — методы с фигурными скобками. Для машины аргумент это ссылка на структуру объекта, в которой 1: vtable, в котором хеши из сигнатур (у нас же только методы) и значение-ссылка на такую же структуру другого объекта; 2: хэштаблица из хешей (2) предков и себя самого; и 3: адрес метода.Я опять же, спрашивал не столько про особенности реализации, сколько про дизайн языка. Вот у вас, судя по всему, структурная типизация, так? Вот в typescript я могу написать
function foo(x: { bar(x: number): string }) { x.bar(23) }
и сюда подойдёт инстанс любого класса, у которого есть bar. Если попробовать в foo засунуть что-то не обладающее методом bar нужной сигнатуры, то компилятор нарисует ошибку. Вот где в вашем языке определяется сигнатура метода? Как в ней описать требования к передаваемому в метод объекту, если нет интерфейсов?
Ага, т.е. множественное наследование реализаций? А как будет реализовываться vtable?
Не совсем множественное наследование. vtable состоит из key — хешкода сигнатуры метода, и value — ссылки структуру, описанную в (3), где есть и тело метода и такой же vtable и т.д. до победыА вот это уже был вопрос про реализацию. И правильно я понимаю, что вы предлагаете виртуальный вызов вместо обычной косвенной адресации со смещением (одна инструкция на x86) делать lookup в хэш-таблице? А как же производительность?
Простите, а как при ссылке на overloded-метод должен резолвиться метод с конкретной сигнатурой?
Прямо по хешу сигнатуры метода из vtable. И есть куда оптимизировать простые случаи.Вопрос снова был про семантику а вы ответили реализацией. Хорошо, попробую вот так. Пусть у нас есть в Java такие объявления:
void foo(Integer x); void foo(String x);
когда я пишу
o.foo(23)
, компилятор точно знает, что надо вызвать первый метод, потому что он подходит по сигнатуре. Далее, если у нас все методы есть просто поля функционального типа, то такой резолв становится невозможен (например, он невозможен в JavaScript, где ровно такое поведение, и там похожая (но не такая же) штука реализуется уже в рантайме руками). Именно поэтому для ссылок на методы и в Java используется такой синтаксис, который используется (там по сигнатуре метода в целевом SAM-интерфейсе можно сделать резолв нужного метода). Вы предлагаете отказаться от перегрузки по сигнатуре? А если не предлагаете, то как разработчик должен сообщать компилятору, который из методов ему нужен?
Практика показывает, что голова начнёт чесаться при решении задачи каскадной упаковки, а именно где остановиться и как это правило сформулировать.
Просто свои приватные массивы и примитивы, они же лежат по адресу без всяких vtable. Чужие не надо. В пункте 13 даже есть заделка, но для этого и она наверное медленная.Ещё раз обратите внимание — практика показывает. На Java вполне можно просто в виде библиотеки это сделать. И никто не делает. Точнее, делают в виде наколенных поделок, которые приходится выбрасывать, потому что при усложнении проекта и появления дополнительных требований оказывается, что никакая автоматика не справится.
Изобретать неявные преобразования, как в C++?
Используется обыкновенный класс с абстрактными полями, по тому же самом принципу. Можно его даже подзаполнить, если хочется. Поскольку есть динамические типы, расширяем подходящий объект этим «темлейтом» и абстрактные методы радостно становятся неабстрактными. Просто этот «темплейт» попадает в хештаблицу предков. Т.е., даже никакого механизма специального не надо. Так получается потому, что из языка всё повыкинули.Вопрос был про варантность generics, т.е. про возможность объявить такое:
void foo(List<? extends C> supplier, List<? super C> consumer);
у шаблонов в C++ с этим проблемы. Ну как проблемы, там это решается средствами, которых и близко нет в Java (и про которые вы так же ничего не сказали)
mtk0xf Автор
08.02.2019 22:50Для удобства немного перегруппировал вопросы.
Честно говоря, ответа ни на один вопрос я не получил.
судя по всему, структурная типизация, так?
Вместо описаний алгоритма вы ждали обобщающей формализации, но это лучший компромисс для меня, т.к. индукция абстракциями всегда скрадывает конкретику, а мне нужен только алгоритм. Дальше про типизацию написано много, но я выражаюсь максимально атомарно.
предлагаю всё-таки для конструктивного общения описать дизайн языка, с bnf и операционной семантикой
Это хорошо бы, но меня в первую очередь интересуют не ньюансы семантики, а алгоритм.
зачем
Вопросы «зачем» наверное могу сформулировать развёрнуто, но сейчас это не в приоритете. Из гармонии сфер с моим опытом.
1.Во-первых, тут вы оперируете слишком большим количеством терминов, которые мы с вами не согласовали (объекты по-умолчанию, внутренние объекты).
Да, статья писалась слишком быстро.
По поводу умолчания и статики. Отвлечёмся от терминологии, описывающей языки. На диске есть данные. Данные структурированы. Иерархически, релятивно ссылками композиции и наследованием. У нас есть runtime инструмент клонирования этих данных и манипуляции ссылками. Очевидно, что на диске статично лежат дефолтные данные.
Объекты по умолчанию прямо подгружаются с диска со всеми своими внутренностями, инструмент создания нового экземпляра просто клонирует эту вложенность, начиная с того уровня, который создаётся. Дефолтные значения копируются, abstract поля перед этим либо явно назначаются, либо выдают ошибку. Таким образом, любой объект может runtime сериализоваться в исходники согласно п. 13 статьи, а не в что-то бинарное, и обратно компилироваться уже как бы в дефолтный статичный объект, который физически от остальных объектов не отличается, он отличается только своим создателем-машиной и временем происхождения. Любому объекту в памяти можно добавить поле abstract и тогда его нельзя будет клонировать без определения этого abstract и будет выдаваться NPE при попытке считать значение abstract.
2.По поводу внутренностей.
В языке за пределами тела метода нет ничего объектного кроме методов, внешних и на одном уровне. Объект, объявленный внутри другого объекта — внутренний объект. Для внешних пользователей нет даже полей, поскольку они семантически внутренние объявленные объекты, это из-за подразумеваемых неявно, до перегрузки, объектов-сеттеров и объектов-геттеров. Для самого объекта и для его внутренних, в пределах прямой видимости, поля есть, все они — приватные. Прямая видимость определяется по иерархии. Язык запрещает обращаться напрямую к полям вне прямой видимости, т.е. к полям, которые определены в других детях своих родителей.
Программа это просто область памяти, часть которой компилятор разрешает дёргать прямыми со смещением ссылками, а часть — запрещает. Эта область памяти увеличивается по мере создания новых объектов. Компилятор все вызовы в пределах прямой видимости делает прямыми со смещением, за пределами — через vtable, т.е. любой внешний вызов это не вызов из прямой видимости и происходит только через vtable. В прямой видимости также лежит либо ссылка на дескриптор объекта, либо примитив, либо массив, который я не считаю нужным делать объектом.
3.Что называть классом объекта? Весь дескриптор, описанный в предыдущих ответах. Т.е., у каждого объекта кроме наследников ещё и два собственных типа. Первый высчитывается просто по сигнатуре метода. Второй — хеш всех сигнатур из vtable. Кто как назовёт эту типизацию?
Алгоритм я постарался описать подробно и работает он за конечное время, об этом алгоритме ещё раз в след параграфе про вызов метода.
Дальше Баньян, наследующий ни кого-нибудь, а аж собственные внутренние классы. В дескрипторе в первой таблице по хэшам сигнатур значениями дескрипторы Tree, Branch, Leaf, Cell и перегруженный Grow, и хэш-ключ типа из всех этих сигнатур. Во второй таблице, по своим ключам типа, дескрипторы самого Banyan и его предков Tree, Branch, Leaf и Cell. Так у него срослось.
void Banyan extends Banyan.Tree{ void Tree() extends Tree.Branch{ void Branch() extends Branch.Leaf{ void Leaf extends Leaf.Cell{ Cell[] cells; //тут массивы - не объекты void Cell(){ void Grow(){ } }//Из этой клетки пошло деление-заполнение массива, она дефолтная и в массив её не обязательно. @Override void Grow(){ } };//Эта клетка произошла от зелёных клеток ростка, но решила быть веткой @Override void Grow(){ } }//Первый Branch это ствол. @Override void Grow(){ } }//Это старейший баян @Override void Grow(){ } }
4.Собственные типы могут совпадать, если совпадает ещё и хэш ключей vtable, то это либо просто клоны, не перезагружавшие общего предка, либо, другая крайность, счастливо совпавшие и не имеющие общих предков классы из разных реализаций. Могут они быть взаимонезаменяемыми? Вопрос архитектору, факт совпадения можно выяснить на любом этапе даже runtime, поскольку ссылки-значения отличаются частично или полностью.
5.обладающее методом bar нужной сигнатуры, то компилятор нарисует ошибку. Вот где в вашем языке определяется сигнатура метода? Как в ней описать требования к передаваемому в метод объекту, если нет интерфейсов?
Описание на уровне языка выглядит точно так, как описание в Яве. Fruit first. При компиляции исходников, структура передаваемого в метод объекта бёрется из двух таблиц просто по Fruit. Первая собственная таблица компилятора — имена->сигнатуры. Вторая — сигнатуры->ссылки на структуры. Тип, интерфейс и класс и даже метод — «Fruit». Посредством этих двух таблиц мы получаем ссылку на нужную структуру и вперёд.
Вы предлагаете отказаться от перегрузки по сигнатуре?
Во-первых, это проблема только компилятора, которая разрешима, см. дальше, но лаконичнее всего конечно не перегружать, а обернуть.
void Foo(int x){ void Foo(char* x){ } }
потому что базовая функциональность там скорее всего в int x, a текст в него конвертируется, либо наоборот, это по смыслу. Если же там вообще разная функциональность, то я считаю такую перегрузку вредной.
При необходимости выбирать метод нужно всего-то положить в первую таблицу компилятора (не дескриптора) не сигнатуру, а таблицу сигнатур, из которых выбрать, причём, это же только при компиляции.
Чтот такое Fruit? Фрукт. Как кто-то назовёт тип этого типа?
6. Машина посылает аргументом либо примитив, либо прямую ссылку на структуру в памяти. Поскольку, при вызове метода мы уже подготовили ссылки на дескрипторы, либо из собственного дескриптора с vtable, либо приватные по смещению, либо локальные после операций с первыми двумя и аргументами. По этой ссылке на дескриптор будет всё найдено в вызываемом методе.
7.А вот это уже был вопрос про реализацию. И правильно я понимаю, что вы предлагаете виртуальный вызов вместо обычной косвенной адресации со смещением (одна инструкция на x86) делать lookup в хэш-таблице? А как же производительность?
Так обыгрываютя только логически важные переменные. Чем больше будет ООП, вокруг таких переменных — тем лучше. Не случайно к проектам на Си в довесок идут всякие медленные скриптяги.
Производительность компенсируется тем, что работа с родными полями и полями прямой видимости происходит напрямую. Элементарные массивы я не стал бы делать объектами, ну и проверки границ при доступе убрал бы.
Простейший процедурный код там, где нужна производительность, компилятор может многое оптимизировать, если не будет внешних ссылок. Можно добавить модификатор private, который будет явно сообщать, что не local, но полное внешнее исчезновение.
Вопрос был про варантность generics, т.е. про возможность объявить такое:
Да, без специального синтаксиса для темплейтов будет уныло вбивать. Утилита даже и runtime создаст два новых объекта:
void Supplier extends List{ //в котором перезагрузит все методы с Object, например Object Get(int index) на С Get(int index) extends Get(int){ return (C)super.Get(index); } <...> } //и ещё один void Consumer extends List{ Object Add(Object arg) extends Add(Object) throws TheObjectNotParentFor{ if (! C.instanceOf(arg)){ //С это полноправный объект и arg - полноправный класс throw TheObjectNotParentFor(object, C);//catch сделано через методы, в статье описано в пункте 9 } return super.Add(object); } <...> }
Объявляем void foo(List<? extends C> supplier, List<? super C> consumer);mtk0xf Автор
09.02.2019 00:27Ещё раз обратите внимание — практика показывает. На Java вполне можно просто в виде библиотеки это сделать. И никто не делает. Точнее, делают в виде наколенных поделок, которые приходится
Java — слишком сложный язык. Там слишком много лишнего. Тут же нет ничего. Процедурные сорцы просто повторно использовать, генерить на диск не надо. Либо наслаждаться их отсутствием, назвав нативным кодом, что тоже весьма и весьма не плохо.
Throwable
07.02.2019 12:51+1п15. Чтоб можно было грабить корованы.
Очень наивные утверждения, ломающие обратную совместимость, либо рудиментарные, либо вообще не реализуемые ввиду возникающих побочных проблем. Из здравого я бы отметил только п.3 — properties. Легко реализуемо и сразу убирает огромное количество бойлерплейта.
khim
07.02.2019 13:28Почитайте комментарии. По неизвестной науке причине
properties
не годятся.StrangerInTheKy
07.02.2019 17:43Я читал комментарии. По неизвестной науке причине ни один из комментирующих не смог внятно объяснить, что такое property в Delphi. То есть все вроде знают, но объяснить внятно никто не может. Поэтому нет смысла читать весь тот флуд выше.
P. S. Мне не надо рассказывать, что это. Я отлично знаю, и в целом согласен, что появление Delphi-style property в Java пойдет ей на пользу.
mtk0xf Автор
07.02.2019 21:58-1Никакой совместимости там и не подразумевалось, написано было раз сто, как не подразумевалась, например, совместимость Java и Си. По поводу наивности, это абсолютно голословное утверждение, не подкреплённое ничем абсолютно. Обсуждающие зачем-то какие-то проперти накатали уйму текста, в то время как сам факт обсуждения этих пропертей в контексте статьи свидетельствовал о том, что никто из обсуждающих вообще не разбирался по существу ни в чём из написанного в статье. Никакого труда не составляло бы за всё это время по пунктам перечислить конкретные наивности и побочные проблемы, но их там просто нет или исчезающе мало.
Непонятность это конечно вина статьи, потому что подобные вещи не пишутся наверное в спешке, но тема специальная, для ценителей и смысла нет писать бессодержательные негативные комментарии, если просто тупо не разбирался. Желания разобраться не было, так как наводящих вопросов был ровным счётом один от товарища джависта в конце обсуждения. Народ просто гнал какую-то свою дельфийскую волну непонятно куда непонятно зачем.konsoletyper
07.02.2019 23:24Никакого труда не составляло бы за всё это время по пунктам перечислить конкретные наивности и побочные проблемы, но их там просто нет или исчезающе мало.
Мой коммент выше читали? Там как раз некоторые наивности разобраны и обозначены некоторые побочные проблемы.
mtk0xf Автор
08.02.2019 00:48Таки дошёл, ответил. У меня конечно болела голова, что-то я устал за предыдущие сутки от какого-то странного общения, но, отвечая Вам, даже немного отдохнул.
Throwable
08.02.2019 14:48Просто чтобы понять суть многих проблем, посмотрите обсуждения, которые велись в блоге Kotlin, когда он еще был на этапе дизайна. Там тоже предлагали многообещающие нововведения, от большинства которых впоследствии пришлось отказаться, например от функции с множественным результатом. Некоторые из них все же были реализованы, но совсем в другом виде.
mtk0xf Автор
08.02.2019 23:18Причём здесь Kotlin? Мне бы блог Lisp-а или Scala. Ещё блог SmallTalk интересно почитать. И Пролога в прологе. Не найти, и прочитать жизни не хватит. Процедурная часть в языке настолько отделена от ООП, который на что похож, на нововведения? Вы сами сказали, что он похож на рудимент, но это ваше личное мнение. Так отделён, что можно, наверное, куски ANCI Си вставлять продумав слегка фреймворк.
vintage
08.02.2019 08:28Возможность вернуть более одного результата из функции.
Это не удобно. Лучше возвращать структуру (частный случай — кортеж), а с ней уже делать что душе угодно. А не как в Го — примите и проигнорируйте.
Для «protected», «default» и «public» полей автогенерация сеттеров и геттеров компилятором, без автогенерации видимых сорцов, но с возможностью их перегрузки, «private» убрать из языка, поскольку «сами» поля все и так будут «private» без возможности перегрузки.
Фактически вы описали property.
Типы классов сравниваются по хеш-коду, который будет сгенерирован именами поля, именами аргументов, типами и возвращаемыми значениями
Фактически вы описали структурную типизацию.
В результате, объект будет наследовать код и реализовывать все родительские типы.
Фактически вы описали множественное наследование.
не сложно организовать перепланировку расширением типа инстанса прямо runtime, сужение — запретить
Насколько я понял речь про ковариантность. А что насчёт контравариантности и инвариантности?
Подметоды как в Паскале.
Все, конечно, в курсое как там в Паскале. Замыкания что ли?
Конструктор класса будет телом метода по умолчанию, который будет создан во время компиляции, в соответствии с пунктом 2 «экземпляры по умолчанию». Больше не понадобятся специальные ссылки на метод, как в Java 8. Ссылка на метод будет означать ссылку на объект.
По описанию похоже на замыкания.
Новый оператор для runtime шифрования всяких примитивов
Какой алгоритм и размер ключа захардкодим?
я бы дал возможность читать напрямую из памяти без контроля границ массива
То есть иногда читать мусор из других объектов, а иногда аварийно завершаться по access violation?
Кроме того, в методе «run» объекта Runnable, который передается в Thread, требовать явно вызывать метод, прерывающий поток, и, чтобы без этого была ошибка компиляции.
Какой поток? Зачем его прерывать? Речь о yield что ли?
Фактически, граф всех объектов в памяти всегда имеет только примитивные типы, массивы или null или ссылку на нечто нативное на всех своих вершинах. Будет очень полезен базовый инструмент, который может сохранять весь этот граф в любой текстовой форме.
И как сохранить часть этого графа? Если же предлагается сохранять его целиком, то проще и быстрее память сдампить, как это делается в SmallTalk.
Полезный инструмент для поиска любых объектов в графе объектов по заданным критериям с учетом модификаторов доступа, по типу простого SQL.
Если это будет не только лишь дерево, а именно произвольный граф, то боюсь ваш SQL получится очень не простым.
Резюмируя: без примеров хотя бы псевдокода понять о чём вы говорите крайне сложно. А вообще, заходите к нам в телеграм, где мы иногда обсуждаем дизайн языков: https://t.me/lang_idioms
mtk0xf Автор
08.02.2019 22:55У меня сегодня хватило сил только на один большой ответ. Будет и второй.
axifive
Вот только джава уже на протяжении двух десятилетий сохраняет обратную совместимость, и похоже никто не собирается менять эти чудесные традиции.
mtk0xf Автор
Тебе не понять романтики одинокого малайского язычника в толпе мусульман, который смотрит на вулканы и мечтает о новых Кракатау. «Сила взрыва Кракатау оценивается в 100—200 мегатонн тротила, что более чем в 10 тысяч раз превышает силу взрыва, уничтожившего Хиросиму». Индонезия. С моей точки зрения, сложность и запутанность кода растёт быстрее производительности компьютеров, и, если так дело пойдёт, то, лет через 50 будут не роботы по улицам ходить, а священнослужители с кадилом перезагружать постоянно зависающие девайсы. Профессия такая появится наподобии DevOps — «девпоп».
mtk0xf Автор
Не понимаю, народу не нравится вулканизм, черти, ладан или философские обсуждения программирования считаете бессмысенными? Сказал же: Ява ни при чём. Мне казалось, это и так понятно было.
olegchir
Имхо, проблема в инертности мышления и связанном с этим придумывании несуществующих правил. Это не первая статья, которую несправедливо заминусовали прямо в карму, не читая. Люди так привыкли, что на хабре пишут исключительно экспертные статьи вида «я эксперт, вам нужно делать так и так», что совершенно любой другой жанр рассматривается как нарушение устоев.
То же касается и комментариев: сложилась практика (по-моему, весьма адская) плюсовать и минусовать комментарии исходя из экспертности. То есть, если человек пишет в ответ «а мне нравится по-другому», и тебе нравится как-то иначе, нужно сжечь собеседника минусами в комментарий. Это опять же неявно подразумевает, что минусующий считает, что его собеседник знает правду и намеренно распространяет ложь. Люди слишком привыкли, что существует не более одного формата общения — того, в котором целый тред пытается что-то доказать друг другу. Отсюда например, часто встречающийся паттерн «лесенки минусов» (все комментарии в ветке — перепалка двух человек, которые минусуют друг друга) или «лесенки чётных минусов» (та же перепалка, но сообщество решило, что виноват чётный оправдывающийся, и его минусят сразу десятками, сотнями). Формат обсуждения, когда люди просто пытаются в ходе обсуждения найти какое-то решение в это никак не помещается.
Что с этим делать — непонятно. Наверное, вначале зарабатывать некий капитал из плюсов и потом сливать его на нестандартных статьях, пытаясь выработать привычку читать что-то кроме экспертных статей.
khim
Вы слишком глубоко копаете. Люди минусуют статьи и комментарии, в которых видно, что человек пишет о предмете, в котором он ничего не понимает.
В частности если человек предлагает реформировать язык программирования, то предполагается, что они знает, в общих чертах, хотя бы десяток самых известных-распространённых и может как-то сравнивать их плюсы и минусы.
Ну ведь не будете же вы выкладывать на Хабр статью о том, как вы написали свою первую сортировку пузырьком? Да даже и
merge sort in place
(хотя это сложный достаточно алгоритм) — тоже не будете. А обсуждаемая статья — это примерно этот уровень и комментарии это только подтверждают.olegchir
"Ничего не понимает" — это вещь относительная. То, что пишет мидл — это какая-то постыдная чепуха для сеньора. И наоборот, то что пишет джун — откровение для новичка. Для вашей прабабушки вы всегда будете "компьютерным гением". Требование всегда "чего-то понимать" означает, что вы наложили на автора поста или комментария обязанность быть экспертом в обсуждаемой теме, экспертнее чем большинство на Хабре. Вроде как если бы уроки математики в школе мог вести только академик.
И — нет, нету такого правила, что каждый писатель и улучшатель обязан быть экспертом. Уверен, что половина улучшений происходит потому, что человеку лень разбираться с какой-то сложной механикой, он откладывает сложную книгу на миллион страниц о сложной фиче и придумывает другую — свою, простую. В результате на следующей итерации мы имеем, например, более простые и понятные фреймворки, которые можно понять за в два раза меньшее количество страниц. Улучшения иногда делают те, кто не разобрался.
Когда-то давно мне казалось, что если я не понимаю код, это значит — я тупой и нужно учиться. Сейчас пришло понимание, что если я не понимаю код, то скорей всего — код очень, очень плох :-)
Дискуссия между обычными людьми (не экспертами) часто выглядит так: люди говорят в рамках своих крайне лимитированных знаний и в конце концов, дополняя дыры в понимании друг друга, приходят к каким-то выводам. Результат разговора не обязательно будет корректный, но зато все получат удовольствие и узнают что-то новое. Это обычный разговор о истории в курилке, например: два коллеги-программиста обсуждают какую-то войну в V веке, о которой помнят лишь по обрывкам институтских лекций и в ходе этого диалога упражняются, например, в логике. Никто из адекватных людей не бьёт друг другу лицо в курилке и не бьётся в конвульсиях от того, что кто-то из собеседников не прав в отношении войны в V веке!
Подумайте, что ваши категоричные суждения о тех или иных вещах, скорей всего, кажутся смешными и наивными в глазах какого-нибудь дизайнера языка. который занимается этим на работе все ближайшие 30 лет.
Запретить все разговоры в курилке? Поставить там крупнокалиберный пулемёт и разрывать на куски мяса всех, кто сказал нечто, противоречащее школьному учебнику (то есть, вообще всех)? Не хотел бы жить в таком мире.
> Ну ведь не будете же вы выкладывать на Хабр статью о том, как вы написали свою первую сортировку пузырьком?
Ещё как буду! Помойму там есть много чего обсудить и спросить у экспертов, что и как правильно писать.
khim
Разумеется! А иначе какой смысл писать статью? О предмете, в котором вы не разбираетесь?
Нет, это как если бы уроки математики в школе вёл физрук. Для комедии — сойдёт, а для Хабра — нет.
На чём, извините, уверенность основана? У вас есть примеры?
Иногда — да. Но очень-очень редко. В большинстве случаев улучшения как раз делаются теми, кто разобрался — и понял что и откуда можно выкинуть.
Нет, зачем. Запретить туда набиваться тысяче человек одновременно. Это и негигиенично и шум будет черезмерный.
Одно дело — когда вы обсуждаете что-то со свомими 5-6-10 лучшими друзьями, совсем другое — когда вы вовлекаете в это тысячи людей, и совсем третьей — когда вы о чём-то говорите с тысячами экспертов на конференции.
Хабр находится где-то посредине между курилкой и конференцией: от вас не ожидается, что вы будете экспертом — но какой-то уровень компетенции должен-таки быть.
olegchir
> Разумеется! А иначе какой смысл писать статью?
Такой же, как у разговора в курилке. Приятно пообщаться и узнать что-то новое в комментариях.
Больше скажу, признанные эксперты так делают доклады на профильных конференциях. Например, пару дней назад на FOSDEM (крупнейшая в мире free open source конференция), на джава-треке, Christine H Flood (наверное, не надо ее представлять? это дизайнер языков включая Java и LISP с десятками лет опыта, работающая сейчас в RedHat) рассказала просто о проекте, которым она занимается по фану. Нет, она не продумала хорошо то, что делает, и о чем собирается говорить, и половина ответов на вопросы звучала как "я делегирую эту проблему утилите CRIU, она может быть это делает… а может быть и нет, спросите у её автора, он тут есть на конференции". От этого у многих в зале конкретно бомбануло, они ожидали от человека такого уровня чего-то более другого, более масштабного, каких-то громких заявлений от имени RedHat — и ничего этого не было. А я наоборот радовался — вся жизнь прошла, а девушка так и не потеряла способности относиться к происходящему легко, как к игре, как к искусству, без всей этой фигни вида "я эксперт с N-цать летним стажем, сейчас расскажу, что вам делать". Она пришла на сцену просто чтобы поджечь интересную дискуссию, и своей цели добилась!
А вот не говорите мне, пожалуйста, что от меня ожидается, а что — нет. Работодатель может рассказывать, что от меня ожидается, и то только потому, что там договор на сорок страниц с подписью кровью. Рандом в курилке? Не думаю. Лично мне интересно приятно общаться — этим я и занимаюсь.
В частности, сейчас мы обсуждаем какие-то вопросы организации сообщества, в которых не являемся не то что экспертами, вообще никем. По вашей логике, вы не имеете права писать комментарий вот тот, что выше, нужно звать сразу Дениса Крючкова :)
khim
Это иногда работает с «живой» аудиторией (хотя почти всегда это — результат недостатка времени на подготовку, так что приходится «вытягивать» провальное, по сути, выступление, за счёт харизмы). И почти никогда не работает в интернете.
olegchir
Хинт: есть специальные Q&A сайты, где подразумевается, что ответы даются не просто из желания почесать языком, а технически грамотные советы. Например, Тостер или StackOverflow. На SO за попытку флуда в комментариях придут кровавые модераторы и турецкими саблями разрисуют хулигана под хохлому. Там это официальное правило, что "
ДумаSO — не место для дискуссий", там всё как вы хотите. На SO никогда не случился бы диалог, который мы ведём сейчас.khim
Есть, да. Там переход на другие темы не приветствуется. Требуют создавать новую тему и там обсуждать.
На Хабре — с этим особо не борются. Но тратить время и силы на объяснение того, что человек и так, вроде как, должен знать (если он собрался рассуждать на определённые темы) редко кто будет.
mtk0xf Автор
Какая разница, какой информацией вы владеете или не владеете, если вы всё равно не умеете с ней работать. Даже, если, предположим, лично вы и умеете это в другой ситуации, то общей удручающей картины это не отменяет. Как вообще люди умудряются со всем этим психологическо-социальным грузом создавать сложные системы, которые в принципе, по факту самой своей сложности, склонны порождать новую и ситуативную семантику? Вот это и есть тот самый главный баг.
mtk0xf Автор
Кстати, khim, вы не ответили ниже по существу и не одному мне, там какие-то properties. Вообще, работа мозга это очень и очень занятная штука, а ещё занятней — работа системы мозгов да ещё и в связке с нервными системами. Не даром устройство нейрона до сих пор никому не известно. В средние века в первом классе школьники своё образование начинали с «тривиума» — логика, риторика, грамматика. У нас первые два куда-то перенеслись настолько на очень никогда потом, что умереть со смеху. Представляете, вы на энном курсе института вскользь прошли бы арифметику. Аккурат после матанализа. Нормально? Вот и мне смешно.
Весь этот мерзкий тривиум на самом деле пошёл от чудака Сократа, который очень хорошо понимал то, что ничего не понимает. Такое не каждому дано. Т.е., «ничего не понимает» это комплимент и ещё какой. После Сократа жила старушка Грейс Хоппер, автор Кобола, одной из целей которой было максимально приблизить конструкции Кобола английскому языку, и ещё в 2006 году Кобол считался языком программирования, на котором было написано больше всего строк кода — из Википедии. Двуногим же без перьев типа меня обычно и приходится юзать всё такое гениальное, а вдруг и правда гениальное — я же не спорю. JavaScript был там кем-то из нетскейп что ли написан за десять дней чтобы только не визжал бейсик. И опять чувак попал в струю. Очевидно, я так не умею, но мне приходится с этим иметь дело.
khim
Разговор просто перешёл в состояние, когда стало ясно, что ничего конструктивного из него не родится. И сама-то статья состояла из какого-то малоосмысленного «потока сознания», а когда выяснилось, что вместо обсуждения плюсов и минусов разных решений описанных вами проблем в разных языках нужно объяснять «а как это вообще бывает»…
P.S. По поводу языков, которые «оказались в нужное время в нужном месте»… JavaScript это ещё не «ужас летящий на крыльях ночи». Настоящий ужас — это Perl и PHP. По крайней мере JavaScript был рождён из очень пристойного языка, пусть и сильно изуродованного. Perl и PHP — были рождены примерно тем методом, про который вы говорите… и многие году люди занимаются тем, что пытаются их «выпрямить»… с не слишком большим успехом, прямо скажем.
mtk0xf Автор
В принципе, работа программиста и состоит в том, чтобы что-то чему-то объяснять, особенно сложно это делать тупому компилятору. Таки вы этого умения почему-то не демонстрируете, всё остальное — лирика. Докажите мне, что я тупее компилятора. У вас это не получится никогда, зато, я знаю ваши проблемы как свои пять пальцев и они тоже социально-лингвистические, если хотите.
vintage
Думаю вы спутали Scheme c языком Self.
khim
Брендан утверждает, что идея была именно Scheme внедрить — но начальству не понравились скобочки.
mtk0xf Автор
Да Ява тут вообще ни при чём, просто как модель какая-то, типа Си для той же Явы. В Яве мне нравится типизация, как-то не доводилось встречать такую же удобную в других языках.