Здравствуйте, vdimas, Вы писали:
K>>А смысл? Словари никто в рантайме не ищет, только в компайлтайм. V>Для случая ООП и рантайм-вариант прозрачно для программиста работает.
В ООП словари в рантайме тоже никто не ищет, на словарь уже есть ссылка. (если речь не идет про какие-нибулдь скриптовые языки)
V>Все-равно не представляю, как ср-вами CLR хранить описание таких типов. V>И если не сложно, раскрой, плиз выделенное.
Точно так же, как любые дженерики реализуются в языках для JVM (Я в курсе, что это размен одних костылей на другие). Поддержка value-типов при таком подходе невозможна, потому я и написал, что обобщать конструкторы value-типов не получится.
V>В среднем коде наблюдается этой арифметики, в т.ч. булевой логики — до половины. Весь остальной мильон альфанумериков делят оставшиеся %% кода м/у собой. Отсюда такое внимание именно операторам языка — они ведь составляют приличную долю синтаксиса исходника.
Если речь идет о коде с for-ами а-ля C и if-ами со всякими сложными условиями — да. Если код в более современном стиле — нет.
Впрочем, обобого смысла обсуждать это направление я не вижу, я сам сторонних возможности объявлять произвольные операторы с заданным приоритетом/ассоциативностью, возможности использования альфанумерик-имен в качестве инфиксных операторов и т.д.
V>Тогда это будет гибрид, как C# или C++ с чуть более продвинутой системой типов. ))
Ну, система типов будет ощутимо продвинутее, только использовать ее будет нельзя из-за того, что уточнения типов будут больше чем код места занимать.
V>В любом случае, нечто вроде сабтайпинга накрутить можно и в Хаскель: V>
V>type OutputStream a = StreamBase (COutputStream a)
V>
Не уловил сходства с сабтайпингом. (хотя "что-то вроде" сабтайпинга при наличии параметрического полиморфизма делать конечно можно, но на это упомянутые проблемы сабтайпинга не распространяются)
V>Ведь контракты ООП — это тоже ограничения. ))
Если это статически проверяемые контракты вроде refinement types, то можно и так сказать.
V>В итоге, иерархия ограничений Хаскеля в точности равна иерархии интерфейсов ООП с т.з. дизайна.
Если речь про "классический" ООП без всяких дженериков — то это точно не так. Если речь про дженерики, то да, сходдство есть, и то и другое параметрический полиморфизм с ограниченной квантификацией.
V>Ну это в дотнете, разве что, а не плюсах (или Swift). Ты не обратил ниже внимание на разницу Cat и Cat*. Просто для дотнета этой разницы нет, ведь в нем всегда Cat* для классов.
Это распространенный подход. Какие без * ООПешные полиморфизм и подтипирование?
V>Даже в Хаскеле в сетевых и GUI либах сплошное ООП.
Для такого ООП надо уж слишком широко трактовать.
V>Класс типов это не тип, а контракт.
С некоторых пор это тип.
V>Его "воплощения" в природе не существует.
Вполне существует в виде словаря функций/GADT в зависимости от реализации.
V>Это лишь в языках-наследниках ML.
Да, т.е. во всех функциональных языках кроме схемы и ее диалектов.
V>Обобщение и ФП — вещи глубоко ортогональные друг другу
Смотря какое обобщение. Параметрический полиморфизм как в ML, Haskell, Java, C# — это ФП. Плюсовые темплейты, генеративные дженерики в Аде и Модуле-3 — судя по всему, глубоко ортогональны ФП и никакой связи с параметрическим полиморфизмом не имеют.
V>Ну да. Но мы же сравниваем конкретные языки. А они гибридные. ))
Я вроде бы явно написал, что сравниваю именно с ООП, а вы сами заявили, что любые свойства гибридных языков на ООП не распространяются.
V>Сам словарь-то для конкретного типа зачастую не обобщенный нифига, какие проблемы с раздельной компиляцией?
Словарь, конечно, не обобщенный — в этом и весь смысл ad-hoc полиморфизма. Но причем тут это? Я же говорю, подход с передачей словаря проблем с раздельной компиляцией не имеет. Проблему с ней имеет подход нарушающий параметричность "подхватыванием" каких-то операторов в виде констрейнта нигде не фигурирующих (т.е. типичный плюсовой, например).
V>Если я правильно понял вопрос, то через области видимости. Через неймспейсы, например. V>Если не в тему, то расшифруй вопрос, плиз.
Нет, разрешение противоречий при поиске словарей с использованием областей видимости нарушает когерентность инстансов.
Когерентность инстансов означает, что одному типу соответствует один инстанс/словарь данного класса.
V>Можно мне, тупому, показать на пальцах пример в Хаскель, когда бы у нас была последовательность абстрактных Pet a
Для Pet (без a) диспетчеризация будет в рантайме. Ничего заинлайнить нельзя. Для Pet a (обратите внимание, что тут a есть, это ключевой момент) "диспетчеризация" будет в комайлтайм.
V>Это зависит от того, что "видит" компилятор — сам объект или только его адрес. Если компилятор С++ видит Cat по-значению (на стеке, глобальную переменную или как поле другого объекта), то он вызывает методы напрямую,
Ну так тут и полиморфизма ООПешного нет.
V>если же он видит Cat* или Cat&, то он понятия не имеет (в общем случае) о точном типе объекта по адресу, поэтому работает рантайм-полиморфизм.
Ну да.
V>>>Известно только если компилятор не видит точный (конечный) тип объекта. Если же видит, то вызывает виртуальные методы напрямую, без таблицы. Именно поэтому я вижу тут аналогию.
ОК, сформулирую по-другому. При параметрическом полиморфизме больше сценариев использования, когда компилятор видит "точный (конечный)" тип, полиморфизм через сабтайпинг достигается "стиранием" информации о "точном" типе. Естественно, совсем без "стирания" не обойтись и для этого средства везде есть, но ООП-подход такому стиранию благоприятствует.
V>По отношению к парадигме ООП, наследование реализаций — это просто некий трюк где-то сбоку. Можно взять для рассмотрения более строгую парадигму КОП — наследование только интерфейсов.
И чем это нам тут поможет?
V>Ну и в обычных пользовательских классах доля виртуальных методов далеко не 100%, а как бы заметно ниже 50%.
Мы вроде про полиморфный код говорим. Как тут в ООП без виртуальных методов?
V>В общем, с заявлением "В ООП сложно обозначить область где рантайм-полиморфизм не требуется" согласиться оч сложно. По-сути, ты приписал всему ООП ограничения пары популярных платформ — дотнета/джавы. V>Более того, нет никаких ограничений, даже в условиях GC, располагать объекты по-значению в теле объектов-владельцев.
Как их располагать по значению в условиях полиморфизма? Разные типы по размеру отличаются. Поэтому и хранится ссылка, котороая по размеру не отличается, вне зависимости от того, на какой наследник Pet она указывает.
K>>Виртуальные вызовы только какой-нибудь трассирующий джит нормально устранить сможет. V>Намного больше их устранит нивелирование избыточной/ненужной косвенности.
Как ее для полиморфного кода нивелировать?
K>>Поэтому, там где рантайм полиморфизм требуется — там он везде будет. А там, где не требуется — в ООП скорее всего будет, а в хаскеле — нет.
V>Косвенность и ООП — тоже ведь вещи ортогональные.
И что без нее от ООП остается? ООП-ешный полиморфизм без нее не работает.
V>Странно, что ты не понял еще в прошлый раз, о чем речь. Пофиг на шаблонный vector<>, пусть у нас будет два обычных массива: V>
V>Cat cats;
V>Cat* catsByPtr[];
V>
V>При обработке первого массива методы объектов будут вызываться напрямую (со всей оптимизацией и инлайнингом, на которую способен компилятор), при обработке второго массива — как виртуальные.
Непонятно, какой смысл сравнивать Cat и Cat* если речь идет про, скажем, Pet*. Как в Cat cats хранить Dogs и применять к каждому эдементу такого массива обобщенную функцию kill, которая для Cat и для Dog определена?
K>>В дотнете же, если Cat не struct придется бессмысленно тормозить на виртуальных методах, даже если все элементы одного типа на самом деле — из за сабтайпинга это установить невозможно.
V>Это не из-за сабтайпинга, а из-за того, что только при косвенной адресации сабтайпинг начинает нам мешать.
Ну естественно. Он и работать только при косвенной адресации начинает.
V>Это всё унаследованный от джавы кретинизм. Парадигма ООП тут не при чем.
Никакой джава-специфики тут нет. ООП-полиморфизм в основном так и реализуется.
V>В С++ более распространены их статические варианты: traits и "статический визитор". А так-то да. Если забыть, что речь шла про операторы... ))
Ну так и обсуждаемый вариант на C# — статический.
V>С операторами удобнее таки через явное указание "модуля", то бишь области видимости. Именно таким образом мы "передаем словарь" один раз на всю текущую область видимости (через указание других видимых явно "модулей"), т.е. не надо передавать в каждый метод. Очень даже оправданный подход, коль речь не о вызовах методов, а о глобальных ф-иях/операторах.
Не считаю, что это хороший подход (хотя широко практикуемый в ML-ях). В одном выражении и в одной области видимости может быть + и для int и для double.
V>Меня интересует библиотечная либа, умеющая вызывать kill Pet a, которая еще ничего не знает о Cat и Dog, и которая принимает на входе выраженную каким-либо способом последовательность абстрактных Pet a.
Если работать c Pet (без a) — то будет рантайм диспетчеризация, как в ООП — как иначе-то?
V>Я бы посмотрел на оба варианта. Если можно.
Пример см. по ссылке чуть ниже.
V>Есть соображения насчет последнего?
Некоторые хаскелисты не любят тайпклассы, некоторые — любые расширения. Вот тут http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/ позиция противника такого подхода.
K>>По моему, диспетчеризация подразумевает выбор между какими-то ветками вычислений. V>Самый популярный способ диспетчеризации на сегодня — это косвенная адресация. Есть код, который вызывает другой код не по известному на момент компиляции адресу, а по фактическому поданному в процессе работы программы.
Ну да, и что? Это никак не отменяет фактической разницы случаев, когда нужно выбирать между ветками вычислений и когда не нужно. Во втором случае "выбор" устраним на этапе компиляции и на практике устраняется в значительном числе случаев.
V>Вызов виртуального метода и есть "просто dereferencing".
Не просто. Мы не знаем до рантайма какой метод вызываем. Тут же все в компайл-тайм известно, это как поле структуры прочитать.
V>в дотнете можно рожать в рантайм конечные типы из генериков через рефлексию.
Не самая хорошая идея по-моему.
K>>Ну да, можно и на плюсах писать со стиранием, ссылками и передачей словарей, но обычно не пишут. Но это не "подстановочное" решение для которого библиотека нужна будет в исходниках. V>В плюсах в исходниках нужны только заголовочные файлы для этого случая, а тело методов может быть библиотечным. Если мы всё еще об одном и том же — о реализации словаря ComplexNumber, например. ну и инлайнинг на сегодня может выполняться во время линковки, не только во время компиляции.
Так я и говорю, решение с передачей словаря лучше подходит для раздельной компиляции.
V>- Сабжу не надо воровать львиную долю человекочасов на собственный бэкенд и оптимизацию конечного бинарного кода. Особенно это актуально для современного числодробления. V>- LLVM последних версий отстаёт от самого лучшего GC уже всего лишь в полтора раза на специальных тестах и почти не отстаёт на "обычном" коде.
Разница в производительности генерируемого кода между clang и компиляторами других языков, использующих LLVM вполне наблюдаема.
V>В общем, потенциал неплох. По-сути, это прямой конкурент D.
У меня впечатление, что у D возможности побогаче. Но существенного роста популярности D я не ожидаю.
V>Причем, за этим языком стоит IT-компания из первой тройки.
Тут как раз не все так просто. Эппл, конечно, имеет возможность сделать его не менее популярным, чем Objective-C и тем же самым способом, ну так и за пределами эппловской платформы у него будет популярность, как у Objective-C.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, vdimas, Вы писали:
V>С того, что эффективный и безопасный ПМ возможен только на закрытых суммах типов, а не на открытых, которые представляют из себя иерархии классов в ООП. V>Еще непонятно как эффективно разместить размеченное объединение в памяти, т.е. как эффективно всем этим пользоваться при минимуме накладных расходов. Например, динамическое приведение в ПМ в Немерле показывает всю кривизну такой попытки.
Так в сабже же суммы произведений есть. Только рекурсии нет.
V>Наверно, стоит сравнивать примерно равные по популярности языки.
По меркам непопулярных языков, производительность у ФЯ вполне хорошая.
K>>Вопрос был в том, зачем делать убогим, если можно не убогим? Что мешает-то?
V>Отсутствие размеченных объединений в языке.
Какое отсутствие? Есть же enum (спасибо эппл, за не название с неверными ассоциациями).
V>Дык, если в Хаскель всего три типа данных — это туплы, размеченные объединения и сигнатуры ф-ий
Еще и рекурсия, мутабельные ячейки, массивы. Ну а в ООП языке обычно меньше — сумм, например, нету.
V>, то синтаксис будет минимальным, конечно.
Ну так в чем необходимость навороченного синтаксиса для описания типов, если их разновидностей даже меньше?
V>Тем более, что в условиях иммутабельности нет надобности скрывать устройство типов, т.е. отпадают еще всякие public/protected/private.
public/protected/private там на уровне модуля задается.
V>Избыток синтаксиса в ООП только в оформлении деклараций типов.
О них и речь.
V>Тела ф-ий в С++-синтаксисе смотрится нормально, особенно с переопределением операторов.
Тут еще сильно неспособствует легковестности то, что не все является выражением, а так да, нормально, бывает куда хуже.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, AlexRK, Вы писали:
ARK>Понял. То есть речь просто о сахаре для вызовов цепочек функций. Тогда зачем же притягивать целый ФЯ?
Нет, речь идет не только о сахаре. Для комбинирования комбинаторов нужно чтоб комбинация комбинаторов по производительности не сильно отличалась от ручного фьюжена в лапшу, а объем кода и его читаемость наоборот отличались сильно, чтоб комбинирование комбинаторов можно было действительно использовать, а не обсуждать его на форумах.
Для этого нужно:
0) Контроль эффектов, чтоб были функции и было что комбинировать.
1) Быстрый сборщик мусора для нормальных замыканий.
2) Карринг и соответствующая поддержка от рантайма.
3) Ленивость и соответствующая поддержка от рантайма.
4) Оптимизирующий компилятор.
5) Стек в куче чтоб нормальная поддержка рекурсии была.
6) Легковесный синтаксис.
7) Что-то еще, что навскидку не вспомнилось.
итого, целый ФЯ, да еще и не любой-каждый ФЯ.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
В пункте 1 большой проблемой считается невозможность написания обобщённого интерфейса для произвольного функтора (в терминологии хаскеля). А оно вообще кому-то надо? )))
В пунктах 2 и 3 ругаются на падения компилятора (который в бета-версии) — это вообще странно комментировать...
Здравствуйте, alex_public, Вы писали:
DM>>http://schani.wordpress.com/2014/06/11/associated-types-considered-weird/
_>В пункте 1 большой проблемой считается невозможность написания обобщённого интерфейса для произвольного функтора (в терминологии хаскеля). А оно вообще кому-то надо? ))) _>В пунктах 2 и 3 ругаются на падения компилятора (который в бета-версии) — это вообще странно комментировать...
Твои пункты — совсем из другой статьи. Ссылку-то открой.
А по поводу хитрой системы совмещения шаблонов и интерфейсов я как раз писал уже здесь, что заметил это, но пока ещё не разобрался зачем оно так. И от данной критики особо понятнее пока не стало. )))
Здравствуйте, alex_public, Вы писали:
_>В пункте 1 большой проблемой считается невозможность написания обобщённого интерфейса для произвольного функтора (в терминологии хаскеля). А оно вообще кому-то надо? )))
_>>В пункте 1 большой проблемой считается невозможность написания обобщённого интерфейса для произвольного функтора (в терминологии хаскеля). А оно вообще кому-то надо? ))) DM>Мне надо.
Так а где там универсальный интерфейс "Imappable"? ) Я вижу там реализацию одиночного класса и вроде как это не должно быть проблемой на Swift'e.
Здравствуйте, VladD2, Вы писали:
V>>Бывает так, что запуск программы требует время (на всю установку некоего тяжеловесного окружения). Скажем, запуск вижуал-студии. V>>В этом смысле REPL банально удобнее, т.к. уже при установленном некоем окружении позволяет "играть" с ним. VD>В отладчике можно вызвать функцию, поменять значения и даже изменить код программы. Этого более чем достаточно для отладки. А вот писать большую программу из репла — это утопия.
Оказывается, LISP и Forth это утопии. Ах да, BASIC образца ранних персоналок — тоже.
Почитал ветку/поучаствовал в ней. И все, что могу сказать: вы все наркоманы, и не лечитесь.
«О боже Apple не сделали в своем языке <вставить один из 100500 фич двух десятков разных языков разной степени маргинальности>».
Вы с дуба рухнули? У Apple'а была задача:
— избавиться от Objective-C, который дальнейшим улучшениям не поддается
— создать язык, полностью совместимый с Objective-C на уровне рантайма
— создать язык, полностью совместимый с Objective-C на уровне библиотек
— создать язык, в первую очередь предназначенный для разработки для и работы под iOS
— создать язык, совместимый с существующим инструментарием
— создать язык, в первую предназначенный для:
-- людей, которые уже разрабатывают под iOS
-- людей, которые хотят начать разрабатывать под iOS
В рамках заданных ограничений Apple создали достаточно приятный язык.
Здравствуйте, NeoCode, Вы писали:
NC>Странный подход, написано free, в фиг скачаешь без этого вашего тунца. Как они собираются привлекать разработчиков, не имевших до этого дела с эппл?
Вот здесь http://swiftlang.eu/
можно свободно почитать в pdf формате. Плюс к этому куча примеров.
Здравствуйте, Klapaucius, Вы писали:
V>>Это зависит от того, что "видит" компилятор — сам объект или только его адрес. Если компилятор С++ видит Cat по-значению (на стеке, глобальную переменную или как поле другого объекта), то он вызывает методы напрямую,
K>Ну так тут и полиморфизма ООПешного нет.
Так он и не нужен. ООП-полиморфизм нужен там где нужен, т.е. где именно в рантайм, согласно условию, требуется диспетчеризация. В этом случае ООП-полиморфизм делает сию диспетчеризацию типобезопасной, только и всего (в сравнении с аналогиным решением на С, например).
V>>>>Известно только если компилятор не видит точный (конечный) тип объекта. Если же видит, то вызывает виртуальные методы напрямую, без таблицы. Именно поэтому я вижу тут аналогию.
K>ОК, сформулирую по-другому. При параметрическом полиморфизме больше сценариев использования, когда компилятор видит "точный (конечный)" тип, полиморфизм через сабтайпинг достигается "стиранием" информации о "точном" типе. Естественно, совсем без "стирания" не обойтись и для этого средства везде есть, но ООП-подход такому стиранию благоприятствует.
Это попахивает твоими собственными ощущениями.
Поделюсь своими.
Среди всех случаев вызовов методов объектов в реальных программах на С++ можно наблюдать лишь единицы %% мест с виртуальными вызовами. Обобщенное программирование даже в реалиях С++ и общепринятая в нём же идеология преимущественного размещения объектов по-значению сводит кол-во этих рантайм-диспетчеризаций ровно к тому кол-ву, которое у тебя было бы и на других языках, даже на тех, где есть параметрический полиморфизм. Например, где речь шла бы о последовательности абстрактных Pet.
Повторюсь, я внимательно одно время рассматривал скомпилированные примеры на Хаскеле с использованием классов типов и параметрическим полиморфизмом, где в ООП в аналогичном случае без виртуальных вызовов не обойтись, — наблюдал, что происходит точно такая же диспетчеризация в рантайм по адресу ф-ии, аналогично вызову виртуальной ф-ии в ООП-программе (то бишь вызов не по вшитому адресу ф-ии, а по прочитанному из памяти).
V>>По отношению к парадигме ООП, наследование реализаций — это просто некий трюк где-то сбоку. Можно взять для рассмотрения более строгую парадигму КОП — наследование только интерфейсов.
K>И чем это нам тут поможет?
По безопасности это будет аналог классов типов, т.к. единственная страшная грабля ООП — это дауншифтинг или любое динамическое приведение типов. В этом гипотетическом случае, если классом объекта нельзя будет оперировать напрямую, а только через интерфейс, то будут так же безопасно.
V>>Ну и в обычных пользовательских классах доля виртуальных методов далеко не 100%, а как бы заметно ниже 50%. K>Мы вроде про полиморфный код говорим. Как тут в ООП без виртуальных методов?
Да вот так! ))
По дизайну метод виртуальный. А реальных мест, где этот же самый метод нужен именно как виртуальный — оч мало.
ООП — это не столько виртуальные методы, сколько концепция типов-черных ящиков с собственным состоянием. При наличии шаблонов даже уровня С++, виртуальность становится необходима ровно там, где в решении не обойтись без рантайм-диспетчеризации. В Хаскеле в аналогичных случаях будет или параметрический полиморфизм + классы типов и деспетчеризация по адресу ф-ии, либо обычная диспетчеризация на паттерн-матчинге.
V>>В общем, с заявлением "В ООП сложно обозначить область где рантайм-полиморфизм не требуется" согласиться оч сложно. По-сути, ты приписал всему ООП ограничения пары популярных платформ — дотнета/джавы. V>>Более того, нет никаких ограничений, даже в условиях GC, располагать объекты по-значению в теле объектов-владельцев.
K>Как их располагать по значению в условиях полиморфизма? Разные типы по размеру отличаются. Поэтому и хранится ссылка, котороая по размеру не отличается, вне зависимости от того, на какой наследник Pet она указывает.
Вот так и располагать, если процедура создания объекта не требует абстракции (а она оч редко требует абстракции, абстракции при создании графов объектов обычно нужны на уровне совсем "крупных мазков" архитектуры).
Зато этот внутренний объект, размещенный как поле по значению, можно подавать на "входную точку" некоего внешнего алгоритма, принимающего абстракции. А если этот алгоритм обобщенный на шаблонах — то опять методы могут быть вызваны не виртуально, т.к. компилятор, наблюдая в месте вызова объект по значению, знает его точный тип.
В общем, если сравнивать ссылочный граф объектов в памяти в программе на дотнете/джаве с графом объектов программы на С++, то в последнем случае этот граф будет на порядок-другой скромнее. Ссылочные места будут ровно в тех случаях, где это требуется по дизайну, а не потому, что другого способа комбинирования типов и нет. ))
K>>>Виртуальные вызовы только какой-нибудь трассирующий джит нормально устранить сможет. V>>Намного больше их устранит нивелирование избыточной/ненужной косвенности.
K>Как ее для полиморфного кода нивелировать?
Вопрос неправильно поставлен. На было спросить так: "как нивелировать рантайм-полиморфизм там, где она не требуется по алгоритму". Об этом я и распинаюсь уже 3-й пост.
Собсно, все твои аргументы стоят на том, что в Хаскель легко избежать избыточного рантайм-полиморфизма, а в привычном тебе C# — нет.
K>>>Поэтому, там где рантайм полиморфизм требуется — там он везде будет. А там, где не требуется — в ООП скорее всего будет, а в хаскеле — нет. V>>Косвенность и ООП — тоже ведь вещи ортогональные. K>И что без нее от ООП остается? ООП-ешный полиморфизм без нее не работает.
От ООП остаётся способ комбинирования типов с хранимым состоянием. Спор тут идёт лишь относительно того, что из полиморфного работает на этапе компиляции, а что на этапе исполнения.
K>Непонятно, какой смысл сравнивать Cat и Cat* если речь идет про, скажем, Pet*. Как в Cat cats хранить Dogs и применять к каждому эдементу такого массива обобщенную функцию kill, которая для Cat и для Dog определена?
Именно что. Давай ограничим сценарии фактического применения рантайм-полиморфизма только заранее запланированными по сути решения задачи.
V>>Это не из-за сабтайпинга, а из-за того, что только при косвенной адресации сабтайпинг начинает нам мешать. K>Ну естественно. Он и работать только при косвенной адресации начинает.
Проблема в том, что в дотнете/джаве он работает даже тогда, когда в конкретном месте вызова метода этого вовсе не требуется.
V>>Это всё унаследованный от джавы кретинизм. Парадигма ООП тут не при чем. K>Никакой джава-специфики тут нет. ООП-полиморфизм в основном так и реализуется.
Нет. ))
Изначально именно такого ООП-полиморфизма и не было. Но само ООП было. ))
V>>В С++ более распространены их статические варианты: traits и "статический визитор". А так-то да. Если забыть, что речь шла про операторы... )) K>Ну так и обсуждаемый вариант на C# — статический.
Дудки. Для каждого типа-словаря value-type в твоём примере в рантайм будет генерироваться уникальный код генерика. По моим представлениям это оч далеко от статики. ))
V>>С операторами удобнее таки через явное указание "модуля", то бишь области видимости. Именно таким образом мы "передаем словарь" один раз на всю текущую область видимости (через указание других видимых явно "модулей"), т.е. не надо передавать в каждый метод. Очень даже оправданный подход, коль речь не о вызовах методов, а о глобальных ф-иях/операторах.
K>Не считаю, что это хороший подход (хотя широко практикуемый в ML-ях). В одном выражении и в одной области видимости может быть + и для int и для double.
Ты не понял. Как раз перегруженные сигнатуры операторов + для int и для double прекрасно разруливаются компилятором в одной области видимости. Речь о случае когда для надо указать некую специальную реализацию + для некоего пользовательского Double, — например, у нас есть быстрая арифметика пониженной точности на SSE-регистрах, и медленная повышенной точности на стандартных регистрах с плавающей запятой. У тебя на C# надо явно передавать словарь в каждой строчке кода, а в С++ можно указать произвольный using namespace в произвольном по охвату scope.
V>>Меня интересует библиотечная либа, умеющая вызывать kill Pet a, которая еще ничего не знает о Cat и Dog, и которая принимает на входе выраженную каким-либо способом последовательность абстрактных Pet a. K>Если работать c Pet (без a) — то будет рантайм диспетчеризация, как в ООП — как иначе-то?
О чем и речь. В ООП вполне можно свести кол-во рантайм диспетчеризаций к аналогичному в ФП.
Наконец я вернулся к самому началу того, о чем говорил насчет Swift.
K>Ну да, и что? Это никак не отменяет фактической разницы случаев, когда нужно выбирать между ветками вычислений и когда не нужно. Во втором случае "выбор" устраним на этапе компиляции и на практике устраняется в значительном числе случаев.
Это зависит от системы типов и принципов формирования бинарного кода. В C# не устранимо никак в большинстве случаев.
V>>Вызов виртуального метода и есть "просто dereferencing". K>Не просто. Мы не знаем до рантайма какой метод вызываем. Тут же все в компайл-тайм известно, это как поле структуры прочитать.
Там где в Хаскеле тоже будет рантайм-диспетчеризация, там тоже будет точно такой же косвенный вызов, а не прямой.
V>>В плюсах в исходниках нужны только заголовочные файлы для этого случая, а тело методов может быть библиотечным. Если мы всё еще об одном и том же — о реализации словаря ComplexNumber, например. ну и инлайнинг на сегодня может выполняться во время линковки, не только во время компиляции.
K>Так я и говорю, решение с передачей словаря лучше подходит для раздельной компиляции.
Ортогонально. Прочитать объявления ф-ий и скомпилировать их тела — это несравнимая работа для компилятора. Если рассматривать компиляцию тел ф-ий, то получим раздельную компиляцию и в С++.
V>>- LLVM последних версий отстаёт от самого лучшего GC уже всего лишь в полтора раза на специальных тестах и почти не отстаёт на "обычном" коде. K>Разница в производительности генерируемого кода между clang и компиляторами других языков, использующих LLVM вполне наблюдаема.
Это больше проблема самой LLVM. Оптимизирующие компиляторы — это дорогое удовольствие.
V>>В общем, потенциал неплох. По-сути, это прямой конкурент D. K>У меня впечатление, что у D возможности побогаче.
Они у него противоречивее, увы. Кое-что "красивого" добавлялось позже, но не удалялась первоначальная кривизна. ))
K>Тут как раз не все так просто. Эппл, конечно, имеет возможность сделать его не менее популярным, чем Objective-C и тем же самым способом, ну так и за пределами эппловской платформы у него будет популярность, как у Objective-C.
Там достаточная емкость рынка для того, чтобы язык был оч популярным. Сотни тыщ разрабов по всему миру — это не мелочь. В первые 5 лет у джавы было меньше.
Здравствуйте, Ikemefula, Вы писали:
I>Я просил upward, a ты выдал downward. За ликбезом смотри рядом пост alex_public.
Ты порядком утомляешь своей невнимательностью. Иногда обсуждать что-либо с тобой просто невозможно — настолько жестоко ты тормозишь. Ладно бы еще извинился и поправился, но ты же проявляешь упрямство, сравнимое только с твоей несообразительностью.
Последний раз. Для жителей Крайнего Севера — репост:
В первом случае замыкание можно безопасно сохранить во внешнем контексте, во втором — нет.
В первом случае хоть вверх, хоть вбок. Во втором случае — только вниз по стеку.
Обрати внимание на комменты:
// по значению
...
// по ссылке
В первом случае будут копии значений. Именно поэтому пропадает зависимость от контекста, что мы не ссылаемся ни на какой контекст, а захватили копии значений в лямбду. Саму лямбду затем можно копировать произвольное кол-во раз, порождая произвольное кол-во копий. Такая лямбда иммутабельна, со всеми вытекающими.
Здравствуйте, vdimas, Вы писали:
I>>Я просил upward, a ты выдал downward. За ликбезом смотри рядом пост alex_public.
V>Ты порядком утомляешь своей невнимательностью. Иногда обсуждать что-либо с тобой просто невозможно — настолько
До свидания. Приходи когда научишься приводить адекватный код.
Здравствуйте, vdimas, Вы писали:
V>Ес-но, реализация арифметических операторов для Complex должна быть где-то описана. Но не дважды же! В Хасклеле бери любую либу с каким-нить MegaComplex, да пользуйся. А в твоём решении на C# надо еще раз по операторам пройтись да продублировать их. Что-то не так в консерватории, не правда ли? ))
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, vdimas, Вы писали:
V>>Ес-но, реализация арифметических операторов для Complex должна быть где-то описана. Но не дважды же! В Хасклеле бери любую либу с каким-нить MegaComplex, да пользуйся. А в твоём решении на C# надо еще раз по операторам пройтись да продублировать их. Что-то не так в консерватории, не правда ли? ))
AVK>Все течет, все изменяется. http://referencesource.microsoft.com/#mscorlib/system/int32.cs — обрати внимание на закомментированное.
Здравствуйте, alex_public, Вы писали:
_>Вообще то как раз только интроспекция времени компиляции (как в том же D) и имеет смысл для статически типизированных компилируемых языков. А убогие интроспекции времени исполнения, как в Java/C# — это только от недостатка умения.
Видишь ли, есть задачи для рефлексии, которые статически нерешаемы в принципе.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>