В соседней темке идёт длинная вялотекущая дискуссия на тему сочетания одновременной красоты (удобности, корректности и т.п. субъективных понятий) кода и его быстродействия. В контексте сравнения различных парадигм, а так же сравнения мультипарадигменных языков с так сказать чистыми. Кстати, забавно (см. ниже), что при этом упоминался язык D и рассматривались примеры с обработкой изображений. Ну и лично моя позиция всегда заключалась в том, что будущее за мультипарадигменными языками, которые впитают в себя всё лучшее.
Так вот, на днях я натолкнулся на эту http://habrahabr.ru/post/218429/ замечательную статью и хочу поделиться ею с вами. Очень советую внимательно посмотреть на примеры кода там — на мой взгляд это как раз код максимально в стиле языка D (который ярко выраженный мультипарадигменный). Здесь взято всё лучшее из функциональной и императивной парадигмы и щедро приправлено сверху метапрограммированием. В итоге получился очень красивый, удобный, строгий код, который при этом является ещё и очень быстродействующим.
Думаю это не только прекрасный пример для демонстрации моей точки зрения на тему перспективности различных направлений, но и весьма любопытный образец по настоящему современного мультипарадигменного кода.
Re: Язык D - действительно красота и эффективность в одном ф
Когда же вы, любители мертвых языков, наконец поймете, что в языке важнее всего не красота, правильные парадигмы или еще что-то невероятно полезное с точки зрения разработчика, а предсказуемость развития и поддержка. Язык может быть каким угодно красивым, правильным и т.д. но совершенно не предсказуемым, как D и посему недопустимым к использованию в подавляющем большинстве проектов, за редким исключением. Под редкое исключение попадают те проекты, где Сам Автор (как же я рад что он D, а не C++ увлекается в первую очередь) доступен на постоянной основе, т.е. в Фэйсбчке, да и все на этом.
Re[2]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Когда же вы, любители мертвых языков, наконец поймете, что в языке важнее всего не красота, правильные парадигмы или еще что-то невероятно полезное с точки зрения разработчика, а предсказуемость развития и поддержка. Язык может быть каким угодно красивым, правильным и т.д. но совершенно не предсказуемым, как D и посему недопустимым к использованию в подавляющем большинстве проектов, за редким исключением. Под редкое исключение попадают те проекты, где Сам Автор (как же я рад что он D, а не C++ увлекается в первую очередь) доступен на постоянной основе, т.е. в Фэйсбчке, да и все на этом.
В языке прекрасна именно его эстетическая ценность. А на работе все равно писать приходится на том, на чем пишет команда (а это нередко десятки, если не сотни человек).
Re[2]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Когда же вы, любители мертвых языков, наконец поймете, что в языке важнее всего не красота, правильные парадигмы или еще что-то невероятно полезное с точки зрения разработчика, а предсказуемость развития и поддержка.
Ну, такие языки можно пересчитать по пальцам одной руки. Остальные языки не нужны?
Тот же Rust в настоящее время не живее D, и взлетит ли он — неизвестно.
Re[3]: Язык D - действительно красота и эффективность в одно
Здравствуйте, AlexRK, Вы писали:
ARK>Ну, такие языки можно пересчитать по пальцам одной руки. Остальные языки не нужны?
Ничего подобного. Подобных языков очень и очень много: C++, Java, C#, Python, Ruby, Scala, Erlang, Objective-C, Haskell, Clojure. Честно говоря, еще долго можно перечислять.
ARK>Тот же Rust в настоящее время не живее D, и взлетит ли он — неизвестно.
В настоящее время, язык которому 4 года не живее языка которому 13 лет. Это реально "достижение" со стороны D, т.к. за 13 лет уж можно было бы родить что-то применимое для промышленного использования или перестать насиловать труп.
Вероятность взлета выше по одной простой причине. D пишут потому, что Александреску интересно. Rust пишут потому, что Мозилле и Самсунгу он нужен в их проектах. Разница заметна?
Re[3]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, x-code, Вы писали:
XC>В языке прекрасна именно его эстетическая ценность. А на работе все равно писать приходится на том, на чем пишет команда (а это нередко десятки, если не сотни человек).
Любой язык, теоретически, может быть использован в проектах, если будет доказана экономическая выгода от этого. Когда-то, давным давно, я присматривался к D, и, к счастью, правильно оценил его перспективы
Re[4]: Язык D - действительно красота и эффективность в одно
Здравствуйте, kaa.python, Вы писали:
KP>Ничего подобного. Подобных языков очень и очень много: C++, Java, C#, Python, Ruby, Scala, Erlang, Objective-C, Haskell, Clojure. Честно говоря, еще долго можно перечислять.
Scala, Clojure, Haskell и Erlang из этого списка надо убрать. В Scala чуть ли не в каждом релизе компилятора ломающие изменения, Haskell развивается непредсказуемо, Clojure мертвый. Поддержка у всех тоже швах.
Erlang — нишевой язык, не является general purpose language.
В действительности, из более-менее стабильных и поддерживаемых языков общего назначения — C, C++, Objective-C, C#, Java, Ruby, Python. С большой натяжкой Ada и Go. Вроде все.
KP>В настоящее время, язык которому 4 года не живее языка которому 13 лет. Это реально "достижение" со стороны D, т.к. за 13 лет уж можно было бы родить что-то применимое для промышленного использования или перестать насиловать труп.
Ну, Python тоже долго не взлетал, насколько я помню.
KP>Вероятность взлета выше по одной простой причине. D пишут потому, что Александреску интересно. Rust пишут потому, что Мозилле и Самсунгу он нужен в их проектах. Разница заметна?
Да, согласен, что вероятность взлета выше. Но в истории есть случаи, когда и в таких ситуациях не взлетало.
Re[4]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Любой язык, теоретически, может быть использован в проектах, если будет доказана экономическая выгода от этого. Когда-то, давным давно, я присматривался к D, и, к счастью, правильно оценил его перспективы
Ну мы же здесь на форуме "философия программирования", а не на форуме "экономика программирования". Я рассматриваю это именно как интересную тему для обсуждения фич языков. А "взлетит/не взлетит" конкретный язык — какая разница? Все проекты открытые, если к примеру народу понравится какая-то фича в том же D, что мешает силами сообщества перенести ее в Rust или даже в C++?
Люди пишут reactos, haiku, colibri, вряд ли это можно рассматривать как коммерческие проекты, но пишут же. Да тот же linux пишут не только корпорации, но и простые программисты.
Re[5]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, x-code, Вы писали:
XC>Ну мы же здесь на форуме "философия программирования", а не на форуме "экономика программирования". Я рассматриваю это именно как интересную тему для обсуждения фич языков. А "взлетит/не взлетит" конкретный язык — какая разница? Все проекты открытые, если к примеру народу понравится какая-то фича в том же D, что мешает силами сообщества перенести ее в Rust или даже в C++?
Взлетит/не взлетит разница есть мне кажется. Дело в том, что если тебе нравится какой-то инструмент, то казалось бы очевидным попытаться продвинуть этот инструмент в рабочие проекты. Поэтому и увлечения стоит как-то подгонять под реальность. Но, может быть, я слишком уж практично подхожу.
XC>Люди пишут reactos, haiku, colibri, вряд ли это можно рассматривать как коммерческие проекты, но пишут же. Да тот же linux пишут не только корпорации, но и простые программисты.
Да и Brainfuck кто-то написал
Re: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
Пользуясь случаем, хочу спросить про строки в D. Смущает, что как-то много вариантов есть. С обычными строками всё понятно, но ещё есть:
auto s1 = r"raw string\n\r";
auto s2 = `raw string\n\r`;
Ну тут ещё ладно, в документации даётся пояснение:
The ` character is not available on some keyboards and the font rendering of it is sometimes indistinguishable from the regular ' character. Since, however, the ` is rarely used, it is useful to delineate strings with " in them.
Впрочем, это довольно странно. Зачем было вводить второй вариант вообще? Да и раз не особо ломающих изменений боятся — убрали бы лишнюю сущность. Или хотя бы депрекейтед объявили.
Плюс строки с "особыми разделителями", список которых, впрочем, жестко задан ('[', '(', '<', '{'):
auto s3 = q"(raw string\n\r)";
auto s4 = q"[raw string\n\r]";
auto s5 = q"<raw string\n\r>";
auto s6 = q"{raw string\n\r}";
auto s7 = q"|raw string\n\r|"; // По идее, это не разрешено. Но работает.
Причём разделители могут быть вложены, что мне тоже кажется не сильно полезным.
Ну и наконец произвольные разделители-ограничители:
auto s8 = q"EOS
raw string\n\r
EOS";
Причём записать в одну строчку нельзя. Имхо, плюсовый вариант получился как-то логичнее и удачнее, пусть и появился "недавно":
auto s = R"EOS(raw string\n\r)EOS"
Я что-то упускаю и в этом многообразии есть смысл?
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали:
DE>Причём записать в одну строчку нельзя. Имхо, плюсовый вариант получился как-то логичнее и удачнее, пусть и появился "недавно": DE>
DE>auto s = R"EOS(raw string\n\r)EOS"
DE>
DE>Я что-то упускаю и в этом многообразии есть смысл?
Скорее всего, в данном случае разработчики стандарта С++ смотрели на ошибки дизайна D, а не наоборот.
Re[2]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Когда же вы, любители мертвых языков, наконец поймете, что в языке важнее всего не красота, правильные парадигмы или еще что-то невероятно полезное с точки зрения разработчика, а предсказуемость развития и поддержка. Язык может быть каким угодно красивым, правильным и т.д. но совершенно не предсказуемым, как D и посему недопустимым к использованию в подавляющем большинстве проектов, за редким исключением. Под редкое исключение попадают те проекты, где Сам Автор (как же я рад что он D, а не C++ увлекается в первую очередь) доступен на постоянной основе, т.е. в Фэйсбчке, да и все на этом.
1. Вообще то это всё оффтопик в данной теме — она про красоту и эффективность кода, а не про подобные вопросы.
2. Если говорить о проблемах языка вообще, то у D их действительно не мало. И главные как раз не в вышеописанном, а в отсутствие некоторых библиотек и инструментов (типа полноценной интеграции в ключевые IDE).
3. Если же говорить о "непредсказуемости развития", то например мы используем D в пробном проекте уже почти год и не наткнулись ни на одно ломающее изменение (и это при использование некоторые жирные библиотеки на D, т.е. объём кода очень солидный), хотя стараемся использовать последнюю версию компилятора.
Ну и возвращаясь к теме — можно увидеть пример кода с подобной функциональностью и быстродействием на не "мёртвом языке"?
Re[3]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>1. Вообще то это всё оффтопик в данной теме — она про красоту и эффективность кода, а не про подобные вопросы.
В чем красота? C++11/14 дает не менее красивый код Ну а по эффективности, думаю ты и сам понимаешь что тут мерить с плюсами бессмысленно.
_>3. Если же говорить о "непредсказуемости развития", то например мы используем D в пробном проекте уже почти год и не наткнулись ни на одно ломающее изменение (и это при использование некоторые жирные библиотеки на D, т.е. объём кода очень солидный), хотя стараемся использовать последнюю версию компилятора.
О, а можно поподробнее? Некрофилов нужно знать в лицо, а то вдруг занесет ненароком, а таааам...
_>Ну и возвращаясь к теме — можно увидеть пример кода с подобной функциональностью и быстродействием на не "мёртвом языке"?
Где код на C++11/14 искать знаешь?
Re[4]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Здравствуйте, alex_public, Вы писали:
_>>1. Вообще то это всё оффтопик в данной теме — она про красоту и эффективность кода, а не про подобные вопросы.
KP>В чем красота? C++11/14 дает не менее красивый код Ну а по эффективности, думаю ты и сам понимаешь что тут мерить с плюсами бессмысленно.
В том-то и проблема, что ++ такими темпами попер в развитии, оставаясь языком, в котором _легко_ просчитать вплоть до инструкции, что куда скомпилируется, что будущее дей, грусти и гоев выглядит весьма и весьма безрадостным.
<Подпись удалена модератором>
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
DE>Ну тут ещё ладно, в документации даётся пояснение:
DE>The ` character is not available on some keyboards and the font rendering of it is sometimes indistinguishable from the regular ' character. Since, however, the ` is rarely used, it is useful to delineate strings with " in them.
Впрочем, это довольно странно. Зачем было вводить второй вариант вообще? Да и раз не особо ломающих изменений боятся — убрали бы лишнюю сущность. Или хотя бы депрекейтед объявили.
Ну как раз иметь два вида строк с разными кавычками — это вполне удобно. Такое я уже видел в разных языках и вполне удачно используется. Правда тогда и r"" вводить не было смысла. Но тут ещё есть варианты совместимости с C/C++, да и вот вышеуказанные причины... В целом тут действительно видится излишество.
DE>Плюс строки с "особыми разделителями", список которых, впрочем, жестко задан ('[', '(', '<', '{'): DE>
DE>auto s3 = q"(raw string\n\r)";
DE>auto s4 = q"[raw string\n\r]";
DE>auto s5 = q"<raw string\n\r>";
DE>auto s6 = q"{raw string\n\r}";
DE>auto s7 = q"|raw string\n\r|"; // По идее, это не разрешено. Но работает.
DE>
DE>Причём разделители могут быть вложены, что мне тоже кажется не сильно полезным.
Это сделано для удобной записи строк содержащих кавычки и т.п. ) Правда опять же непонятно к чему подобное разнообразие (кстати, в коде выше это не ошибка — разделителем может служить любой одиночный знак) сделано. На мой взгляд было бы достаточно одного варианта. С другой стороны подобное разнообразие не напрягает, т.к. все возможные варианты работают строго одинаково.
DE>Ну и наконец произвольные разделители-ограничители: DE>
DE>auto s8 = q"EOS
DE>raw string\n\r
DE>EOS";
DE>
DE>Причём записать в одну строчку нельзя. Имхо, плюсовый вариант получился как-то логичнее и удачнее, пусть и появился "недавно": DE>
DE>auto s = R"EOS(raw string\n\r)EOS"
DE>
Вариант с произвольным разделителем полезен для задания произвольного текста (в котором может встретится что-то вроде )"). Довольно специфическая вещь, но опять же есть во многих языках. В целом это выглядит как единая вещь с предыдущим пунктом. Насчёт сравнения с C++ — ну не знаю. Если честно, я произвольные разделители вообще не использовал ни разу. А вот вариант записи просто row строк как раз в D удобнее.
DE>Я что-то упускаю и в этом многообразии есть смысл?
В большей части этого действительно есть смысл. Но и подкорректировать есть что. Я бы всё же несколько подсократил разнообразие, при сохранение всех возможностей.
Кстати, а тут ещё были пропущены шестнадцатеричные строки (типа auto s=x"00 FBCD 32FD 0A"; ) и самое интересное, строки токенов (типа auto s=q{token string}; ). Причём последнее как раз интенсивно используется в статье, из-за которой я и завёл данную темку.
Re[4]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>В чем красота? C++11/14 дает не менее красивый код Ну а по эффективности, думаю ты и сам понимаешь что тут мерить с плюсами бессмысленно.
А ты точно внимательно смотрел на код в той статье? Лично я как раз специалист в C++ (гораздо больший чем в D) и я прекрасно вижу, что значительную часть того кода повторить на C++ просто невозможно. Т.е. я безусловно могу написать на C++ графическую библиотеку с той же итоговой функциональностью и быстродействием, но объём и выразительность кода этой библиотеки будет несравнима с этим вариантом на D.
KP>О, а можно поподробнее? Некрофилов нужно знать в лицо, а то вдруг занесет ненароком, а таааам...
Что поподробнее? )
KP>Где код на C++11/14 искать знаешь?
Подобный тому что в статье? ) Не знаю. )
Re[5]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>А ты точно внимательно смотрел на код в той статье? Лично я как раз специалист в C++ (гораздо больший чем в D) и я прекрасно вижу, что значительную часть того кода повторить на C++ просто невозможно. Т.е. я безусловно могу написать на C++ графическую библиотеку с той же итоговой функциональностью и быстродействием, но объём и выразительность кода этой библиотеки будет несравнима с этим вариантом на D.
Внимательно. Не впечатляет. Ну код, ну не очень много его. И главный вопрос: и что с того?!
KP>>О, а можно поподробнее? Некрофилов нужно знать в лицо, а то вдруг занесет ненароком, а таааам... _>Что поподробнее? )
Название компании в РФ где применяют D в проектах. Ты же явно не в Фэйсбучике.
Re[6]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Внимательно. Не впечатляет. Ну код, ну не очень много его. И главный вопрос: и что с того?!
С такой логикой развитие ЯП должно было бы остановиться где-то на уровне макроассемблера...
KP>Название компании в РФ где применяют D в проектах. Ты же явно не в Фэйсбучике.
Ну мы не то чтобы применяем на практике, а как раз запустили тестовый проект (который ведёт стажёр), чтобы понять можно ли применять D на практике или нет. Ну и за одно попрактиковаться в нём. Причём проектик этот даже не в нашей основной области (которая довольно специфическая), а так сказать в более приземлённой и доступной для быстрого и недорого одиночного коммерческого запуска в случае успеха. Реализуется всё на базе этого http://vibed.org фреймворка и пока что результаты можно сказать восхитительные — дохленький vds спокойно тянет нагрузку, которую при классической архитектуре потянуло бы только облако с ценой раз в 10 больше.
Re[7]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Реализуется всё на базе этого http://vibed.org фреймворка и пока что результаты можно сказать восхитительные — дохленький vds спокойно тянет нагрузку, которую при классической архитектуре потянуло бы только облако с ценой раз в 10 больше.
Чем это лучше других языков с зелёными потоками? От C++ с boost.coroutine до Go, Rust и Python?
Sapienti sat!
Re[7]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_> Реализуется всё на базе этого http://vibed.org фреймворка и пока что результаты можно сказать восхитительные — дохленький vds спокойно тянет нагрузку, которую при классической архитектуре потянуло бы только облако с ценой раз в 10 больше.
Не хочу тебя расстраивать, но такое умеет даже Python с Twisted В чем плюс именно твоего решения, кроме того что оно на прекрасном D?
Re: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>В соседней темке идёт длинная вялотекущая дискуссия на тему сочетания одновременной красоты (удобности, корректности и т.п. субъективных понятий) кода и его быстродействия. В контексте сравнения различных парадигм, а так же сравнения мультипарадигменных языков с так сказать чистыми. Кстати, забавно (см. ниже), что при этом упоминался язык D и рассматривались примеры с обработкой изображений. Ну и лично моя позиция всегда заключалась в том, что будущее за мультипарадигменными языками, которые впитают в себя всё лучшее.
_>Так вот, на днях я натолкнулся на эту http://habrahabr.ru/post/218429/ замечательную статью и хочу поделиться ею с вами. Очень советую внимательно посмотреть на примеры кода там — на мой взгляд это как раз код максимально в стиле языка D (который ярко выраженный мультипарадигменный). Здесь взято всё лучшее из функциональной и императивной парадигмы и щедро приправлено сверху метапрограммированием. В итоге получился очень красивый, удобный, строгий код, который при этом является ещё и очень быстродействующим.
_>Думаю это не только прекрасный пример для демонстрации моей точки зрения на тему перспективности различных направлений, но и весьма любопытный образец по настоящему современного мультипарадигменного кода.
Что отсутствует в языке D
Совместимость с исходным кодом на языке C. Уже существуют языки программирования, в полной мере или практически полностью совместимые с исходным кодом, написанным на языке C (Objective-C, C++ и Vala). Авторы посчитали, что дальнейшая работа в этом направлении препятствует реализации существенных возможностей. Однако они постарались не допускать нестандартного поведения заимствованых из C операторов, которое может приводить к трудно исправляемым ошибкам.
Препроцессор[13]. Включение файлов посредством #include заменено на модули с собственным пространством имён. Неструктурированные директивы типа #ifdef заменены на структурированные блоки version и debug.[14] Выполнение кода во время компиляции, включение любых константных выражений, а также чтение файлов во время компиляции могут в большинстве случаев эмулировать макро-язык C с большей надёжностью (тем не менее, некоторые возможности C утрачены, например, нельзя написать аналог #define TEXT(quotes) L ## quotes), а также открывают множество дополнительных возможностей, например перевод кода другого языка программирования в D «прямо во время компиляции».
Множественное наследование. Однако это частично компенсируется более надёжными интерфейсами, работа с которыми поддерживается языком D.
Пространства имён (namespaces). Пространства имён были попыткой решить проблему, возникающую при объединении разработанных независимо друг от друга кусков кода, когда пересекаются имена переменных, типов данных и так далее. Модульный подход выглядит проще и удобнее для использования.
Битовые поля (bit fields) произвольного размера. Битовые поля сложны, неэффективны и достаточно редко используются. Компенсируется модулем в стандартной библиотеке D 2.0[15]
Поддержка 16-битных компьютеров. В языке D нет никаких решений для генерирования качественного 16-битного кода.
Взаимная зависимость проходов компилирования (compiler passes). В языке C++ успешная обработка исходного кода основывается на таблице символов (symbol table) и различных командах препроцессора. Это делает невозможным предварительную обработку кода и значительно усложняет работу анализаторов кода.
Оператор разыменования с обращением к члену класса ->. В языке D оператор обращения к члену класса производит разыменование по умолчанию при необходимости.
То что нет множественного наследования это очень плохо. Отговорка про надёжность интерфейса звучит очень сомнительно, так как ничто не мешает при множественном наследовании сделать один интерфейс главным, а все остальные дополнительными. Плохо, когда такой возможности в принципе нет.
Я сравнил результат работы с эквивалентной командой ImageMagick:
convert \
input/*.bmp \
-depth 16 \
-gamma 0.454545 \
-filter box \
-resize 25% \
-gamma 2.2 \
-depth 8 \
output-im/%02d.bmp
Версия на D выполняется в 4-5 разра быстрее. Конечно, это нечестное сравнение: даже если обе используют 16-битную глубину цвета, гамма коррекцию, многопоточность и оптимизированы под одинаковые архитектуры, D программа содержит код специально оптимизированный для этой задачи. Если не брать в расчет различные JIT техники, пакет нельзя сравнивать с библиотеками обработки изображений общего назначения.
Истинно правильным было бы написать такой же код на С++ и сравнить. Причём баловство с компилятором тоже играет не последнюю роль. А про маркетинг не согласен, что его нет. Язык переименовали с Марса на D, то есть как бы подмазались к C++, дескать это следующее поколение языков. Хотя опять же лично моё мнение, что выразительность языке не может заменить фазы проектирования проекта. Причём пока никакой особой выразительности не заметил, но не в этом суть. Говорят же, программируйте с помощью языка, а не на языке. Язык программирования не должен заменять мышление.
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_> целом тут действительно видится излишество. _> Правда опять же непонятно к чему подобное разнообразие (кстати, в коде выше это не ошибка — разделителем может служить любой одиночный знак) сделано. На мой взгляд было бы достаточно одного варианта. _> С другой стороны подобное разнообразие не напрягает, т.к. все возможные варианты работают строго одинаково.
Вот именно, что куча вариантов, которые делают абсолютно одно и то же. По моему преимуществ тут нет, а недостаток, как минимум, лишняя сложность. Я не придираюсь, если что. Просто в С++, в основном, не нравится как раз накопившаяся гора кривостей и костылей, пусть они и оправданы из-за совместимости. А тут симпатичный язык, но постоянно всплывает какая-то фигня "в стиле С++" от которой и хотелось уйти.
_> кстати, в коде выше это не ошибка — разделителем может служить любой одиночный знак
Ну... вот тут четыре разделителя перечислены явно. А в остальном не очень ясно, что считается "подходящим символом". Буквы — нет, запятые/точки тоже. Восклицательные знак, тем не менее, таким образом использоваться может.
_>Если честно, я произвольные разделители вообще не использовал ни разу. А вот вариант записи просто row строк как раз в D удобнее.
Чем? В С++ (в этом моменте) как раз всё просто и логично:
auto s1 = R"(raw string)"; // 1
R"delimiter(raw string)delimiter"// 2
Если нужна просто raw строка — берём первый вариант. Не менее лаконично чем в D. Надо что-то более навороченное — второй. Причём он вытекает из первого, по сути, это одна конструкция. И нет 100500 отдельных правил на ровном месте.
_> Кстати, а тут ещё были пропущены шестнадцатеричные строки (типа auto s=x"00 FBCD 32FD 0A"; ) и самое интересное, строки токенов (типа auto s=q{token string}; ).
Они пропущены сознательно — это особые вещи, наличие которых понятно (и удобно).
Re[8]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Чем это лучше других языков с зелёными потоками? От C++ с boost.coroutine до Go, Rust и Python?
Да, действительно часть этой функциональности можно реализовать на C++ (хотя я бы наверное взял libevent/libev, чтобы писать поменьше велосипедов, правда фреймворк то в любом случае придётся в начале написать) и получить не меньшую производительность. С другими языками уже несколько сомневаюсь даже насчёт этой части. Но в любом случае это будет только часть, а самое интересное не получится даже на C++14. Я про встроенный язык шаблонов для страниц. Синтаксис там взят из известного по node.js jade'a, но при этом в качестве встроенного языка используется не JS, а полноценный D. Причём всё это в итоге статически компилируется... Т.е. имеем очень удобный и быстрый способ создания динамических страниц, который при этом автоматом даёт безумную скорость работы сервиса.
Ну и ещё благодаря множеству приятных фич языка программирование реально приятное — позволяет делать разные мелочи так, как в других языках невозможно в принципе. Но это уже скорее приятный бонус, а главное всё же в той необычной архитектуре фреймворка.
Re[8]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Не хочу тебя расстраивать, но такое умеет даже Python с Twisted В чем плюс именно твоего решения, кроме того что оно на прекрасном D?
Хы, даже если забыть про то, что twisted покрывает только маленькую часть фич vibe.d (причём не затрагивая самое вкусное — см. моё предыдущее сообщение), в любом случае сравнение быстродействия D с Питоном выглядит несколько смешно.
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
V>То что нет множественного наследования это очень плохо. Отговорка про надёжность интерфейса звучит очень сомнительно, так как ничто не мешает при множественном наследовании сделать один интерфейс главным, а все остальные дополнительными. Плохо, когда такой возможности в принципе нет.
С учётом того, что такое интерфейсы в D, думаю можно сказать, что множественное наследование практические есть. )))
V>
V>Я сравнил результат работы с эквивалентной командой ImageMagick:
V>...
V>Истинно правильным было бы написать такой же код на С++ и сравнить. Причём баловство с компилятором тоже играет не последнюю роль.
А прямо такой не напишешь. Ни на C++, ни на чём-то другом. А если обойтись только аналогичной функциональностью, то ImageMagick как раз на C и написана. )
V>А про маркетинг не согласен, что его нет. Язык переименовали с Марса на D, то есть как бы подмазались к C++, дескать это следующее поколение языков. Хотя опять же лично моё мнение, что выразительность языке не может заменить фазы проектирования проекта. Причём пока никакой особой выразительности не заметил, но не в этом суть. Говорят же, программируйте с помощью языка, а не на языке. Язык программирования не должен заменять мышление.
D — это как раз и есть улучшенный C++. Т.е. следующий шаг по тому же вектору развития, по которому движется C++. Кстати, в этом смысле выход C++11 немного подпортил ситуацию с D, т.к. включил много приятных фич, из-за которых стоило переходить. Но далеко не все.
Насчёт проектирования я частично согласен — в первую очередь за красоту кода отвечает человек, а не язык. К примеру я видел код на языке D, написанный в классических традициях старого голого C. Однако язык может позволяет некоторые возможности просто недостижимые с помощью других инструментов. И тут D явно один из лидеров.
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали:
DE>Вот именно, что куча вариантов, которые делают абсолютно одно и то же. По моему преимуществ тут нет, а недостаток, как минимум, лишняя сложность. Я не придираюсь, если что. Просто в С++, в основном, не нравится как раз накопившаяся гора кривостей и костылей, пусть они и оправданы из-за совместимости. А тут симпатичный язык, но постоянно всплывает какая-то фигня "в стиле С++" от которой и хотелось уйти.
Да, есть такое. Но с другой стороны и C++ и D обладают известным положительным качеством — в них понапихано очень много всего, но совершенно не обязательно это всё использовать (или даже знать, хотя всё же рекомендуется) для нормальной работы.
DE>Ну... вот тут четыре разделителя перечислены явно. А в остальном не очень ясно, что считается "подходящим символом". Буквы — нет, запятые/точки тоже. Восклицательные знак, тем не менее, таким образом использоваться может.
Это перечислены так называемые "парные разделители", а ещё могут быть не парные — просто "любой знак". Это я книжку Александреску цитирую. )
DE>Чем? В С++ (в этом моменте) как раз всё просто и логично: DE>
Если нужна просто raw строка — берём первый вариант. Не менее лаконично чем в D. Надо что-то более навороченное — второй. Причём он вытекает из первого, по сути, это одна конструкция. И нет 100500 отдельных правил на ровном месте.
Ну так как минимум лишние скобки. А если взять вариант `raw string` на D, то ещё и префикс лишний. T.e. в D чуть меньше синтаксического мусора, хотя конечно же это всё несущественные мелочи.
Re: Язык D - действительно красота и эффективность в одном флаконе
Можно спорить о разных аспектах языка.
Но метапрограммирование на строках это просто несерьезно.
Далее __traits выглядит как костыль, а не как нормальная работа с API компилятора.
Боюсь когда там это все осознают, придут к выводу, что надо создавать D 3.0
Почему это? Это же не какой-то аналог eval, работающий во время исполнения. Функция mixin отрабатывает во время компиляции и соответственно весь переданный строкой код:
— проходит все проверки на стадии компиляции, как и обычный код
— полностью попадает под все возможные оптимизации, включай инлайн и т.п.
Чего собственно ещё желать то? )
_NN>Далее __traits выглядит как костыль, а не как нормальная работа с API компилятора.
А тут что не так? )
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, _NN_, Вы писали:
_NN>>Но метапрограммирование на строках это просто несерьезно.
_>Почему это? Это же не какой-то аналог eval, работающий во время исполнения. Функция mixin отрабатывает во время компиляции и соответственно весь переданный строкой код: _>- проходит все проверки на стадии компиляции, как и обычный код _>- полностью попадает под все возможные оптимизации, включай инлайн и т.п.
Вот именно, что аналог eval.
Я предпочитаю работать с объектной моделью.
Т.е. обычный код во времени компиляции:
auto x = someClass.getMethods();
if(x.contains("someMethod")) someClass.addMethod(<[ void otherMethod() { } ]>);
_>Чего собственно ещё желать то? )
_NN>>Далее __traits выглядит как костыль, а не как нормальная работа с API компилятора.
_>А тут что не так? )
См. выше.
Здравствуйте, _NN_, Вы писали:
_NN>Вот именно, что аналог eval. _NN>Я предпочитаю работать с объектной моделью.
_NN>Т.е. обычный код во времени компиляции: _NN>
Что-то я не понял как подобное может работать во время компиляции. Т.е. вот допустим у нас есть некий класс A. И плюс где-то по коду раскиданы различные вызовы A.AddMethod(...). Так каким будет тип данных A в итоге после компиляции?
Re[3]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>2. Если говорить о проблемах языка вообще, то у D их действительно не мало. И главные как раз не в вышеописанном, а в отсутствие некоторых библиотек и инструментов (типа полноценной интеграции в ключевые IDE).
Наоборот, главные причины это именно описаные, а отсутствие библиотек, инструментов это следствие.
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>С учётом того, что такое интерфейсы в D, думаю можно сказать, что множественное наследование практические есть. )))
Можно немного подробнее?
Вообще, я не считаю это серьёзным недостатком, но один момент всё-таки смущает. Возможна ведь ситуация, когда есть две никак не пересекающиеся иерархии классов, причём без интерфейсов — просто линейное наследование. И в какой-то момент нам требуется создать наследника обеих иерархий. Так как они независимы, то никаких ужасов множественного наследования не будет. Но если в самом начале никто не позаботился об интерфейсах, то в С++ мы всё-таки можем отнаследоваться. В D (а так же С# и т.д.), насколько я понимаю, придётся всё-таки вводить интерфейсы. Так?
Понятное дело, можно заявить про "кривой дизайн" и т.д. Но тем не менее, на С++ "проблема" решается, вернее её даже нет.
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Да, есть такое. Но с другой стороны и C++ и D обладают известным положительным качеством — в них понапихано очень много всего, но совершенно не обязательно это всё использовать (или даже знать, хотя всё же рекомендуется) для нормальной работы.
Ну да, но шутки типа этой
не на ровном месте возникают. Всё-таки одно дело, когда это именно разные "части" языка добавляющие дополнительные возможности (скажем, шаблоны в С++) и другое когда куча всякой фигни, которая (почти) ничего не упрощает. Похожие мысли у меня "uniform initialization" вызывает. "Есть много способов с нюансами, которые сложно запомнит" (почти цитата), поэтому сделаем ещё один.
Оно всё логично, если знать почему, но если бы не совместимость, то можно было бы проще сделать.
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Что-то я не понял как подобное может работать во время компиляции. Т.е. вот допустим у нас есть некий класс A. И плюс где-то по коду раскиданы различные вызовы A.AddMethod(...). Так каким будет тип данных A в итоге после компиляции?
А в чем проблема то ?
В Nemerle/Scala это работает
Каждый макрос добавляет метод и компилятор создает класс со всему нужными методами.
По-моему автору(авторам) языка D не хватает критики со стороны. Уж больно похоже, что разные вещи включены в язык непродуманно, а просто потому, что авторам захотелось. Это, опять же мой взгляд со стороны. D я, можно сказать, вижу впервый раз. Кстати, не понравился синтаксис, и дело тут не в похожести или непохожести на С/C++, а в недостаточной продуманности — опять же это моё впечатление только от просмотра исходников. Всё-таки, если взять С++, там есть коммитет, то есть порядочное число людей с разными мнениями. И они всё-таки делают свою работу: новые вещи, включаемые в язык, не вызывают когнетивного диссонанса, и вписываются в старый язык органично. D же выглядит как полигон для разных идей, а ни как серьёзный, продуманный до мелочей язык программирования. Опять же это моё мнение.
__________________________________
Не ври себе.
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, _NN_, Вы писали:
_NN>Можно спорить о разных аспектах языка. _NN>Но метапрограммирование на строках это просто несерьезно.
Да, с т.з. теории это полное безобразие. Авторы Ди — прожженые плюсовики-практики, слово теория им незнакомо, они сначала делают потом думают. Выходит странная штука с кучей ручек, но удивительно удобная на практике. Не в теории.
Но конкретно про метапрограммирование на строках — эта штука на крайний случай, большинство задач решаются без ее применения. Даже когда поначалу кажется, что нужно использовать ее, потом раз-раз, тут поменял, тут упростил, все свелось к сочетанию шаблонов, компайл-тайм интроспекции и static if. Не раз это испытывал на себе.
Недавний пример. Сделал себе отслеживальщик всех аллокаций в GC-куче, чтобы быть уверенным, что в нужном мне месте конпелятор не наделал неявных аллокаций под замыкания. У Дивного рантайма есть структурка с указателями на все основные функции менеджера памяти, изначально используется для возможности задействовать один GC на несколько DLL-ок. Выглядит как-то так:
Мне нужно сгенерить аналогичный набор функций с теми же самыми типами, где будет делаться определенное действие сначала, потом вызываться оригинальная функция из той структурки, потом делаться еще одно мое действие. Отличный повод для метапрограмминга, и полностью решается без использования строк.
Завожу структурку myProxy того же типа и генерю функции так:
где FunArgsTypes — тайп-левел функция, возвращающая типы аргументов указанной по имени функции из структуры Proxy:
template FunArgsTypes(string funname) {
alias FunType = typeof(*__traits(getMember, myProxy, funname));
alias FunArgsTypes = ParameterTypeTuple!FunType;
}
И все! Тип возвращаемого результата генерящихся функций тут выводится автоматически. Генерятся они посредством шаблонов, никаких манипуляций со строками. И все это в пределах одного маленького модуля, который элементарно импортируется. Никаких заморочек с раздельными стадиями компиляции.
Если не лень, можете показать, как такая задача решается в других статически типизированных языках, сравним.
_NN>Далее __traits выглядит как костыль, а не как нормальная работа с API компилятора. _NN>Боюсь когда там это все осознают, придут к выводу, что надо создавать D 3.0
Не без этого. Те же AST-макросы там вечная тема, которую периодически упоминают, но не решаются даже начать проектировать, оставляя на гипотетическое будущее и версию 3.0.
Re[9]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>С другими языками уже несколько сомневаюсь даже насчёт этой части. Но в любом случае это будет только часть, а самое интересное не получится даже на C++14. Я про встроенный язык шаблонов для страниц. Синтаксис там взят из известного по node.js jade'a, но при этом в качестве встроенного языка используется не JS, а полноценный D.
JSP в Java, как и куча других *SP. Есть даже C++ Server Pages со встроенным С++.
Sapienti sat!
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали: DE>Вообще, я не считаю это серьёзным недостатком, но один момент всё-таки смущает. Возможна ведь ситуация, когда есть две никак не пересекающиеся иерархии классов, причём без интерфейсов — просто линейное наследование. И в какой-то момент нам требуется создать наследника обеих иерархий.
А можно сколь-нибудь убедительный пример? На первый взгляд кажется, что такой класс-наследник нарушает всякие принципы типа SRP.
Для задач типа "давайте сделаем наш класс сериализуемым" поддержка в D есть, и значительно лучше, чем в С++.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Да, действительно часть этой функциональности можно реализовать на C++ (хотя я бы наверное взял libevent/libev, чтобы писать поменьше велосипедов, правда фреймворк то в любом случае придётся в начале написать) и получить не меньшую производительность. С другими языками уже несколько сомневаюсь даже насчёт этой части. Но в любом случае это будет только часть, а самое интересное не получится даже на C++14. Я про встроенный язык шаблонов для страниц. Синтаксис там взят из известного по node.js jade'a, но при этом в качестве встроенного языка используется не JS, а полноценный D. Причём всё это в итоге статически компилируется... Т.е. имеем очень удобный и быстрый способ создания динамических страниц, который при этом автоматом даёт безумную скорость работы сервиса.
Yet another template engine
_>Ну и ещё благодаря множеству приятных фич языка программирование реально приятное — позволяет делать разные мелочи так, как в других языках невозможно в принципе. Но это уже скорее приятный бонус, а главное всё же в той необычной архитектуре фреймворка.
Это сказки. vibe это как Node.js только на D и с меньшими возможностями.
Re[10]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
I>>Это сказки. vibe это как Node.js только на D и с меньшими возможностями.
DM>Ну да, там нет callback hell, нет проблем с многопоточностью, нет тормозов, нет откладывания тупых ошибок до рантайма, и еще много чего нет.
В node.js ничего это нет, кроме тупых ошибок до рантайма. Они бывают в основном у тех, кто и строчку кода без дебуггера не может написать.
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, D. Mon, Вы писали:
DM>И все! Тип возвращаемого результата генерящихся функций тут выводится автоматически. Генерятся они посредством шаблонов, никаких манипуляций со строками. И все это в пределах одного маленького модуля, который элементарно импортируется. Никаких заморочек с раздельными стадиями компиляции.
Интересно.
А как гарантируется вызов этого всего во время компиляции ?
template это ясно, а вот вызов функции и foreach ?
DM>Если не лень, можете показать, как такая задача решается в других статически типизированных языках, сравним.
В данном случае здесь выйдет тот же код, только другой API.
Макросы Nemerle могут больше, например перезаписывать тело методов.
F([NotNull] a : object) : void { ... }
Будет после раскрытия
F(a : object) : void { when(a == null) throw ArgumentNullException("a", "a is null"); ... }
DM>Не без этого. Те же AST-макросы там вечная тема, которую периодически упоминают, но не решаются даже начать проектировать, оставляя на гипотетическое будущее и версию 3.0.
Цитирование это очень мощная штука.
Кстати в Rust уже есть макросы.
Здравствуйте, DarkEld3r, Вы писали:
DE>Можно немного подробнее?
DE>Вообще, я не считаю это серьёзным недостатком, но один момент всё-таки смущает. Возможна ведь ситуация, когда есть две никак не пересекающиеся иерархии классов, причём без интерфейсов — просто линейное наследование. И в какой-то момент нам требуется создать наследника обеих иерархий. Так как они независимы, то никаких ужасов множественного наследования не будет. Но если в самом начале никто не позаботился об интерфейсах, то в С++ мы всё-таки можем отнаследоваться. В D (а так же С# и т.д.), насколько я понимаю, придётся всё-таки вводить интерфейсы. Так?
Да, безусловно. Я имел в виду, что интерфейсы в D несколько менее ограничены (ближе к классам), чем скажем в Java. Но всё же не настолько, как абстрактные классы в C++.
DE>Понятное дело, можно заявить про "кривой дизайн" и т.д. Но тем не менее, на С++ "проблема" решается, вернее её даже нет.
Нууу, проблемы с множественным наследование в C++ действительно нет. Но только при условии, что мы говорим о нормальном специалисте в C++ (который хотя бы слышал про виртуальное наследование, представляет себе таблицы виртуальных функций в таком случае, преобразования типов и т.п.).
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
не на ровном месте возникают. Всё-таки одно дело, когда это именно разные "части" языка добавляющие дополнительные возможности (скажем, шаблоны в С++) и другое когда куча всякой фигни, которая (почти) ничего не упрощает. Похожие мысли у меня "uniform initialization" вызывает. "Есть много способов с нюансами, которые сложно запомнит" (почти цитата), поэтому сделаем ещё один. DE>Оно всё логично, если знать почему, но если бы не совместимость, то можно было бы проще сделать.
О, а чем uniform initialization не нравится то? ) Как раз очень полезная фича, можно сказать восстанавливающая справедливость. А то раньше была удобная инициализация только для C массивов, а теперь и C++ массивам (vector, array) дали. Т.е. даже если не пользоваться данной фичей самому (не делать своих функций с подобными параметрами), то просто от использования её стандартной библиотекой уже явный позитив идёт. Причём он приводит как раз к упрощению и унификации.
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали:
DE>Вообще, я не считаю это серьёзным недостатком, но один момент всё-таки смущает. Возможна ведь ситуация, когда есть две никак не пересекающиеся иерархии классов, причём без интерфейсов — просто линейное наследование. И в какой-то момент нам требуется создать наследника обеих иерархий. Так как они независимы, то никаких ужасов множественного наследования не будет. Но если в самом начале никто не позаботился об интерфейсах, то в С++ мы всё-таки можем отнаследоваться. В D (а так же С# и т.д.), насколько я понимаю, придётся всё-таки вводить интерфейсы. Так? DE>Понятное дело, можно заявить про "кривой дизайн" и т.д. Но тем не менее, на С++ "проблема" решается, вернее её даже нет.
Именно эта конкретная проблема, то есть скрещивание двух независимых иерархий в D тоже легко решается Alias This
Re[12]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>>>Это сказки. vibe это как Node.js только на D и с меньшими возможностями. DM>>Ну да, там нет callback hell, нет проблем с многопоточностью, нет тормозов, нет откладывания тупых ошибок до рантайма, и еще много чего нет. I>В node.js ничего это нет
Это сказки.
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, _NN_, Вы писали:
_NN>Интересно. _NN>А как гарантируется вызов этого всего во время компиляции ? _NN>template это ясно, а вот вызов функции и foreach ?
В данном примере идет заполнение полей структуры. Само заполнение конкретными значениями — указателями на функции происходит в рантайме, там и writeln и что угодно еще может быть. А генерация функций, на которые получаются указатели, происходит статически при компиляции.
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, _NN_, Вы писали:
_NN>А в чем проблема то ? _NN>В Nemerle/Scala это работает
_NN>Каждый макрос добавляет метод и компилятор создает класс со всему нужными методами.
Ну так а если там будет где-то код вида "if(x) A.AddMember(...);", где x — это переменная (т.е. значение не известно на время компиляции), то какой набор методов будет у типа A в итоге?
Что-то я пока так и не понял как сделать подобные вещи во время компиляции. Вот в рантайме подобное естественно без проблем, но это вообще другое дело (и на мой взгляд никчемное).
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Sinclair, Вы писали:
S>А можно сколь-нибудь убедительный пример?
Нет. (:
Единственное, что так сразу в голову приходит — это только пример с кодом, в который надо "побыстрее" изменения внести без масштавного рефакторинга и переделки архитектуры.
S>Для задач типа "давайте сделаем наш класс сериализуемым" поддержка в D есть, и значительно лучше, чем в С++.
Хотя, наверняка, можно что-то помимо сериализации придумать.
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>О, а чем uniform initialization не нравится то? )
Всем нравится, кроме того, что это "ещё один способ". Понятно, что без этого никак, потому и хочется в "более новых" языках находить меньше костылей.
Впрочем, один момент всё-таки не очень:
int i = {10}; // intauto a1 = 10; // intauto a2 = {10}; // initializer_list
Логично, но инициализация получается не такая и "uniform".
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>По-моему автору(авторам) языка D не хватает критики со стороны. Уж больно похоже, что разные вещи включены в язык непродуманно, а просто потому, что авторам захотелось. Это, опять же мой взгляд со стороны. D я, можно сказать, вижу впервый раз. Кстати, не понравился синтаксис, и дело тут не в похожести или непохожести на С/C++, а в недостаточной продуманности — опять же это моё впечатление только от просмотра исходников. Всё-таки, если взять С++, там есть коммитет, то есть порядочное число людей с разными мнениями. И они всё-таки делают свою работу: новые вещи, включаемые в язык, не вызывают когнетивного диссонанса, и вписываются в старый язык органично. D же выглядит как полигон для разных идей, а ни как серьёзный, продуманный до мелочей язык программирования. Опять же это моё мнение.
Хы, ну называть D идеальным я бы тоже не стал, но уж никак не при сравнение с C++. Особенно если вспомнить про основу современного C++ (шаблонную магию), а потом взглянуть на то, как подобное же реализовано в D.
А есть какие-то конкретные претензии к D для обсуждения или это просто некое интуитивное ощущение? )
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, FR, Вы писали:
FR>Именно эта конкретная проблема, то есть скрещивание двух независимых иерархий в D тоже легко решается Alias This
В принципе, да (реально забыл про эту возможность). Только, к сожалению, не "решается", а "решится когда-нибудь":
Note: Multiple AliasThis is currently unimplemented.
Re[10]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>JSP в Java, как и куча других *SP. Есть даже C++ Server Pages со встроенным С++.
Да, направление мысли правильное, но:
1. Всякие JSP и им подобные — это всё же не отдельный язык шаблонов (типа jade или haml), а просто html (т.е. куски текста по сути) со вставками кода.
2. У большинства *SP быстродействие используемого языка (собственно у всех, кроме C++) не сравнимо с D.
3. Далеко не у всех *SP имеется в наличие подобный асинхронный сервер.
Т.е. в данном случае vibe.d ближе скорее к node.js (с jade и т.п.), чем к jsp. Только с поправкой на использование высокопроизводительного статически типизированного компилируемого языка вместо JS.
Re[10]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Yet another template engine
Ну в общем да. Только с использованием высокопроизводительного статически типизированного компилируемого языка — это уже не такая обычная вещь. )))
I>Это сказки. vibe это как Node.js только на D и с меньшими возможностями.
Ну да, пожалуй он ближе всего к node.js. Только при этом благодаря используемому языку он:
1. Заметно быстрее (ну тут понятно всё)
2. Заметно надёжнее (благодаря строгой статической типизации и компиляции)
3. Заметно удобнее (благодаря мощному метапрограммированию — я это уже реально использовал).
Re[8]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали:
DE>В принципе, да (реально забыл про эту возможность). Только, к сожалению, не "решается", а "решится когда-нибудь": DE>
DE>Note: Multiple AliasThis is currently unimplemented.
Ну для пары классов и сейчас вполне работает.
Re[11]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Ну в общем да. Только с использованием высокопроизводительного статически типизированного компилируемого языка — это уже не такая обычная вещь. )))
Для малопопулярных статически типизированных языков вполне обычная:
Здравствуйте, FR, Вы писали:
FR>Ну для пары классов и сейчас вполне работает.
Действительно. Когда писал, то что-то не подумал, что от одного класса можно отнаследоваться.
Re[11]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Да, направление мысли правильное, но: _>1. Всякие JSP и им подобные — это всё же не отдельный язык шаблонов (типа jade или haml), а просто html (т.е. куски текста по сути) со вставками кода.
Такое тоже было, для Java в том числе. Есть даже для Питона (mako), с JIT'ом от PyPy будет сравнимо с D.
_>2. У большинства *SP быстродействие используемого языка (собственно у всех, кроме C++) не сравнимо с D.
JSP компилируется в Java, которая работает быстрее D. В частности, из-за нормального мусоросборщика, а не D-шного угрёбища.
_>3. Далеко не у всех *SP имеется в наличие подобный асинхронный сервер.
И шо? 99% всего софта тупо генерируют страничку целиком и отдают её серверу, который потом на досуге отправляет её в сокет (может и асинхронно).
Sapienti sat!
Re[9]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Ну да, первый вариант явно лишний.
Я немножко про другое — новая "универсальная" иницизация ещё и гарантирует отсутствие приведений типа. Было бы логично её везде применять, в том числе, и в связке с auto, но "внезапно" вылазит initializer_list.
Re[2]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, kaa.python, Вы писали:
KP>Когда же вы, любители мертвых языков, наконец поймете, что в языке важнее всего не красота, правильные парадигмы или еще что-то невероятно полезное с точки зрения разработчика, а предсказуемость развития и поддержка.
Эта фраза на фоне твой подписи "...Rust..." выглядит особо ценично. Вот уж где предсказуемость!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Язык D - действительно красота и эффективность в одном ф
Да, очень похоже. Жаль нет времени сравнить самому удобство и производительность. Правда после привыкания к наличию мощного метапрограммирования, все языки без него кажутся уже не такими удобными... ))) А вообще ocaml мне когда-то весьма нравился.
FR>F# — WebSharper
А вот здесь уже немного другое. Здесь уже классическая традиция MS видна: фреймворк всё за тебя делает, но при этом шаг влево или вправо — расстрел. ))) Лично я против подобной смеси клиентского/серверного кода. Ну и наконец производительность самого F# в сравнение C++/D/Ocaml... )))
Re[4]: Язык D - действительно красота и эффективность в одно
Здравствуйте, VladD2, Вы писали:
VD>Эта фраза на фоне твой подписи "...Rust..." выглядит особо ценично. Вот уж где предсказуемость!
Именно тут. Язык развиваемый парой корпораций для конкретных нужд, у которого есть вполне конкретный план развития которому следует команда, в любом случае куда предсказуемее языков развиваемых десятком энтузиастов.
Re[5]: Язык D - действительно красота и эффективность в одно
Здравствуйте, AlexRK, Вы писали:
ARK>В действительности, из более-менее стабильных и поддерживаемых языков общего назначения — C, C++, Objective-C, C#, Java, Ruby, Python. С большой натяжкой Ada и Go. Вроде все.
Go? Ты шутишь?
Руби между версиями имел такие изменения, что многие остались на старой версии. С Python тоже, вроде, проблемы были при переходе от 2.х к 3.х.
Зри в корень. C, C++ стали популярны потому что их проталкивал AT&T. C# взлетел в следствии проталкивания и поддержки MS. Objective-C — основной язык разработки Эпла. Питон тянет Гугль. Руби потихоничку загибается без поддержки, хотя язык лучше Питона.
D тоже взлетел бы, если бы за ним стояла какая-нибудь топовая компания и занимался бы его продвижением. Отсутствие бабла и пиара — это основной его недостаток.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Язык D - действительно красота и эффективность в одно
Здравствуйте, VladD2, Вы писали:
ARK>>В действительности, из более-менее стабильных и поддерживаемых языков общего назначения — C, C++, Objective-C, C#, Java, Ruby, Python. С большой натяжкой Ada и Go. Вроде все. VD>Go? Ты шутишь?
Неа. Он стал весьма популярен, многие его начали использовать in-house как такой быстрый мега-Питон (мы на нём MPI-кластеры строим). Из огромных плюсов Go — полная автономность софта на нём, т.е. можно скомпилировать бинарик, скопировать на другую машину и запускать его без установки каких-либо библиотек и framework'ов (если не использовать явно внешние нативные библиотеки).
Из крупного софта на нём написан Docker.
VD>Руби между версиями имел такие изменения, что многие остались на старой версии. С Python тоже, вроде, проблемы были при переходе от 2.х к 3.х.
Тем не менее, они поддерживаются и вполне популярны.
VD>Зри в корень. C, C++ стали популярны потому что их проталкивал AT&T. C# взлетел в следствии проталкивания и поддержки MS. Objective-C — основной язык разработки Эпла. Питон тянет Гугль. Руби потихоничку загибается без поддержки, хотя язык лучше Питона.
Питон развивают тонны компаний. У Dropbox на нём весь софт написан, например. Ruby поддерживает Github и т.д.
Sapienti sat!
Re[12]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Такое тоже было, для Java в том числе. Есть даже для Питона (mako), с JIT'ом от PyPy будет сравнимо с D.
Хыхы, похоже ты совсем не в курсе что такое D. Его главный компилятор (dmd) заметно уступает только C++, но эффективнее Java. А JavaScript или вообще Python (даже с PyPy) ещё хуже Java.
Если же взять компилятор GDC (у которого соответственно бэкенд gcc), то быстродействие становится сравнимым с C++. У него правда кое-какие глюки под виндой были, но под линухом всё идеально.
C>JSP компилируется в Java, которая работает быстрее D. В частности, из-за нормального мусоросборщика, а не D-шного угрёбища.
Кстати, нормальный код на D может практические не использовать GC (переменные на стеке и т.п. в лучших традициях C++). В том же обсуждаемом фреймворке основные типы данных объявлены как struct, а не как class и соответственно при работе с ними GC обычно не затрагивается. Я уже не говорю про эффективную работу с иммутабельными (а все строки из шаблонов как раз такими и являются) данными...
Ну и кстати мы же уже обсудили, что jsp — это совсем не то по своей изначальной структуре.
C>И шо? 99% всего софта тупо генерируют страничку целиком и отдают её серверу, который потом на досуге отправляет её в сокет (может и асинхронно).
Эээ что? ) Вот допустим берём jsp. Тут часто используют TomCat. Так вот какова схема работы TomCat, какую нагрузку он способен выдерживать, есть ли автобалансировщик и т.п.?
Re[10]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, DarkEld3r, Вы писали:
DE>Я немножко про другое — новая "универсальная" иницизация ещё и гарантирует отсутствие приведений типа. Было бы логично её везде применять, в том числе, и в связке с auto, но "внезапно" вылазит initializer_list.
Нууу это на самом деле сочетание двух новых фич в одном месте. )))
Re[6]: Язык D - действительно красота и эффективность в одно
Здравствуйте, kaa.python, Вы писали:
KP>От тебя в данном вопросе я другого и не ожидал. Все же ты еще более дохлый язык чем D уже много лет активно пилишь
Я же говорю — смешно слушать о дохлости того, что живет по 10 лет от энтузиаста языка который не родился и не факт что родится вообще. Жалко что ты не понимаешь насколько это забавно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_NN>>Каждый макрос добавляет метод и компилятор создает класс со всему нужными методами.
_>Ну так а если там будет где-то код вида "if(x) A.AddMember(...);", где x — это переменная (т.е. значение не известно на время компиляции), то какой набор методов будет у типа A в итоге?
Макрос — сущность времени компиляции как и шаблон.
Генерацией кода во времени выполнения макрос не занимается ровно как и шаблоны.
_>Что-то я пока так и не понял как сделать подобные вещи во время компиляции. Вот в рантайме подобное естественно без проблем, но это вообще другое дело (и на мой взгляд никчемное).
Может потому что тут разные цели ?
Здравствуйте, VladD2, Вы писали:
VD>Я же говорю — смешно слушать о дохлости того, что живет по 10 лет от энтузиаста языка который не родился и не факт что родится вообще.
Так в том-то и дело, что я сравниваю то, что еще не родилось, но имеет большой потенциал с тем, что не родилось и почти наверняка не родится (т.е. не будет пользоваться хоть сколь-нибудь заметной популярностью) никогда.
VD>Жалко что ты не понимаешь насколько это забавно.
Не забавнее чем положить годы на не нужный никому кроме десятка энтузиастов язык
Re[11]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Ну в общем да. Только с использованием высокопроизводительного статически типизированного компилируемого языка — это уже не такая обычная вещь. )))
Обычная.
_>Ну да, пожалуй он ближе всего к node.js. Только при этом благодаря используемому языку он: _>1. Заметно быстрее (ну тут понятно всё)
Нисколько. Ядро node.js нативное.
_>2. Заметно надёжнее (благодаря строгой статической типизации и компиляции)
Сильно вряд ли.
_>3. Заметно удобнее (благодаря мощному метапрограммированию — я это уже реально использовал).
В джаваскрипте метапрограммирование уже отменили ?
Re[13]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>В соседней темке идёт длинная вялотекущая дискуссия на тему сочетания одновременной красоты (удобности, корректности и т.п. субъективных понятий) кода и его быстродействия. В контексте сравнения различных парадигм, а так же сравнения мультипарадигменных языков с так сказать чистыми. [i]Кстати, забавно (см. ниже), что при
что в нем хорошего, в нем даже return обязателен, хотя могли бы не делать обязательным.
Re[8]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, _NN_, Вы писали:
_NN>Макрос — сущность времени компиляции как и шаблон. _NN>Генерацией кода во времени выполнения макрос не занимается ровно как и шаблоны.
А ну тогда без проблем. Только тогда подобный код должен как-то отделяться от остального. Как макросы или шаблоны в том же C++.
Re[12]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>А есть какие-то конкретные претензии к D для обсуждения или это просто некое интуитивное ощущение? )
Да найдутся — просто лень писать, будет многа букав. Позволю одно замечание: злоупотребление шорткатами это плохо. У меня сложилось впечатление, что это основная цель этого языка. K примеру, C++ не отбирает у меня контекст, он не говорит, мол вы итак понимаете контекст, поэтому он не нужен. Как раз нужен! Я не писатель, я читатель.
Только одна иллюстрация
template procedural(alias formula)
Это шаблон класса, структуры или функции? Я не должен видеть тело, чтобы это понять.
__________________________________
Не ври себе.
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, ManFeel, Вы писали:
MF>>что в нем хорошего, в нем даже return обязателен, хотя могли бы не делать обязательным.
_>А зачем делать необязательным?
для упрощения.
Re[13]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>В джаваскрипте метапрограммирование уже отменили ?
_>Ты про функцию eval что ли? ))) Это даже близко не оно...
Во первых, метапрограммирование в js доступно безо всякого eval и подобных техник.
Во вторых, возможности абсолютно одинаковые с теми, что ты показал
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
I>>Зато есть люди, которые неспособны писать код на динамическом языке.
DM>Разумеется. Все люди такие. Просто некоторые наивно думают, что они могут.
Очевидно "все" это ты и пару твоих знакомых
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Да, очень похоже. Жаль нет времени сравнить самому удобство и производительность. Правда после привыкания к наличию мощного метапрограммирования, все языки без него кажутся уже не такими удобными... ))) А вообще ocaml мне когда-то весьма нравился.
Тык OCaml (с Camlp4) как раз и есть язык с весьма мощным метапрограммированием
FR>>F# — WebSharper
_>А вот здесь уже немного другое. Здесь уже классическая традиция MS видна: фреймворк всё за тебя делает, но при этом шаг влево или вправо — расстрел. ))) Лично я против подобной смеси клиентского/серверного кода. Ну и наконец производительность самого F# в сравнение C++/D/Ocaml... )))
Насчет производительности спорить не буду, хотя для веба должно быть вполне достаточно.
А вот с метапрограммированием и асинхроностью там все вполне неплохо, скажем даже на заглавной страничке
есть примеры использования того же цитирования которое чуть выше тут обсуждалось.
Re[3]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
MF>>что в нем хорошего, в нем даже return обязателен, хотя могли бы не делать обязательным.
_>А зачем делать необязательным?
Отмена обязательного return это следсвие возможности рассматривать любой блок кода как выражение.
Re[13]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Такое тоже было, для Java в том числе. Есть даже для Питона (mako), с JIT'ом от PyPy будет сравнимо с D. _>Хыхы, похоже ты совсем не в курсе что такое D. Его главный компилятор (dmd) заметно уступает только C++, но эффективнее Java. А JavaScript или вообще Python (даже с PyPy) ещё хуже Java.
Да в курсе я про D. Быстрее он только на детских benchmark'ах. Если нужно что-то серьёзное, с большим количеством памяти и не дай б-г многопоточностью — всё упс.
C>>JSP компилируется в Java, которая работает быстрее D. В частности, из-за нормального мусоросборщика, а не D-шного угрёбища. _> Кстати, нормальный код на D может практические не использовать GC (переменные на стеке и т.п. в лучших традициях C++). В том же обсуждаемом фреймворке основные типы данных объявлены как struct, а не как class и соответственно при работе с ними GC обычно не затрагивается.
И что? В реальных программах данные не в стеке лежат. Добавляем сюда ещё отсутствие нормального межпоточного разделения данных и вообще всё уныло.
_>Я уже не говорю про эффективную работу с иммутабельными (а все строки из шаблонов как раз такими и являются) данными...
Нет там эффективной работы. Она есть только в Rust.
_>Эээ что? ) Вот допустим берём jsp. Тут часто используют TomCat. Так вот какова схема работы TomCat, какую нагрузку он способен выдерживать, есть ли автобалансировщик и т.п.?
Ну как обычно — рендериться страничка, отдаётся в буффер, Tomcat его пихает в сокет. Масштабируемость зависит от прикладного кода.
Sapienti sat!
Re[12]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, alex_public, Вы писали:
_>>Ну в общем да. Только с использованием высокопроизводительного статически типизированного компилируемого языка — это уже не такая обычная вещь. )))
FR>Для малопопулярных статически типизированных языков вполне обычная:
FR>OCaml — Ocsigen FR>F# — WebSharper
Эээ, а си шарп — тоже малопопулярный???
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Да найдутся — просто лень писать, будет многа букав. Позволю одно замечание: злоупотребление шорткатами это плохо. У меня сложилось впечатление, что это основная цель этого языка. K примеру, C++ не отбирает у меня контекст, он не говорит, мол вы итак понимаете контекст, поэтому он не нужен. Как раз нужен! Я не писатель, я читатель.
Не очень понимаю о чём речь. Лично я как раз максимально привычен к C++, но при этом на D коде (особенно шаблонном) реально отдыхаю и наслаждаюсь... )
A>Только одна иллюстрация A>
template procedural(alias formula)
A>Это шаблон класса, структуры или функции? Я не должен видеть тело, чтобы это понять.
Эээм, если речь про шаблоны классов/структур/функций в значение C++, то они записываются в D совершенно по другому (вообще без специальных ключевых слов, просто появляется дополнительный набор параметров). А ключевым словом template в D обозначаются так называемые "параметризованные контексты" — вообще отдельная вещь, точного аналога которой в C++ нет.
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, ManFeel, Вы писали:
MF>для упрощения.
Не вижу никакого упрощения. Если надо возвращать некое значение, то нам всё равно придётся записать его отдельно в конце. Так в чём тогда простота, в экономии лишнего слова? )
Re[14]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Во первых, метапрограммирование в js доступно безо всякого eval и подобных техник. I>Во вторых, возможности абсолютно одинаковые с теми, что ты показал
Угу, в рантайме то вообще всё что угодно можно творить. Но я подобное не считаю нормальным метапрограммированием. Оно тормозное и непроверяемое (на стадии компиляции). Т.е. формально говоря это конечно же МП, но на практике лучше уж без него. )))
Re[14]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
FR>Тык OCaml (с Camlp4) как раз и есть язык с весьма мощным метапрограммированием
Хы, ну с этой штукой OCaml и посильнее D становится, не говоря уже о плюсах. Но оно всегда казалось некой отдельной сущностью, а не частью языка. Т.е. вот в C++ и D шаблоны и макросы используются не только для каких-то "особенных" вещей (ну типа boost.spirit и т.п.), но и вообще повсеместно в рядовом простейшем коде для ускорения работы. А Camlp4 для таких дел кажется как-то не нормально подключать.
FR>Насчет производительности спорить не буду, хотя для веба должно быть вполне достаточно. FR>А вот с метапрограммированием и асинхроностью там все вполне неплохо, скажем даже на заглавной страничке FR>есть примеры использования того же цитирования которое чуть выше тут обсуждалось.
Не, я здесь уже не про сам язык, а именно про фреймворк. Там мягко говоря слишком многое интегрировано и слишком жёстко. Т.е. какому-нибудь студенту делающему первую страничку это может быть и классно (в пару строк уже всё само работает), но для профессионала всё же предпочтительно выбирать отдельные лучшие инструменты и не смешивать серверный/клиентский код.
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, ManFeel, Вы писали:
MF>>для упрощения.
_>Не вижу никакого упрощения. Если надо возвращать некое значение, то нам всё равно придётся записать его отдельно в конце. Так в чём тогда простота, в экономии лишнего слова? )
Да, в экономии отдельного слова.
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Cyberax, Вы писали:
C>Да в курсе я про D. Быстрее он только на детских benchmark'ах. Если нужно что-то серьёзное, с большим количеством памяти и не дай б-г многопоточностью — всё упс.
Ждём пруфлинк тогда. )
C>И что? В реальных программах данные не в стеке лежат. Добавляем сюда ещё отсутствие нормального межпоточного разделения данных и вообще всё уныло.
Как раз с межпоточным там всё удобно. Причём есть несколько разных возможных уровней работы. Можно работать на самом низком уровне (мьютексы и т.п. как в том же C++), можно на более высоком уровне синхронизации (как в java и т.п.), а можно использовать готовую полноценную систему акторов (как в эрланге). Последнее мне нравится больше всего. И всё это поддерживается соответствующими моделями памяти.
Но что самое интересное, в контексте нашей текущей беседы (фреймворка vibe.d) это всё вообще не актуально, т.к. фреймворк базируется на классической асинхронной схеме со своими лёгкими потоками.
C>Нет там эффективной работы. Она есть только в Rust.
Кстати, вот как раз для многопоточной работы иммутабельные данные в D и оптимизированы, т.к. обмен ими между потоками происходит без всяких блокировок.
А что касается Rust'а... То он же ещё пока даже близко не является готовым языком программирования. Так, какие-то наброски пока. Ну и кстати из того, что уже есть, он выглядит скорее как замена языку C, а не C++.
C>Ну как обычно — рендериться страничка, отдаётся в буффер, Tomcat его пихает в сокет. Масштабируемость зависит от прикладного кода.
Ага, ага... Только отзывчивость сервера, объём отжираемой памяти и т.п. почему-то очень сильно отличаются. )))
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Угу, в рантайме то вообще всё что угодно можно творить. Но я подобное не считаю нормальным метапрограммированием.
Это именно нормальное метапрограммирование, при том, что есть все остальные виды.
>Оно тормозное и непроверяемое (на стадии компиляции). Т.е. формально говоря это конечно же МП, но на практике лучше уж без него. )))
Вообще то наоборот, оно лучше чем eval, и без него в современном JS вообще ничего не делается.
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Угу, в рантайме то вообще всё что угодно можно творить. Но я подобное не считаю нормальным метапрограммированием. Оно тормозное и непроверяемое (на стадии компиляции). Т.е. формально говоря это конечно же МП, но на практике лучше уж без него. )))
На счет метапрограммирования. Представь, у тебя есть либа, асинхронная, на колбеках.
Задача — сделать вызовы вот такими
var result = start().x().y().z();
Все функции в либе асинхронные, имеют два колбека — success, error, а вот код который я привел выглядит как обычный синхронный.
Джаваскрипт требует смешное количество кода, что бы убрать спагетти из колбеков. Попробуй для сравнения тоже самое в С++ или D.
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Под контекстом я как раз понимаю то, что С++ явно называет и выделяет все конструкции, а D нет. Например в С++ шаблон это template<typename T>, в D это (Т). Для меня, незнаюшего контекста, было трудно понять, что такое (Т), потому что также записываются и вызов функции, и параметры функции. Естественно можно сказать, что проблема взята из ниоткуда, ибо если я знаю контекст, то она сразу же исчезает, но мне не нравится общая тенденция без какой-либо видимой причины использовать контекстно-зависимый синтаксис.
__________________________________
Не ври себе.
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Под контекстом я как раз понимаю то, что С++ явно называет и выделяет все конструкции, а D нет. Например в С++ шаблон это template<typename T>, в D это (Т). Для меня, незнаюшего контекста, было трудно понять, что такое (Т), потому что также записываются и вызов функции, и параметры функции. Естественно можно сказать, что проблема взята из ниоткуда, ибо если я знаю контекст, то она сразу же исчезает, но мне не нравится общая тенденция без какой-либо видимой причины использовать контекстно-зависимый синтаксис.
С++ явно называет и выделяет все конструкции? По-моему, С++ один из самых зависимых от контекста языков (если не самый).
Например, что это?
a(b);
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Например в С++ шаблон это template<typename T>, в D это (Т). Для меня, незнаюшего контекста, было трудно понять, что такое (Т), потому что также записываются и вызов функции, и параметры функции.
Честно говоря, не понимаю где тут проблема. На Д ведь шаблоны обьявляются так:
void foo(T)(T x)
Как это можно с обьявлением простой функции спутать? Тут же два "списка параметров". То есть разница есть. Или речь про то, что подумает человек не знающий синтаксиса? Ну тогда он и в С++, в не меньшей степени, потеряется.
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Именно, вы сами дали ответ — два "списка параметров". Это выглядит как два списка параметров, а не как список параметров для шаблона и список параметров для функции.
Когда я начинаю читать объявление функции, то есть "void f(Color, ... " это выглядит как объявление обычной функции. Пока я не натренирую себя, что это может быть нетак, я могу ошибиться. Я бы предпочёл, чтобы эти два понятия как-то синтаксически отличались.
Всё понятно с самого начала. Но как я уже сказал, даже если этот пример не столь страшен, мне не нравится подобная тенденция упрощать вещи не принимая во внимание возможные разночтения.
__________________________________
Не ври себе.
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Это именно нормальное метапрограммирование, при том, что есть все остальные виды.
Просто метапрограммирование такого уровня есть считай вообще в любом языке, работающем в интерпретаторе...
I>Вообще то наоборот, оно лучше чем eval, и без него в современном JS вообще ничего не делается.
Причём тут eval или нет? Это всё равно всё в рантайме работает и соответственно не может проверяться до запуска и не может иметь нормальную оптимизацию. Да, для скриптов это вполне нормально. Но мы же не про скрипты говорим в этой темке (один из двух пунктов в заголовке — эффективность).
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Ikemefula, Вы писали:
I>На счет метапрограммирования. Представь, у тебя есть либа, асинхронная, на колбеках. I>Задача — сделать вызовы вот такими I>
I>var result = start().x().y().z();
I>
I>Все функции в либе асинхронные, имеют два колбека — success, error, а вот код который я привел выглядит как обычный синхронный. I>Джаваскрипт требует смешное количество кода, что бы убрать спагетти из колбеков. Попробуй для сравнения тоже самое в С++ или D.
Собственно для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами. Правда при этом будет не максимально эффективно по быстродействию (вызовы не будут инлайниться как минимум). С помощью МП можно подобное записать в статике, так что всё заинлайнится. А для более громоздкого кода можно вообще взять сопрограммки какие-нибудь (кстати, в D fiber входят в стандартную библиотеку).
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Под контекстом я как раз понимаю то, что С++ явно называет и выделяет все конструкции, а D нет. Например в С++ шаблон это template<typename T>, в D это (Т). Для меня, незнаюшего контекста, было трудно понять, что такое (Т), потому что также записываются и вызов функции, и параметры функции. Естественно можно сказать, что проблема взята из ниоткуда, ибо если я знаю контекст, то она сразу же исчезает, но мне не нравится общая тенденция без какой-либо видимой причины использовать контекстно-зависимый синтаксис.
Вообще то шаблоны функций/классов в D работают полностью аналогично своему прообразу в C++. Только чуть меньше синтаксического шума (всяких там ключевых слов, скобочек и т.п.) и больше возможностей (одна передача строк в качестве параметра шаблона чего стоит!).
Re[8]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Именно, вы сами дали ответ — два "списка параметров". Это выглядит как два списка параметров, а не как список параметров для шаблона и список параметров для функции.
А это и надо понимать как два списка параметров, в этом и смысл! Один список с параметрами времени компиляции и второй с параметрами времени исполнения. А всё остальное абсолютно равносильно. Возможно кого-то сбивает с толку, что в первом списке параметров можно передавать не только значения, но и скажем типы, но они в D являются вполне себе нормальным видом данных, с которым можно проводить разные операции...
Вообще данный подход D мне кажется намного более логичным и простым. Хотя с точки зрения специалиста по C++ он конечно несколько непривычен, т.к. в C++ параметр шаблона намного меньше похож на полноценный параметр функции (более ограничен).
Re[17]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Все функции в либе асинхронные, имеют два колбека — success, error, а вот код который я привел выглядит как обычный синхронный. I>>Джаваскрипт требует смешное количество кода, что бы убрать спагетти из колбеков. Попробуй для сравнения тоже самое в С++ или D.
_>Собственно для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами. Правда при этом будет не максимально эффективно по быстродействию (вызовы не будут инлайниться как минимум).
Спасибо, капитан. Метапрограммирование в таком случае вообще не требуется, потому что абсолютно все можно написать руками.
>С помощью МП можно подобное записать в статике, так что всё заинлайнится. А для более громоздкого кода можно вообще взять сопрограммки какие-нибудь (кстати, в D fiber входят в стандартную библиотеку).
С помощью МП можно вообще не париться и всё заработает само, даже безо всякой статики и даже без файберов.
Re[17]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Это именно нормальное метапрограммирование, при том, что есть все остальные виды.
_>Просто метапрограммирование такого уровня есть считай вообще в любом языке, работающем в интерпретаторе...
И при этом такое метапрограммирование недоступно в большинстве обычных языков.
I>>Вообще то наоборот, оно лучше чем eval, и без него в современном JS вообще ничего не делается.
_>Причём тут eval или нет? Это всё равно всё в рантайме работает и соответственно не может проверяться до запуска и не может иметь нормальную оптимизацию.
Ты определись, про что речь, про статическую типизацию или про возможности, а то у меня ощущение что статическая типизация это самая главная полезная фича в D.
Re[18]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Ты определись, про что речь, про статическую типизацию или про возможности, а то у меня ощущение что статическая типизация это самая главная полезная фича в D.
Объясняю подробно. На мой взгляд есть два основных вида кодирования (и соответственно языков под них): скриптовой (обычно что-то с динамической типизацией и интерпретатором/jit) и нет (обычно что-то со статической типизацией и оптимизирующим компилятором). Естественно возможно ещё множество других вариантов, но в них обычно гораздо меньше смысла, чем в этих двух, т.к. там преимущества уже в меньшей степени покрывают их цену. Ну и соответственно хороший профессионал должен иметь в своём инструментарии как минимум по одному языку из каждой категории.
Так вот, если мы будем говорить о скриптовых языках, то там с МП обычно всё очень просто. Как минимум есть какая-то разновидность функции eval, а чаще всего (во всех современных языках) есть полноценная интроспекция времени исполнения и возможность динамически менять любые типы данных/куски кода. Конечно у этого есть своя цена, но она обычно не сильно выделяется по эффективности относительно обычного кода на подобных языках.
Если же мы посмотрим на МП во второй категории, то тут уже всё заметно сложнее. Т.к. для подобных языков функция eval или интроспекция времени исполнения абсолютно никчемны (т.е. их можно ввести, но они будут перечёркивать все преимущества языка), то остаётся только МП времени компиляции, которое заметно сложнее в реализации. И если не упоминать такие вырожденные вещи, как внешние кодогенераторы, то собственно подобных языков с эффективным МП будет вообще весьма мало. А конкретно язык D явно будет одним из лидеров среди них.
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Ты определись, про что речь, про статическую типизацию или про возможности, а то у меня ощущение что статическая типизация это самая главная полезная фича в D.
_>Объясняю подробно.
Я скипнул порожнее. Ты ловко перешел от возможностей к типизации. Так держать
Re[8]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Artifact, Вы писали:
A>Именно, вы сами дали ответ — два "списка параметров". Это выглядит как два списка параметров, а не как список параметров для шаблона и список параметров для функции.
Имхо, это всё-таки обычная "проблема" отличающегося синтаксиса. Вы же говорили о наличии контекста. Так вот, в D по одному объявлению шаблонной функции уже видно, что это шаблон. Причём это можно одним взглядом окинуть и сразу понять, что это такое.
Другой вид скобок, наверное, можно было бы использовать, но вряд ли это проблема.
Re[13]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_> том же обсуждаемом фреймворке основные типы данных объявлены как struct, а не как class и соответственно при работе с ними GC обычно не затрагивается.
Вот, кстати, в этом моменте мне больше С++ подход нравится. В смысле, что где размещать объект решает сам программист, а не авторы языка. Так что не приходится делать какие-то особые приседания, чтобы не использовать GC/хип.
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Я скипнул порожнее. Ты ловко перешел от возможностей к типизации. Так держать
Я с удовольствием и МП пообсуждаю (люблю эту тему). А здесь я просто уточнил, МП из каких языков имеет смысл сравнивать при обсуждение возможностей D. Потому как если сравнивать скажем с Питоном, то это будет просто смешно, т.к. речь о вообще ином мире. Хотя формально это всё вроде как МП.
Re[14]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DE>Вот, кстати, в этом моменте мне больше С++ подход нравится. В смысле, что где размещать объект решает сам программист, а не авторы языка. Так что не приходится делать какие-то особые приседания, чтобы не использовать GC/хип.
Да, согласен. Хотя как бы в D всё же не совсем жёстко (можно же спокойно размещать и struct в куче и class на стеке, а жёстко определены только дефолтные размещения) это всё, но скажем если мы привыкли к какому-то одному стилю (например только всё в стеке стараться держать, подразумевая сами объекты, а не скажем внутренние данные контейнеров), то приходится смотреть постоянно класс там или структура, чтобы правильно создать. Это конечно минус на мой вкус.
Re[14]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
_>> том же обсуждаемом фреймворке основные типы данных объявлены как struct, а не как class и соответственно при работе с ними GC обычно не затрагивается. DE>Вот, кстати, в этом моменте мне больше С++ подход нравится. В смысле, что где размещать объект решает сам программист, а не авторы языка. Так что не приходится делать какие-то особые приседания, чтобы не использовать GC/хип.
У структур и классов есть одна принципиальная разница — наличие/отсутствие полиморфизма через виртуальные методы. Если не хотим такого полиморфизма, берем struct и размещаем где хотим (можно ведь через new структуры в куче создавать при желании). Если полиморфизм нужен (а значит, обращаясь к объекту по указателю, мы в общем случае не знаем какой именно там объект), то по-хорошему это автоматически должно означать, что это должен быть reference тип c размещением в куче. Так что разница в дефолтном размещении — лишь естественное следствие разницы в типизации. В С++ такого жесткого разделения нет, там все смешалось в кучу.
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>struct в куче
Это да, тут всё ок.
_>и class на стеке
Может ссылку, где это поподробнее объяснялось бы? Нашел, например такое ("The scope keyword can be used to allocate class objects on the stack"), но это список "Deprecated Features".
Причём, обьяснение, на мой взгляд, совершенно идиотское (или я чего-то не понимаю) — "ссылку на такой обьект можно вернуть из функции, но он ведь разрушится". Почему компилятор не может это отследить мне не понятно. Ещё там говорится, что есть библиотечное решение, но ссылки нет, найти не смог.
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
DM>У структур и классов есть одна принципиальная разница — наличие/отсутствие полиморфизма через виртуальные методы.
Разницу понимаю. Тем не менее, с логикой не согласен.
DM>то по-хорошему это автоматически должно означать, что это должен быть reference тип c размещением в куче. Так что разница в дефолтном размещении — лишь естественное следствие разницы в типизации.
С какой стати? Скажем, ты пишешь либу и (если поведение нельзя легко изменить) накладываешь нежелательные ограничения на клиентский код. Вон alex_public говорит, что в обсуждаемом фреймворке хорошо сделали, что использовали структуры. Складывается впечатление, что они и себя ограничивали и дальнейшее использование. Да, по всей видимости, это хороший компромисс (в рамках языка), но С++ (в этом моменте) оставляет больше свободы.
DM>В С++ такого жесткого разделения нет, там все смешалось в кучу.
Ну нет, не смешалось в кучу, а возможно выбирать самому.
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DM>>то по-хорошему это автоматически должно означать, что это должен быть reference тип c размещением в куче. Так что разница в дефолтном размещении — лишь естественное следствие разницы в типизации. DE>С какой стати? Скажем, ты пишешь либу и (если поведение нельзя легко изменить) накладываешь нежелательные ограничения на клиентский код. Вон alex_public говорит, что в обсуждаемом фреймворке хорошо сделали, что использовали структуры. Складывается впечатление, что они и себя ограничивали и дальнейшее использование. Да, по всей видимости, это хороший компромисс (в рамках языка), но С++ (в этом моменте) оставляет больше свободы.
Свобода выбора никуда не делась. И структуры, и классы в D можно размещать где угодно (см. new и emplace). Но попытка работать с классами как с value-типами чревата рядом неприятностей, т.к. это плохо совместимо с полиморфизмом. Нужно ли этот момент раскрывать подробнее? В итоге D совершенно разумно склоняет программиста полиморфные (в ОО смысле) типы делать reference-типами.
DM>>В С++ такого жесткого разделения нет, там все смешалось в кучу. DE>Ну нет, не смешалось в кучу, а возможно выбирать самому.
В D тоже можно, просто язык подталкивает к менее чреватому ошибками выбору.
Re[15]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Да в курсе я про D. Быстрее он только на детских benchmark'ах. Если нужно что-то серьёзное, с большим количеством памяти и не дай б-г многопоточностью — всё упс. _>Ждём пруфлинк тогда. )
Лень... На shootout были когда-то бенчмарки, но их что-то выпилили.
C>>И что? В реальных программах данные не в стеке лежат. Добавляем сюда ещё отсутствие нормального межпоточного разделения данных и вообще всё уныло. _>Как раз с межпоточным там всё удобно. Причём есть несколько разных возможных уровней работы. Можно работать на самом низком уровне (мьютексы и т.п. как в том же C++), можно на более высоком уровне синхронизации (как в java и т.п.), а можно использовать готовую полноценную систему акторов (как в эрланге).
А чем в Java синхронизация более высокоуровневая, чем в С++-ной?
_>Последнее мне нравится больше всего. И всё это поддерживается соответствующими моделями памяти.
Я не вижу в D какой-то модели памяти, отличной от share-everything.
Ну а асинхронные однопоточные библиотеки — это вообще полное "не шмогла".
C>>Нет там эффективной работы. Она есть только в Rust. _>Кстати, вот как раз для многопоточной работы иммутабельные данные в D и оптимизированы, т.к. обмен ими между потоками происходит без всяких блокировок.
В D для данных общая куча, в любом случае, так как иммутабельность не гарантируется системой типов.
Кроме того, в D отсутствует нормальный механизм снятия иммутабельности в безопасных условиях. Т.е. в типичном сценарии я могу передать граф объектов из одного потока в другой, но в получателе я смогу только читать их (если не использовать небезопасное приведение типов). В Rust с его понятием владения я могу передавать объекты между потоками, так что получатель может их свободно использовать.
Это выглядит как очень маргинальная фича, но на самом деле позволяет делать такие трюки, как гарантированно безопасный параллельный foreach: http://smallcultfollowing.com/babysteps/blog/2013/06/11/data-parallelism-in-rust/
_>А что касается Rust'а... То он же ещё пока даже близко не является готовым языком программирования. Так, какие-то наброски пока. Ну и кстати из того, что уже есть, он выглядит скорее как замена языку C, а не C++.
На Rust уже написан Servo, и развивается Rust в сторону как раз замены С++ для сложных систем. Причём развивается активно.
Sapienti sat!
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DE>Может ссылку, где это поподробнее объяснялось бы? Нашел, например такое ("The scope keyword can be used to allocate class objects on the stack"), но это список "Deprecated Features". DE>Причём, обьяснение, на мой взгляд, совершенно идиотское (или я чего-то не понимаю) — "ссылку на такой обьект можно вернуть из функции, но он ведь разрушится". Почему компилятор не может это отследить мне не понятно. Ещё там говорится, что есть библиотечное решение, но ссылки нет, найти не смог.
Ммм ну я в принципе это и имел в виду. В последнем компиляторе вроде без проблем работает. Хотя я это для теста только проверял, а в реальном коде не приходилось (пока что в используемых библиотеках соотношения class/struct более менее рациональное).
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DE>С какой стати? Скажем, ты пишешь либу и (если поведение нельзя легко изменить) накладываешь нежелательные ограничения на клиентский код. Вон alex_public говорит, что в обсуждаемом фреймворке хорошо сделали, что использовали структуры. Складывается впечатление, что они и себя ограничивали и дальнейшее использование. Да, по всей видимости, это хороший компромисс (в рамках языка), но С++ (в этом моменте) оставляет больше свободы.
Кстати в том фреймворке не всё структуры, а только сущности представляющие данные. Т.е. которые собственно и выделяются/удаляются постоянно. Но там есть и классы, используемые для сущностей типа "сам сервер" и т.п. В данном случае это вполне удобное и продуманно выходит. Однако я боюсь, что где-то в другом месте я столкнусь с кодом, в котором разделение классов/структур будет не соответствовать моему вкусу. И тогда данное дефолтное разделение по памяти действительно станет слегка напрягать.
Re[16]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Лень... На shootout были когда-то бенчмарки, но их что-то выпилили.
Ага, т.е. реальных данных нет... А у меня вот есть, причём не откуда-то там, а проведённые своими руками. И в них D заметно уступает только C++, а ту же жабку опережает очень заметно. Причём это с обычным компилятором (dmd). И это всё именно про быстродействия — про объём отжираемой памяти я вообще молчу (специально не замерял, но смотрел на состояние системы в тех же тестах и жабка там дико отжирала в сравнение с D и C++).
C>А чем в Java синхронизация более высокоуровневая, чем в С++-ной?
Имеется в виду наличие готовых инструментов прямо в языке, а не возможность сделать что-то с помощью внешних библиотек (при таком раскладе и в C++ вообще всё есть). Так вот в D есть возможность синхронизации класса — весьма похоже на вариант в Java и явно более высокуровневый, чем обычные блокировки. Хотя лично мне оно не нравится и я как раз предпочитаю использовать два других базовых способа — низкоуровневые блокировки или же модель акторов.
C>Я не вижу в D какой-то модели памяти, отличной от share-everything.
Советую посмотреть на модификатор share (а главное, что означает его отсутствие). А так же на его взаимодействие с модификатором immutable и как это всё влияет (что разрешено, а что нет) например на передачу данных между потоками с помощью сообщений (та самая модель акторов).
C>Ну а асинхронные однопоточные библиотеки — это вообще полное "не шмогла".
Если мы говорим про высоконагруженные серверные решения, то это весьма забавная мысль... )
C>В D для данных общая куча, в любом случае, так как иммутабельность не гарантируется системой типов.
Что-что? ) Как раз в D есть не только const (как в C++), но и immutable, который полностью всё гарантирует. Естественно можно всё сломать, если постараться специально (так же как в C++ каст к void* позволяет убить любые гарантии), но это уже другой вопрос.
C>Кроме того, в D отсутствует нормальный механизм снятия иммутабельности в безопасных условиях. Т.е. в типичном сценарии я могу передать граф объектов из одного потока в другой, но в получателе я смогу только читать их (если не использовать небезопасное приведение типов). В Rust с его понятием владения я могу передавать объекты между потоками, так что получатель может их свободно использовать.
Если очень хочется, то без проблем можно и такое. ) Только тут иммутабельность уже вообще ни причём (данные то реально не такие). А здесь скорее речь о снятие модификатора share. Так вот поддержка подобных вещей естественно есть, так же как и программирование на основе cas.
C>На Rust уже написан Servo, и развивается Rust в сторону как раз замены С++ для сложных систем. Причём развивается активно.
Ну так на C то написано вообще множество мегасложных систем, но это не делает C лучше. По набору архитектурных возможностей я пока не вижу чтобы Rust добрался хотя бы до C++ (а D является шагом ещё дальше). Rust скорее застрял где-то между C и C++, убрав множественные родовые травмы C, но не получив возможности C++.
Хотя это всё естественно только предварительная оценка — реально же Rust ещё не родился, так что посмотрим, посмотрим...
Re[17]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
DM>Но попытка работать с классами как с value-типами чревата рядом неприятностей, т.к. это плохо совместимо с полиморфизмом. Нужно ли этот момент раскрывать подробнее?
С удовольствием послушал бы подробное объяснение про неприятности.
Единственную проблему вижу в том, что в С++, по умолчанию, всё передаётся по значению. Впрочем, я на какие-то ужасные грабли с этим не натыкался, но теоретически возможна "срезка" по недосмотру. Если бы всё, по умолчанию, передавалось по константной ссылке — было бы проще. Ну и писанины меньше заодно.
Ну и не вижу ничего ужасного в создании объекта класса на стеке и передачи его в функции принимающие интерфейс (базовый класс).
Вообще, мне не очень нравится это разделение на ссылочные типы и типы-значения. Да, это очень много где есть и, вероятно, это просто мои тараканы. Но разве удобно постоянно смотреть, что это за тип?
В С++, на мой взгляд, как раз более логично — если передаёшь по константой ссылке, то обьект останется неизменным. Если по значению — скопируется (и соответственно, тоже не изменится). Для изменений есть ссылки и указатели. В D же недостаточно посмотреть на сигнатуру функции — надо ещё на типы параметров смотреть.
DM>emplace
Да уж, "очень удобно".
Реально не понимаю почему нельзя было "scoped" допилить, чтобы компилятор бил по рукам за передачу ссылки на временный объект куда-то наружу.
DM>В D тоже можно, просто язык подталкивает к менее чреватому ошибками выбору.
Ну про ошибки уже спросил.
Тем не менее, насчёт предотвращения (детских) ошибок — могли бы структуры (они ведь могут быть здоровенными) не передавать по значению.
Кстати, погуглил — пишут, что по константой ссылке нельзя rvalue передавать. Правда что ли? И в каких случаях этот запрет может быть полезен?
Re[17]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Ммм ну я в принципе это и имел в виду. В последнем компиляторе вроде без проблем работает. Хотя я это для теста только проверял, а в реальном коде не приходилось (пока что в используемых библиотеках соотношения class/struct более менее рациональное).
Понятно. Просто привык, что если какую-то фичу обьявляют устаревшей, то предлагают более безопасную/удобную альтернативу (скажем, как произошлo с auto_ptr/shared_ptr в С++), ну и её использование не поощряется.
Re[17]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Лень... На shootout были когда-то бенчмарки, но их что-то выпилили. _>Ага, т.е. реальных данных нет... А у меня вот есть, причём не откуда-то там, а проведённые своими руками. И в них D заметно уступает только C++, а ту же жабку опережает очень заметно.
Ну не может быть он быстрым с консервативным мусоросборщиком. Просто в принципе не может.
_>Причём это с обычным компилятором (dmd). И это всё именно про быстродействия — про объём отжираемой памяти я вообще молчу (специально не замерял, но смотрел на состояние системы в тех же тестах и жабка там дико отжирала в сравнение с D и C++).
Что за тест?
C>>А чем в Java синхронизация более высокоуровневая, чем в С++-ной? _>Имеется в виду наличие готовых инструментов прямо в языке
В Java это просто стандартизованая рекурсивная блокировка в виде synchronized-блоков, и всё. Более высокоуровневой она не является.
C>>Я не вижу в D какой-то модели памяти, отличной от share-everything. _>Советую посмотреть на модификатор share (а главное, что означает его отсутствие). А так же на его взаимодействие с модификатором immutable и как это всё влияет (что разрешено, а что нет) например на передачу данных между потоками с помощью сообщений (та самая модель акторов).
Посмотрел. Не понял в чём суть — оно же используется для глобальных переменных.
C>>Ну а асинхронные однопоточные библиотеки — это вообще полное "не шмогла". _>Если мы говорим про высоконагруженные серверные решения, то это весьма забавная мысль... )
Ну да.
C>>В D для данных общая куча, в любом случае, так как иммутабельность не гарантируется системой типов. _>Что-что? ) Как раз в D есть не только const (как в C++), но и immutable, который полностью всё гарантирует.
Нет. К примеру, нельзя создавать сложные immutable-структуры — банальное дерево со ссылками в узлах на родителя уже не делается. Я поискал и вообще не нашёл иммутабельных контейнеров, в Сети советы типа "создайте мутабельного и закастите".
_>Если очень хочется, то без проблем можно и такое. ) Только тут иммутабельность уже вообще ни причём (данные то реально не такие). А здесь скорее речь о снятие модификатора share. Так вот поддержка подобных вещей естественно есть, так же как и программирование на основе cas.
Каким образом?
Sapienti sat!
Re[18]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Ну не может быть он быстрым с консервативным мусоросборщиком. Просто в принципе не может.
Я же писал уже на эту тему: не стоит сравнивать масштаб использования GC в языке D и в Java. Если мы возьмём скажем нормальный (уровня Boost'a) C++ код и заменим в нём внутренности (и только их — сами контейнеры естественно лежат везде на стеке) всех stl контейнеров на использование GC, то тогда будет что-то весьма близкое к нормальному коду на D. Надо ли пояснять, насколько подобное далеко от языка Java, в котором GC по сути отвечает вообще за всё?
C>Что за тест?
бывало. Хотя это конечно по другой тематике (не серверы, а обработка потоковых данных). А сейчас мы тестируем как раз данный серверный фреймворк и там результаты вообще потрясающие. Но эти данные я ещё никуда не выкладывал.
C>В Java это просто стандартизованая рекурсивная блокировка в виде synchronized-блоков, и всё. Более высокоуровневой она не является.
Ну в D она ещё чуть более продвинутая (там на класс и т.п.), но в любом случае это всё немного другой уровень, чем ручные блокировки. Хотя естественно сводятся к ним — речь исключительно о наличие фичи в самом языке, а не о возможности реализации вообще.
C>Посмотрел. Не понял в чём суть — оно же используется для глобальных переменных.
1. Главное что означает отсутствие shared — данные принадлежат только одному потоку (точнее имеют свою копию в каждом потоке). И это как бы дефолтное, т.е. такими является большинство данных в обычной программе на D.
2. Если мы хотим передавать данные между потоками, то есть несколько разных путей:
— передавать по значению
— передавать ссылки, но на иммутабельное (такие данные естественно не имеют копий по потокам)
— работать с shared данными
Первые два вариант думаю очевидны (хотя уже они покрывают очень значительный набор потребностей), а вот третий уже сложнее. По сути это как раз обычные данные (как в том же C++, общие для всех потоков), но при этом компилятор знает, что с такими данными опасно производить многие операции и просто не позволяет этого. Спокойно можно делать атомарные и synchronized операции, есть гарантии на последовательность исполнения и т.п. И плюс возможен каст из shared данных в обычные — это по сути объявление, что мы сами отвечаем за всё руками (как в C++). И соответственно тут можно уже сделать всё что угодно, в том числе и передачу владения.
C>Нет. К примеру, нельзя создавать сложные immutable-структуры — банальное дерево со ссылками в узлах на родителя уже не делается. Я поискал и вообще не нашёл иммутабельных контейнеров, в Сети советы типа "создайте мутабельного и закастите".
И модификатор immutable и индификатор shared являются транзитивными.
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Я же писал уже на эту тему: не стоит сравнивать масштаб использования GC в языке D и в Java. Если мы возьмём скажем нормальный (уровня Boost'a) C++ код и заменим в нём внутренности (и только их — сами контейнеры естественно лежат везде на стеке) всех stl контейнеров на использование GC, то тогда будет что-то весьма близкое к нормальному коду на D. Надо ли пояснять, насколько подобное далеко от языка Java, в котором GC по сути отвечает вообще за всё?
С чего бы контейнеры будут на стеке?? По факту, единственной оптимизацией в D по сравнению с Java является использование структур. Какие-либо сложные данные через них передавать нельзя — оверхед на копирование всё съедает.
бывало.
Совершенно нерепрезентабельно, тест на скорость обращения к массивам.
C>>В Java это просто стандартизованая рекурсивная блокировка в виде synchronized-блоков, и всё. Более высокоуровневой она не является. _>Ну в D она ещё чуть более продвинутая (там на класс и т.п.), но в любом случае это всё немного другой уровень, чем ручные блокировки. Хотя естественно сводятся к ним — речь исключительно о наличие фичи в самом языке, а не о возможности реализации вообще.
Это всё тот же уровень, вид в профиль. Качественно более высокий уровень — это STM, например. Или сегментированные модели памяти, типа Rust или Erlang.
_>Первые два вариант думаю очевидны (хотя уже они покрывают очень значительный набор потребностей), а вот третий уже сложнее. По сути это как раз обычные данные (как в том же C++, общие для всех потоков), но при этом компилятор знает, что с такими данными опасно производить многие операции и просто не позволяет этого. Спокойно можно делать атомарные и synchronized операции, есть гарантии на последовательность исполнения и т.п. И плюс возможен каст из shared данных в обычные — это по сути объявление, что мы сами отвечаем за всё руками (как в C++). И соответственно тут можно уже сделать всё что угодно, в том числе и передачу владения.
И это всё делает всю эту механику чуть менее, чем бесполезной. В Rust система типов гарантирует сегментированность данных между процессами, что делает возможным приватные мусоросборщики для задач, например. В D это невозможно, так как shared/immutable являются лишь хинтами и легко текут.
Для примера:
import std.stdio;
class Test
{
int a;
};
Test some_global;
void do_something()
{
some_global.a += 1;
}
void main()
{
auto t1 = new Test();
t1.a = 11;
some_global = t1;
do_something();
immutable Test ti = cast(immutable) t1;
writeln(ti.a);
do_something();
writeln(ti.a); //Really immutable, are we?
}
Вывод вполне ожидаемый:
12
13
В Rust такая программа невозможна без мегахаков, помеченных feature-gate'ами. Более того, если в D нет вариантов избежать подобного кода из-за невозможности нормально сразу создать иммутабельный граф объектов, то в Rust всё просто за счёт borrow checker'а — пока я владею уникальной ссылкой на объект, то я его могу безбоязненно мутировать. Соответственно, ненужно и искусственное разделение между структурами и классами.
C>>Нет. К примеру, нельзя создавать сложные immutable-структуры — банальное дерево со ссылками в узлах на родителя уже не делается. Я поискал и вообще не нашёл иммутабельных контейнеров, в Сети советы типа "создайте мутабельного и закастите". _>И модификатор immutable и индификатор shared являются транзитивными.
И как это отвечает на мой вопрос?
Sapienti sat!
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, x-code, Вы писали:
XC>>Отмена обязательного return это следсвие возможности рассматривать любой блок кода как выражение.
_>И? Какие преимущества имеем с этого? )
Например ненужность ужасного оператора ?: .
Обычный — if-else может быть выражением.
Пример:
auto a = if(b) 1 else 2;
auto a = 1 + if(b) 1 else 2;
// А вот здесь обычно ошибаются в приоритетах ;)auto a = 1 + b ? 1 : 2;
Ну и многие другие конструкции также.
_>Кстати, в лямбда-функциях естественно можно и без return. Не пойму даже почему в плюсах так не сделали.
Здравствуйте, alex_public, Вы писали:
I>>Все функции в либе асинхронные, имеют два колбека — success, error, а вот код который я привел выглядит как обычный синхронный.
На самом деле — всё ещё интереснее. В этом коде x(), у(), и z() могут быть синхронными и асинхронными — по вкусу.
То есть я могу написать что-то типа requestStockQuotes().updateChart().alert('Done!') I>>Джаваскрипт требует смешное количество кода, что бы убрать спагетти из колбеков. Попробуй для сравнения тоже самое в С++ или D. _>Собственно для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами.
А можно показать эти "обычные способы" в студию? Ну, то есть чтобы я мог написать аналог на C++, при этом updateChart() — асинхронная, библиотечная; alert() — синхронная, библиотечная, а requestStockQuotes — это асинхронная, самописанная.
Правда при этом будет не максимально эффективно по быстродействию (вызовы не будут инлайниться как минимум).
Какой ещё инлайнинг в асинхронных вызовах?
_>С помощью МП можно подобное записать в статике, так что всё заинлайнится.
Интересно было бы посмотреть. В JS это всё делается путём добавления ссылки на библиотеку.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Ну не может быть он быстрым с консервативным мусоросборщиком. Просто в принципе не может.
Сборщик у него действительно очень медленный, но насилуется он намного меньше. А критичный по скорости код просто сразу пишется без лишних аллокаций и сборок, это не так уж сложно в D.
C>Нет. К примеру, нельзя создавать сложные immutable-структуры — банальное дерево со ссылками в узлах на родителя уже не делается.
Это совершенная неправда, и все дальнейшие твои рассуждения отсюда ложны.
Вот иммутабельное дерево с ссылками на родителя:
immutable class Tree(T) {
T value;
Tree!T left, right, parent;
alias MkT = immutable(Tree!T) delegate(immutable Tree!T);
this(T v, immutable Tree!T prnt, MkT mkLeft, MkT mkRight) {
value = v; parent = prnt;
left = mkLeft(this); right = mkRight(this);
}
this(T v, immutable Tree!T prnt) { this(v, prnt, _ => null, _ => null); }
}
void main(string[] argv)
{
auto t1 = new immutable Tree!int(10, null,
p => new immutable Tree!int(20, p),
p => new immutable Tree!int(30, p));
writeln( t1.left.parent.right.parent.value );
}
(создает дерево с 10 в корне и 20 и 30 в листьях, выводит 10)
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В Rust такая программа невозможна без мегахаков, помеченных feature-gate'ами.
Значит все-таки возможна. Разница лишь в простоте использования мегахаков. Просто считай касты в D такими же мегахаками и не используй их. Например, пиши код в режиме @safe, компилятор будет бить по рукам. Не надо путать возможности системы типов и возможности по ее обходу. Начал обходить систему типов — забудь о ее гарантиях.
Re[21]: Язык D - действительно красота и эффективность в одн
Здравствуйте, D. Mon, Вы писали:
DM>Значит все-таки возможна. Разница лишь в простоте использования мегахаков. Просто считай касты в D такими же мегахаками и не используй их. Например, пиши код в режиме @safe, компилятор будет бить по рукам. Не надо путать возможности системы типов и возможности по ее обходу. Начал обходить систему типов — забудь о ее гарантиях.
Но ведь подавляющее большинство кода в режиме @safe не написано. Т.е. в одном случае (Rust) – тебе нужно сильно нопрячься что бы обойти защиту. В другом случае (D) защита по умолчанию отключена. Не находишь что это не совсем равное сравнение?
Re[18]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DM>>Но попытка работать с классами как с value-типами чревата рядом неприятностей, т.к. это плохо совместимо с полиморфизмом. Нужно ли этот момент раскрывать подробнее? DE>С удовольствием послушал бы подробное объяснение про неприятности. DE>Единственную проблему вижу в том, что в С++, по умолчанию, всё передаётся по значению. Впрочем, я на какие-то ужасные грабли с этим не натыкался, но теоретически возможна "срезка" по недосмотру. Если бы всё, по умолчанию, передавалось по константной ссылке — было бы проще. Ну и писанины меньше заодно.
Слайсинг/срезку действительно часто в этом контексте вспоминают, но есть и еще проще соображения.
Если у нас есть сабтайпинг через наследование и ОО-полиморфизм через виртуальные методы, то допустим у нас есть класс Parent и наследный от него Child с дополнительными полями и оверрайдингом ряда методов. Тогда, раз это подтип, то функция f(Parent a) должна уметь принимать значение типа Child, причем реальный тип аргумента (Parent передается или Child) статически неизвестен. Если мы попробуем передать Child по значению, то либо испортим стек, попытавшись запихать больше байт, чем ожидает функция, либо придется передавать лишь часть объекта (соответствующую полям Parent'a), но поскольку какие-то методы переопределены, они будут думать, что есть все поля Child, а там окажется мусор. В общем, как ни крути, а передавать подобные объекты можно исключительно по ссылке. Они просто не могут быть value-типами. В то же время какие-то value-типы нам все же нужны, ибо нередко нам нужна именно value-семантика, где переданное значение является копией и не зависит от оригинала. Отсюда разделение на reference vs. value типы, отсюда отнесение классов с VMT к первым.
Другой вопрос — почему бы временные объекты не размещать на стеке, продолжая обращаться к ним по ссылкам. В принципе, ничто не мешает. Если компилятор содержит достаточно хороший анализатор, он мог бы делать это автоматически, как это вроде бы делает JVM. Но в D, как я понимаю, такого анализатора нет (и не факт, что язык позволит его сделать), а отдавать на откуп программистам под их ответственность — можно, но лишь продвинутым, поэтому такую возможность сделали менее удобной, лишь для самых настырных.
DE>Тем не менее, насчёт предотвращения (детских) ошибок — могли бы структуры (они ведь могут быть здоровенными) не передавать по значению.
Так можно и не передавать. Пишешь f(ref S x), где S — структура, и все передается по ссылке. Но все-все по ссылке нельзя передавать, ведь value-семантика часто тоже нужна.
DE>Кстати, погуглил — пишут, что по константой ссылке нельзя rvalue передавать. Правда что ли? И в каких случаях этот запрет может быть полезен?
Эту тему давно там педалируют и грозятся исправить, но я как-то не в курсе текущей ситуации.
Re[22]: Язык D - действительно красота и эффективность в одн
Здравствуйте, kaa.python, Вы писали:
KP>Но ведь подавляющее большинство кода в режиме @safe не написано. Т.е. в одном случае (Rust) – тебе нужно сильно нопрячься что бы обойти защиту. В другом случае (D) защита по умолчанию отключена. Не находишь что это не совсем равное сравнение?
Честно говоря, я сам не пробовал форсить @safe, потому не могу сказать, насколько этот вариант юзабельный, и много ли в нем доступно на практике.
Но в целом я согласен, что если определять защищенность не бинарно, а строить градации, то D тяготеет к С/С++ с их рабоче-крестьянской близостью к железу и слабыми гарантиями.
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
DM>Если мы попробуем передать Child по значению, то либо испортим стек, попытавшись запихать больше байт, чем ожидает функция, либо придется передавать лишь часть объекта (соответствующую полям Parent'a), но поскольку какие-то методы переопределены, они будут думать, что есть все поля Child, а там окажется мусор.
Это в каких реалиях? В С++ стек не испортится. Если копирование не запрещено, то будет срезка и да, это почти всегда нежелательно и может приводить к несогласованному состоянию объекта.
DM>почему бы временные объекты не размещать на стеке, продолжая обращаться к ним по ссылкам. В принципе, ничто не мешает. Если компилятор содержит достаточно хороший анализатор, он мог бы делать это автоматически, как это вроде бы делает JVM.
Да можно и без автоматики обойтись. В чём проблема допилить старую возможность (scope)? Ничего сильно анализировать не надо — просто запретить передавать такие объекты за пределы скопа.
DM>Так можно и не передавать. Пишешь f(ref S x), где S — структура, и все передается по ссылке. Но все-все по ссылке нельзя передавать, ведь value-семантика часто тоже нужна.
В курсе. Тут вопрос был слегка в другом (и не только к D относится). Почему нельзя всё-всё передавать по константной ссылке (элементарные типы компилятор мог бы автоматически и по значению передавать, если это эффективнее)? Не было бы срезки, меньше писать (в С++ в куче случаев приходится писать именно "const T &"). Для передачи по ссылке и копирования сделать отдельные ключевые слова.
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DM>>Если мы попробуем передать Child по значению, то либо испортим стек, попытавшись запихать больше байт, чем ожидает функция, либо придется передавать лишь часть объекта (соответствующую полям Parent'a), но поскольку какие-то методы переопределены, они будут думать, что есть все поля Child, а там окажется мусор. DE>Это в каких реалиях? В С++ стек не испортится. Если копирование не запрещено, то будет срезка и да, это почти всегда нежелательно и может приводить к несогласованному состоянию объекта.
Это не в реалиях, а в размышлениях как оно вообще может быть. Либо мы передаем объект целиком, портя стек, либо не целиком (как в С++), но тогда при вызове виртуального метода в нем у него в ряде полей окажется мусор (ибо данные есть только от Parent'a, а методы вызываются от Child'a).
DE>Да можно и без автоматики обойтись. В чём проблема допилить старую возможность (scope)?
Не знаю. Я бы и сам не отказался от такого.
DE>Тут вопрос был слегка в другом (и не только к D относится). Почему нельзя всё-всё передавать по константной ссылке (элементарные типы компилятор мог бы автоматически и по значению передавать, если это эффективнее)? Не было бы срезки, меньше писать (в С++ в куче случаев приходится писать именно "const T &"). Для передачи по ссылке и копирования сделать отдельные ключевые слова.
В некоторых языках примерно так и сделано — данные по умолчанию иммутабельные и передаются по ссылке. В условиях ОО языка передавать все-все по константной ссылке плохо — традиционно объекты мутабельные и передаются, чтобы у них вызывались мутирующие методы. Вот и возникает решение: передавать все объекты классов просто по ссылке, что в D/Java/С# и делается.
Re[21]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
DM>Это не в реалиях, а в размышлениях как оно вообще может быть.
Ну если так, то я всё-таки за вариант "как в С++", но с другим умолчанием. То есть передаём по константной ссылке. Если надо именно модифицировать или требуется именно копия — указываем явно. Вроде, и никаких потенциальных ошибок не возникнет?
Если вдруг "случайно" внутри функции полезли менять объект — компилятор про это скажет. Дальше или понимаем, что ошиблись и не меняем или меняем сигнатуру функции.
В С++ правда так можно передать ссылку и потом сразу разрушить объект, но для D (с его GC) и Раста это не актуально. И опять же компилятор может отслеживать.
DM>В условиях ОО языка передавать все-все по константной ссылке плохо — традиционно объекты мутабельные и передаются, чтобы у них вызывались мутирующие методы. Вот и возникает решение: передавать все объекты классов просто по ссылке, что в D/Java/С# и делается.
Не согласен.
Во первых, не просто "всё-всё", а "всё-всё по умолчанию".
Во вторых, объекты может и мутабельные, но функции (внешние), зачастую, такими быть не обязаны. Если посмотреть на стандартную библиотеку С++, то немало алгоритмов не модифицирующие. У классов тоже немало функций помеченных как const. Ну в джаве/C# сделали ещё "веселее" — там передать "по константной ссылке" нельзя (в джаве есть final, но это вроде, не то). То есть мы даже не можем "пообещать" не изменять обьект внутри функции.
В третьих, в шарпе и джаве многие обьекты и так иммутабельные (строки, BigInt и т.д.). Мне, кстати, больше по душе подход С++/Д, где мы решаем на уровне объекта, а не на уровне класса, будет ли он константным/иммутабельным или нет.
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
C>>Ну не может быть он быстрым с консервативным мусоросборщиком. Просто в принципе не может. DM>Сборщик у него действительно очень медленный, но насилуется он намного меньше. А критичный по скорости код просто сразу пишется без лишних аллокаций и сборок, это не так уж сложно в D.
Насколько меньше? Я вот смотрю тот же vibe.d — структур там минимум. Почти везде классы.
C>>Нет. К примеру, нельзя создавать сложные immutable-структуры — банальное дерево со ссылками в узлах на родителя уже не делается. DM>Это совершенная неправда, и все дальнейшие твои рассуждения отсюда ложны. DM>Вот иммутабельное дерево с ссылками на родителя:
Вах! Я и не думал, что всё так плохо.
Оказывается, можно и с помощью полностью "безопасного" кода на D всё сломать.
import std.stdio;
immutable class Test
{
int a;
alias setter_tp = void function(immutable Test);
this(setter_tp setter)
{
setter(this);
a = 1;
}
};
void doSomeLazyInit(immutable Test t)
{
writeln(t.a); //Тут мы можем объект послать в другой поток, для примера
}
void main()
{
auto a = new immutable Test(&doSomeLazyInit);
writeln(a.a);
}
Если постараться, то я и memory corruption так легко устрою с помощью immutable.
Sapienti sat!
Re[21]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
C>>В Rust такая программа невозможна без мегахаков, помеченных feature-gate'ами. DM>Значит все-таки возможна. Разница лишь в простоте использования мегахаков. Просто считай касты в D такими же мегахаками и не используй их.
В D невозможно писать нетривиальный код без хаков — явных или неявных, типа возможности мутации объектов в конструкторе. В Rust же хаки в большинстве программ просто не нужны.
Sapienti sat!
Re[21]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Я с удовольствием и МП пообсуждаю (люблю эту тему). А здесь я просто уточнил, МП из каких языков имеет смысл сравнивать при обсуждение возможностей D. Потому как если сравнивать скажем с Питоном, то это будет просто смешно, т.к. речь о вообще ином мире. Хотя формально это всё вроде как МП.
Сравнивать можно любой язык с любым — эффект, затраты, возможности и тд.
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>С чего бы контейнеры будут на стеке?? По факту, единственной оптимизацией в D по сравнению с Java является использование структур. Какие-либо сложные данные через них передавать нельзя — оверхед на копирование всё съедает.
А ссылки (константные/обычные) кто-то отменял? )
Ну и оверхед на сами данные в Java не стоит забывать. К примеру в D вся инстроспекция времени компиляции и т.п. Т.е. по этим параметрам D ближе именно к C/C++.
_>>Ну например вот такое http://rsdn.ru/forum/flame.comp/5159524.1
бывало. C>Совершенно нерепрезентабельно, тест на скорость обращения к массивам.
Ну там не только скорость обращения к массивам, но да, действительно тест узкоспециализированный, как и указано в заголовке.
C>И это всё делает всю эту механику чуть менее, чем бесполезной. В Rust система типов гарантирует сегментированность данных между процессами, что делает возможным приватные мусоросборщики для задач, например. В D это невозможно, так как shared/immutable являются лишь хинтами и легко текут.
Ээээ, ну так не надо путать "отсутствие защиты" и "возможность пробить защиту". Это совершенно разные вещи. По умолчанию всё работает надёжно. Плюс для экспертов дана возможность обхода всех защит — типа можете заниматься этой чёрной магией на свой страх и риск. Это подход напрямую из C++, где тоже всё довольно строго, но при этом всегда есть путь обхода. Лично мне такой подход очень даже нравится.
_>>И модификатор immutable и индификатор shared являются транзитивными. C>И как это отвечает на мой вопрос?
D. Mon уже ответил подробнее.
Re[6]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, Sinclair, Вы писали:
S>На самом деле — всё ещё интереснее. В этом коде x(), у(), и z() могут быть синхронными и асинхронными — по вкусу. S>То есть я могу написать что-то типа requestStockQuotes().updateChart().alert('Done!')
Синхронность/асинхронность — это вообще не принципиально, как мы недавно выяснили в соседних темах. Вопрос лишь в построение цепочки. Это можно делать:
— в динамике (через указатели на функции) — элементарно реализуется
— в статике (с помощью МП, в Boost'e полно примеров) — уже чуть сложнее, но эффективнее и надёжнее
— с помощью сопрограмм — цепочки строятся вообще без усилий, но требуется создание некой минимальной инфраструктуры.
S>А можно показать эти "обычные способы" в студию? Ну, то есть чтобы я мог написать аналог на C++, при этом updateChart() — асинхронная, библиотечная; alert() — синхронная, библиотечная, а requestStockQuotes — это асинхронная, самописанная.
Да все серьёзные ООП оконные библиотеки по сути реализуют нечто подобное внутри себя.
S>Какой ещё инлайнинг в асинхронных вызовах?
Какая разница какой там вызов, если все вызываемые функции определены на момент компиляции? Именно за счёт инлайнинга тот же Boost.Spirit настолько летает. А там тоже строится некая цепочка исполнения и обычно посложнее, чем в коде выше. Правда по умолчанию он у нас синхронный, но мы уже видели насколько легко это исправляется. Причём это без переписывания кода. А если поставить цель изначально написать асинхронный Boost.Spirit, то можно такого наворотить... )))
_>>С помощью МП можно подобное записать в статике, так что всё заинлайнится. S>Интересно было бы посмотреть. В JS это всё делается путём добавления ссылки на библиотеку.
Если есть готовая библиотека, то это в любом языке так делается. А про пример см. предыдущий абзац.
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
S>>На самом деле — всё ещё интереснее. В этом коде x(), у(), и z() могут быть синхронными и асинхронными — по вкусу. S>>То есть я могу написать что-то типа requestStockQuotes().updateChart().alert('Done!')
_>Синхронность/асинхронность — это вообще не принципиально, как мы недавно выяснили в соседних темах. Вопрос лишь в построение цепочки. Это можно делать: _>- в динамике (через указатели на функции) — элементарно реализуется
точнее, эмулируется, поскольку нет некоторых нужных механизмов, которые я упоминал.
_>- в статике (с помощью МП, в Boost'e полно примеров) — уже чуть сложнее, но эффективнее и надёжнее
Ткни пальцем, где такое в бусте. Вот есть x(), он асинхронный, сигнатура у него содержит колбек. А надо вызвать так, как будто колбека нет и как будто это синхронный, а у возвращаемого значения, того что мвместо колбека, надо вызвать синхронный y() а него вызвать асинхронный z().
_>- с помощью сопрограмм — цепочки строятся вообще без усилий, но требуется создание некой минимальной инфраструктуры.
С помощью сопрограмм тебе надо как то ухитриться модифицировать поведение функции. Для простоты давай предположим, что доступа к коду асинхронной функции у тебя нет есть только её сигнатура. То есть, тебе надо намолотить кучку кода — взять да переписать.
S>>А можно показать эти "обычные способы" в студию? Ну, то есть чтобы я мог написать аналог на C++, при этом updateChart() — асинхронная, библиотечная; alert() — синхронная, библиотечная, а requestStockQuotes — это асинхронная, самописанная.
_>Да все серьёзные ООП оконные библиотеки по сути реализуют нечто подобное внутри себя.
Точнее ни одна из самых известных этого не делает.
S>>Какой ещё инлайнинг в асинхронных вызовах?
_>Какая разница какой там вызов, если все вызываемые функции определены на момент компиляции? Именно за счёт инлайнинга тот же Boost.Spirit настолько летает. А там тоже строится некая цепочка исполнения и обычно посложнее, чем в коде выше.
Руками-руками-руками-руками.
Неинтересно.
Вобщем нужен код.
В джаваскрипте скажем есть асинхронная функция
function x(succeed, error){ ... }
возвращает в succeed объект, у которого есть function y() {...} который возвращает объект у которого есть асинхронный function z(succeed, error);
все что нужно, это просто вызвать один единственный библиотечный метод:
var result = async().x().y().z();
Этот метод делает лифтинг по всей цепочке и всё работает само.
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, _NN_, Вы писали:
_NN>>Например ненужность ужасного оператора ?: . _NN>>Обычный — if-else может быть выражением.
_>О, кстати, вот этот вот if else в Питоне весьма раздражает после привычки к ?:. Хотя это всё наверное дело вкуса.
В питоне это немного другое.
Там синтаксис слегка непривычен: <then> if <cond> else <other> .
Но это потому как оригинальный if else ничего не возвращает.
Если бы он был изначально выражением, ничего вводить нового бы не пришлось.
Написать такое нельзя:
a = if True:
1
else:
2
И из-за этого можно создавать переменные изнутри, хотя это конечно обход, а не решение.
Здравствуйте, Ikemefula, Вы писали:
I>Ткни пальцем, где такое в бусте. Вот есть x(), он асинхронный, сигнатура у него содержит колбек. А надо вызвать так, как будто колбека нет и как будто это синхронный, а у возвращаемого значения, того что мвместо колбека, надо вызвать синхронный y() а него вызвать асинхронный z().
Речь про организацию цепочек, а не про синхронность/асинхронность — с ней мы вроде как уже давно разобрались. А пример цепочки — ну вот тот же Boost.Spirit. Но не только он. В Boost'е вообще довольно много подобных техник встречается, без какого-то специального выделения этого нюанса. Я уже молчу про банальную реализацию продолжения в классе future (boost.thread), которая напрямую занимается такими вещами.
I>С помощью сопрограмм тебе надо как то ухитриться модифицировать поведение функции. Для простоты давай предположим, что доступа к коду асинхронной функции у тебя нет есть только её сигнатура. То есть, тебе надо намолотить кучку кода — взять да переписать.
Ээээ что? )
>>Какая разница какой там вызов, если все вызываемые функции определены на момент компиляции? Именно за счёт инлайнинга тот же Boost.Spirit настолько летает. А там тоже строится некая цепочка исполнения и обычно посложнее, чем в коде выше. I>Руками-руками-руками-руками. I>Неинтересно.
Ээээ а что у нас в Spirit'е руками? Вроде как задаёшь цепочку простейшим образом, а потом просто запускаешь. Где у нас там руками?
I>Вобщем нужен код. I>... I>Этот метод делает лифтинг по всей цепочке и всё работает само.
И? )
Re[21]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>С чего бы контейнеры будут на стеке?? По факту, единственной оптимизацией в D по сравнению с Java является использование структур. Какие-либо сложные данные через них передавать нельзя — оверхед на копирование всё съедает. _>А ссылки (константные/обычные) кто-то отменял? )
И прямо всё будет в виде ссылок? Не верю. В том же vibe.d оно в виде объектов почти всё. Ну и как обычно — это небезопасно.
_>Ну и оверхед на сами данные в Java не стоит забывать. К примеру в D вся инстроспекция времени компиляции и т.п. Т.е. по этим параметрам D ближе именно к C/C++.
В Java интроспекция нужна, только если хочется.
C>>И это всё делает всю эту механику чуть менее, чем бесполезной. В Rust система типов гарантирует сегментированность данных между процессами, что делает возможным приватные мусоросборщики для задач, например. В D это невозможно, так как shared/immutable являются лишь хинтами и легко текут. _>Ээээ, ну так не надо путать "отсутствие защиты" и "возможность пробить защиту". Это совершенно разные вещи. По умолчанию всё работает надёжно.
По умолчанию C и C++ работают полностью надёжно. Получается, что в D нет совершенно никаких жёстких гарантий.
_>Плюс для экспертов дана возможность обхода всех защит — типа можете заниматься этой чёрной магией на свой страх и риск.
Я уже привёл сценарий, когда всё ломается абсолютно штатными средствами. Наверняка есть и другие подобные.
Sapienti sat!
Re[7]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_NN>>Например ненужность ужасного оператора ?: . _NN>>Обычный — if-else может быть выражением. _>О, кстати, вот этот вот if else в Питоне весьма раздражает после привычки к ?:. Хотя это всё наверное дело вкуса.
А мне как раз очень нравится — и читается естественно: "12 if something else 14". Как дополнительный плюс, границы выражения более понятны.
Sapienti sat!
Re[22]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>И прямо всё будет в виде ссылок? Не верю. В том же vibe.d оно в виде объектов почти всё. Ну и как обычно — это небезопасно.
Ну так в C++ это вполне стандартная практика и как раз вполне безопасно. В D все подобные возможности так же имеются, так что при желание можно сохранить тот же стиль. А можно и другие пробовать...
C>В Java интроспекция нужна, только если хочется.
Эээ ты серьёзно считаешь, что java будет отжирать ровно столько же памяти, сколько C++/D при одинаковом коде?
C>По умолчанию C и C++ работают полностью надёжно. Получается, что в D нет совершенно никаких жёстких гарантий.
В D ровно тот же уровень гарантии (хотя разнообразия побольше), что и в C++.
C>Я уже привёл сценарий, когда всё ломается абсолютно штатными средствами. Наверняка есть и другие подобные.
Я же вроде чётко написал выше, что cast(immutable) — это совсем не штатное средство, а классическая чёрная магия, которую надо применять очень осторожно. Точно так же как и скажем reinterpret_cast в C++.
Re[23]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>И прямо всё будет в виде ссылок? Не верю. В том же vibe.d оно в виде объектов почти всё. Ну и как обычно — это небезопасно. _>Ну так в C++ это вполне стандартная практика и как раз вполне безопасно. В D все подобные возможности так же имеются, так что при желание можно сохранить тот же стиль. А можно и другие пробовать...
В С++ это приводит к тому, что многопоточный код в стиле Erlang'а почти никто не пишет.
C>>В Java интроспекция нужна, только если хочется. _>Эээ ты серьёзно считаешь, что java будет отжирать ровно столько же памяти, сколько C++/D при одинаковом коде?
По сравнению с D — да. При правильных настройках. Обычно в Java предпочитают использовать большой размер кучи сразу, из-за чего кажется, что она сжирает кучу памяти зря.
C>>По умолчанию C и C++ работают полностью надёжно. Получается, что в D нет совершенно никаких жёстких гарантий. _>В D ровно тот же уровень гарантии (хотя разнообразия побольше), что и в C++.
Ну то есть, совершенно никакого.
C>>Я уже привёл сценарий, когда всё ломается абсолютно штатными средствами. Наверняка есть и другие подобные. _>Я же вроде чётко написал выше, что cast(immutable) — это совсем не штатное средство, а классическая чёрная магия, которую надо применять очень осторожно. Точно так же как и скажем reinterpret_cast в C++.
Вот тут пример вообще без кастов: http://rsdn.ru/forum/philosophy/5559913?tree=tree
Здравствуйте, alex_public, Вы писали:
_>Речь про организацию цепочек, а не про синхронность/асинхронность — с ней мы вроде как уже давно разобрались. А пример цепочки — ну вот тот же Boost.Spirit. Но не только он. В Boost'е вообще довольно много подобных техник встречается, без какого-то специального выделения этого нюанса. Я уже молчу про банальную реализацию продолжения в классе future (boost.thread), которая напрямую занимается такими вещами.
ля-ля-ля. Была конкретная задача и снова как дошло дело до решения, у тебя общие слова.
Вещи про которые мы говорим в бусте отсутствуют. Нет там никаких способов превратить апи с одной сигнатурой в другую, смотри сам http://braddock.com/~braddock/future/
I>>С помощью сопрограмм тебе надо как то ухитриться модифицировать поведение функции. Для простоты давай предположим, что доступа к коду асинхронной функции у тебя нет есть только её сигнатура. То есть, тебе надо намолотить кучку кода — взять да переписать.
_>Ээээ что? )
Да-да. Фраза "Ээээ что? )" в прошлые месяцы появлялась именно там, где тебе нечего было сказать Для простоты представим, что у функция такая
а вызвать её надо так, как будто она максимально близко похожа на свой синхронный вариант:
Document getDocument() throws Error;
Ну например
Promise<Document> getDocument();
Валяй, показывай чудеса метапрограммирования — одной строчкой подключил либу и всё палит само. Ручное написание всех сортов врапперов и тд оставь детям. Короче, покажи, наконец "тривиально реализуется обычными способами".
I>>Неинтересно.
_>Ээээ а что у нас в Spirit'е руками? Вроде как задаёшь цепочку простейшим образом, а потом просто запускаешь. Где у нас там руками?
См выше. От тебя нужно показать чудеса метапрограммирования.
I>>Этот метод делает лифтинг по всей цепочке и всё работает само.
_>И? )
Ты утверждал, "для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами"
Похоже, как дошло дело до "обычных способов", так в ход сразу пошли "И? )", "Ээээ что? )", "в бусте всё есть" и тд
Re[23]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Я же вроде чётко написал выше, что cast(immutable) — это совсем не штатное средство, а классическая чёрная магия, которую надо применять очень осторожно. Точно так же как и скажем reinterpret_cast в C++.
Кстати, меня смущает такой момент, что в С++ разные виды кастов и случайно сделать не то, что надо сложнее, чем с одним кастом. На практике в D с этим не возникает проблем?
Re[19]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Синхронность/асинхронность — это вообще не принципиально, как мы недавно выяснили в соседних темах.
О, а можно ссылки на эти темы?
А то я только что наткнулся на .whenAll, .then и прочие примитивы, популярные в JS-фреймворках, и до сих пор под впечатлением.
Чтобы наколбасить хоть что-то подобное на С++ у меня тупо не хватит квалификации.
_>Да все серьёзные ООП оконные библиотеки по сути реализуют нечто подобное внутри себя.
Впервые об этом слышу. Вся "асинхронность" в известных мне "серъёзных ООП оконных библиотеках" сводится к аналогам postThreadMessage.
S>>Какой ещё инлайнинг в асинхронных вызовах? _>Какая разница какой там вызов, если все вызываемые функции определены на момент компиляции?
Эмм... Я, наверное, тупой. Но я совершенно себе не представляю, что и куда можно заинлайнить в случае, когда две "функции" вызываются одновременно. Ну, то есть под капотом там, понятное дело, что-то вроде queueUserWorkItem, а ниже — или пул потоков, или кооперативная многозадачность, или IOCP — по вкусу.
Именно за счёт инлайнинга тот же Boost.Spirit настолько летает. А там тоже строится некая цепочка исполнения и обычно посложнее, чем в коде выше. Правда по умолчанию он у нас синхронный, но мы уже видели насколько легко это исправляется.
А, это вы наверное сейчас про переписывание активного кода в реактивный. Ну, может быть это и можно свернуть в асинхронный код; хотя по моему опыту это ещё немножно сложнее.
_>Если есть готовая библиотека, то это в любом языке так делается. А про пример см. предыдущий абзац.
Ну, то есть нету ничего опять. Только обещания написать "если поставить целью".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, alex_public, Вы писали:
_>>Синхронность/асинхронность — это вообще не принципиально, как мы недавно выяснили в соседних темах. S>О, а можно ссылки на эти темы?
Это та самая тема, которая началась ажно в начале декабря и тянется до сих пор. Он имеет ввиду преобразование энергичного в ленивый код при помощи stackfull короутин. Типа, подменил ты stream, на тот, который унутре будет переключать короутины, так сразу getLine() станет асинхронной и консольное приложение вдруг превратится из жабы в прынца
S>А то я только что наткнулся на .whenAll, .then и прочие примитивы, популярные в JS-фреймворках, и до сих пор под впечатлением. S>Чтобы наколбасить хоть что-то подобное на С++ у меня тупо не хватит квалификации.
js он однопоточный, отсюда простая либа промисов это пару килобайт кода. Но вообще промисы пишет наверное каждый второй
Если интересно такое, то вот, наиболее полная либа https://github.com/petkaantonov/bluebird.git, здесь даже есть реализация навроде async/await для Harmony, через евойный yield
Re[24]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В С++ это приводит к тому, что многопоточный код в стиле Erlang'а почти никто не пишет.
Хм, я очень часто использую разные вариации на тему модели акторов. И кстати даже работа через всякие ссылки/указатели совсем не противоречит этой модели — достаточно установить определённые правила игры. В варианте со встроенной реализацией этой модели (как в Эрланге или в D) эти правила просто ещё и жёстко контролируются компилятором.
C>По сравнению с D — да. При правильных настройках. Обычно в Java предпочитают использовать большой размер кучи сразу, из-за чего кажется, что она сжирает кучу памяти зря.
Что касается D, то они полностью используют выделение памяти в стиле C++ (хотя бы уже потому, что в D полноценно реализована арифметика указателей, со всеми вытекающими последствиями), даже если и используется GC.
C>Вот тут пример вообще без кастов: http://rsdn.ru/forum/philosophy/5559913?tree=tree
Здравствуйте, alex_public, Вы писали:
_>Нет, речь не о преаллокации, а о количестве выделяемой памяти в расчёте на 1 байт реальных данных. У java там всё довольно печально. Вот например помнится были такие https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf измерения...
Что значит памяти на 1 байт? Заголовок объектов в Java — это нынче 16 байт. Если объект большой, то это непринципиально.
У Boehm GC оверхед 8 байт. Чуть меньше, но уже не принципиально.
_>Что касается D, то они полностью используют выделение памяти в стиле C++ (хотя бы уже потому, что в D полноценно реализована арифметика указателей, со всеми вытекающими последствиями), даже если и используется GC.
D без GC никому не нужен.
C>>Причина всё та же — immutable в D сделан топорно. В частности, нет контролируемой возможности его снять. _>Снимать immutable — это вообще выглядит ненормально. Я ещё понимаю снятие shared...
Точнее, наоборот — нет возможности сделать граф объектов и после этого работать с ним как с immutable. В Rust — именно это гениальный штрих.
Sapienti sat!
Re[22]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>ля-ля-ля. Была конкретная задача и снова как дошло дело до решения, у тебя общие слова.
Я могу без проблем накидать велосипед на коленке, решающий ту твою задачку в динамике (указатели на функции и т.п.). Если посидеть дольше (уже лень), то можно накидать подобное и в статике, в стиле boost.spirit'a. Но это всё имеет смысл, только если доказывать что-то действительно необычное (как было например в темке про async или например полноценные монады/лифтинг на C++). А тут мне кажется каждому очевидно, что такие вещи пишутся без проблем. В конце концов колбеки и паттерн стратегия — это одни из самых стандартных приёмов.
I>Вещи про которые мы говорим в бусте отсутствуют. Нет там никаких способов превратить апи с одной сигнатурой в другую, смотри сам I>http://braddock.com/~braddock/future/
I>а вызвать её надо так, как будто она максимально близко похожа на свой синхронный вариант: I>
I>Document getDocument() throws Error;
I>
I>Ну например
I>
I>Promise<Document> getDocument();
I>
I>Валяй, показывай чудеса метапрограммирования — одной строчкой подключил либу и всё палит само. Ручное написание всех сортов врапперов и тд оставь детям. Короче, покажи, наконец "тривиально реализуется обычными способами".
Ты тут путаешь разные вещи. Давай я перечислю все возможные варианты, а ты укажешь что ты конкретно хочешь. Значит имея подобный асинхронный api можно использовать его следующими способами:
1. Собственно асинхронный вызов (обработка результатов происходит в контексте вызывающего). Т.е. код у нас будет вида:
Кстати, замечу, что в том же JS как раз наиболее популярен именно этот вариант.
2. Сделать из асинхронного вызова синхронный. Т.е. код вида:
promise<Document> p;
auto f=p.get_future();
getDocument([&](Document d){
p.set_value(d);
}, [&](int code){
p.set_exception(exception(code));
});//весь код выше можно преобразовать в красивый вариант вида auto f=sync(getDocument);
process(f.get());//в get имеем блокировку
3. Асинхронный вызов с продолжением. Т.е. что-то вроде:
promise<Document> p;
auto f=p.get_future();
getDocument([&](Document d){
p.set_value(d);
}, [&](int code){
p.set_exception(exception(code));
});//опять же можно упрятать весь код выше в функцию
f.then([](future<Document> d){
process(d.get());
return to_string(d.get());
}).then([](future<string> s){
cout<<s.get();
});
Как видно, здесь можно образовывать цепочки исполнения произвольной длины.
4. Асинхронный код, выглядящий как синхронный. Такое уже делается только с помощью сопрограмм и мы подробно разбирали подобный код. Он выглядит (изнутри — понятно, что при нормальном использование мы маскируем все эти вещи в удобные макросы) приблизительно так:
coroutine __c([](){//маскируем под что-то типа ASYNC(...) - выделение блока асинхронного кода
Document doc;
int __error=0;
getDocument([&](Document d){
doc=d;
__c.go();
}, [&](int code){
__error=code;
__c.go();
});
__c.break();
if(__code) throw exception(__code);//маскируем весь кусок досюда под что-то типа Document doc=await_async(getDocument);
process(doc);
});
Кстати, в том же JS я что-то не помню реализации чего-то подобного...
Да, ну и так с реализацией какого из этих 4-ёх вариантов у тебя есть какие-то вопросы?
I>Ты утверждал, "для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами"
Ну да. А что, есть сомнения? )
Re[24]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DE>Кстати, меня смущает такой момент, что в С++ разные виды кастов и случайно сделать не то, что надо сложнее, чем с одним кастом. На практике в D с этим не возникает проблем?
Даже не знаю что сказать, т.к. вообще не помню у нас в коде явных кастов. Кстати, для конвертаций типов в стандартной библиотеке D (std.conv) есть любопытное семейство шаблонных функций to.
Re[20]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Sinclair, Вы писали:
S>О, а можно ссылки на эти темы? S>А то я только что наткнулся на .whenAll, .then и прочие примитивы, популярные в JS-фреймворках, и до сих пор под впечатлением. S>Чтобы наколбасить хоть что-то подобное на С++ у меня тупо не хватит квалификации.
Если говорить про просто классический then, то на это можно взглянуть даже в том же boost.thread.
.
_>>Да все серьёзные ООП оконные библиотеки по сути реализуют нечто подобное внутри себя. S>Впервые об этом слышу. Вся "асинхронность" в известных мне "серъёзных ООП оконных библиотеках" сводится к аналогам postThreadMessage.
Я про другое. Т.к. во всех подобных библиотеках цикл обработки сообщений скрыт внутри неё (не говоря уже о прямых вызовах оконной функции и т.п.), то внешне обработка сообщений с помощью такой библиотеки напоминает именно реакцию на некие асинхронные вызовы.
S>Эмм... Я, наверное, тупой. Но я совершенно себе не представляю, что и куда можно заинлайнить в случае, когда две "функции" вызываются одновременно. Ну, то есть под капотом там, понятное дело, что-то вроде queueUserWorkItem, а ниже — или пул потоков, или кооперативная многозадачность, или IOCP — по вкусу.
Инлайнятся цепочки исполнения, которые следуют за асинхронными вызовами.
S>Ну, то есть нету ничего опять. Только обещания написать "если поставить целью".
А что конкретно надо то? ) Я пока не видел чётких запросов. )
Re[26]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Что значит памяти на 1 байт? Заголовок объектов в Java — это нынче 16 байт. Если объект большой, то это непринципиально.
А как у нас дела с контейнерами (массивами и т.п.) при таком раскладе? )
C>D без GC никому не нужен.
Я бы с удовольствием пользовался таким. Точнее я на самом деле хотел бы перетаскивания самых модных фич (в основном из области метапрограммирование и т.п.) в C++.
C>Точнее, наоборот — нет возможности сделать граф объектов и после этого работать с ним как с immutable. В Rust — именно это гениальный штрих.
А тут вроде уже не так всё страшно. Преобразование в immutable не выглядит особо опасным.
Re[27]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Что значит памяти на 1 байт? Заголовок объектов в Java — это нынче 16 байт. Если объект большой, то это непринципиально. _>А как у нас дела с контейнерами (массивами и т.п.) при таком раскладе? )
В Java используются контейнеры ссылок. Как и в большинстве софта на D.
C>>D без GC никому не нужен. _>Я бы с удовольствием пользовался таким. Точнее я на самом деле хотел бы перетаскивания самых модных фич (в основном из области метапрограммирование и т.п.) в C++.
D без GC может называться только "Rust".
C>>Точнее, наоборот — нет возможности сделать граф объектов и после этого работать с ним как с immutable. В Rust — именно это гениальный штрих. _>А тут вроде уже не так всё страшно. Преобразование в immutable не выглядит особо опасным.
Ну вот я уже тут предложил сделать безопасно дерево со ссылками на родителя на Go. Дырка нашлась сразу же...
Ещё очень важна возможность создания контейнеров объектов. В Rust при желании получаются вполне естественные императивные алгоритмы:
let mut numbers = vec![1, 2];
numbers.push(3);
numbers.push(4);
numbers.pop();
for n in numbers.iter()
{
numbers.pop(); //Ошибка - мутируем список во время итерации по нему
}
numbers.pop(); //Снова всё ОК, не осталось borrowed-ссылок
let numbers_immut = numbers; //Теряем мутирующего владельца
numbers.pop(); //Ошибка
numbers_immut.pop(); //Ошибка
Все ошибки — времени компиляции.
Sapienti sat!
Re[23]: Язык D - действительно красота и эффективность в одном ф
I>>а вызвать её надо так, как будто она максимально близко похожа на свой синхронный вариант: I>>
I>>Document getDocument() throws Error;
I>>
I>>Ну например
I>>
I>>Promise<Document> getDocument();
I>>
I>>Валяй, показывай чудеса метапрограммирования — одной строчкой подключил либу и всё палит само. Ручное написание всех сортов врапперов и тд оставь детям. Короче, покажи, наконец "тривиально реализуется обычными способами".
_>Ты тут путаешь разные вещи. Давай я перечислю все возможные варианты, а ты укажешь что ты конкретно хочешь. Значит имея подобный асинхронный api можно использовать его следующими способами:
Здесь нет путаницы, здесь именно то, что тебе надо сделать — показать чудеса метапрограммирования.
_>1. Собственно асинхронный вызов (обработка результатов происходит в контексте вызывающего). Т.е. код у нас будет вида: _>
_>Кстати, замечу, что в том же JS как раз наиболее популярен именно этот вариант.
Замечу, что твоя задача была избавиться от колбеков, а у тебя они в полный рост. В JS это делается на раз и я уже показал как будет выглядеть.
От тебя требуется вызвать вот так:
auto f = getDocument();
сигнатуры смотри выше
Фейл.
_>2. Сделать из асинхронного вызова синхронный. Т.е. код вида: _>
_>promise<Document> p;
_>auto f=p.get_future();
_>getDocument([&](Document d){
_> p.set_value(d);
_>}, [&](int code){
_> p.set_exception(exception(code));
_>});//весь код выше можно преобразовать в красивый вариант вида auto f=sync(getDocument);
_>process(f.get());//в get имеем блокировку
_>
Нет, надо ровно то что я просил:
auto f = getDocument();
Фейл.
_>3. Асинхронный вызов с продолжением. Т.е. что-то вроде: _>
_>promise<Document> p;
_>auto f=p.get_future();
_>getDocument([&](Document d){
_> p.set_value(d);
_>}, [&](int code){
_> p.set_exception(exception(code));
_>});//опять же можно упрятать весь код выше в функцию
_>f.then([](future<Document> d){
_> process(d.get());
_> return to_string(d.get());
_>}).then([](future<string> s){
_> cout<<s.get();
_>});
_>
_>Как видно, здесь можно образовывать цепочки исполнения произвольной длины.
Ты увлекся похоже. От тебя требовалось избавиться от этих спагетти с помощью метапрограммирования.
В джаваскрипте это легко, а судя по тому, что ты даже не понял о чем речь...
_>4. Асинхронный код, выглядящий как синхронный. Такое уже делается только с помощью сопрограмм и мы подробно разбирали подобный код. Он выглядит (изнутри — понятно, что при нормальном использование мы маскируем все эти вещи в удобные макросы) приблизительно так: _>
_>coroutine __c([](){//маскируем под что-то типа ASYNC(...) - выделение блока асинхронного кода
_>Document doc;
_>int __error=0;
_>getDocument([&](Document d){
_> doc=d;
_> __c.go();
_>}, [&](int code){
_> __error=code;
_> __c.go();
_>});
_>__c.break();
_>if(__code) throw exception(__code);//маскируем весь кусок досюда под что-то типа Document doc=await_async(getDocument);
_>process(doc);
_>});
_>
_>Кстати, в том же JS я что-то не помню реализации чего-то подобного...
Это потому, что код на JS гораздо гибче, и лифтинг в промисы делается при желании сам собой, примерно так — подключил либу и пользуешься.
то есть, цепочка функций с колбеками вида function x(arg1,argN, success, error) {}
вызывается вот так
var result = x1(arg1,arg2).x2(arg3,arg4)...xN(argi, argk);
все промисы, замыкания и прочие вещи, которые ты расписывал в 4х примерах не надо писать, все делается подключением ровно одной либы а дальше всё палит само.
В твоем случае есть только один выход — олдскульная кодогенерация, то есть генерация промежуточного слоя АПИ, который сделает преобразование интерфейса, то есть для каждого метода вида
Document getDocument()
{
return Document.wrap((succeed, error) => {
baseLib.getDocument(succeed, error);
});
}
сам документ это навроде
class Document:Promise<baseLib:Document>{
}
В противном случае ты не сможешь вызывать вот так x().y().z()
Итого — ты привел ажно 4 примера и все мимо. Эпик фейл
_>Да, ну и так с реализацией какого из этих 4-ёх вариантов у тебя есть какие-то вопросы?
С учетом того, что ты не осилил то, чего требовалось ...
I>>Ты утверждал, "для реализации подобного метапрограммирование не требуется. Это тривиально реализуется обычными способами"
_>Ну да. А что, есть сомнения? )
Конечно, и даже сильнее чем раньше.
Re[26]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>>>Причина всё та же — immutable в D сделан топорно. В частности, нет контролируемой возможности его снять. _>>Снимать immutable — это вообще выглядит ненормально. Я ещё понимаю снятие shared... C>Точнее, наоборот — нет возможности сделать граф объектов и после этого работать с ним как с immutable. В Rust — именно это гениальный штрих.
А вот есть такой гениальный штрих в D:
если написать так
То выдается ожидаемая ошибка Error: cannot implicitly convert expression (make()) of type int[] to immutable(int[]).
Но если сделать так
int[] make() pure { return [1,2,3]; }
То все компиляется и работает. Результат чистой функции может быть легально переведен из мутабельного в иммутабельный, т.к. чистота подразумевает, что лишних ссылок на эти данные мы не сделали. Вот и решение не хуже этого вашего Раста.
Re[28]: Язык D - действительно красота и эффективность в одном ф
Rust пока не тянет даже на замену C++, максимум на замену C. Просто по набору возможностей. Хотя их естественно можно нарастить в будущем, если заложен хороший базис. Но на данный момент ситуация именно такая.
C>Ещё очень важна возможность создания контейнеров объектов. В Rust при желании получаются вполне естественные императивные алгоритмы: C>... C>Все ошибки — времени компиляции.
Ну так если не считать запрета на мутацию массива внутри итерации по нему, то всё остальное точно так же работает и на D и на C++.
Re[24]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Итого — ты привел ажно 4 примера и все мимо. Эпик фейл
Во-первых ты похоже не умеешь внимательно читать. Во всех примерах специально показана именно реализация (внутренности), а не внешний интерфейс. Но при этом везде в комментариях указано, как эти внутренности прячутся в удобный интерфейс.
Далее, если ты считаешь, что идеалом является генерация для каждой асинхронной функции некой обёртки, реализующей подобие синхронного кода, то это сомнительное решение. Проще иметь некую одну функцию (естественно шаблонную), которая принимает любые (ну в смысле с интерфейсом success/error) асинхронные функции и производит все необходимые действия. Но даже если остановится на твоей точке зрения, то очевидно что соответствующие синхронные обёртки делаются из тех моих примеров банальным копипастом.
Ну и наконец если сравнивать с JavaScript (кстати, не пойму откуда у наз возникла эта идея, ну да ладно), то я видел в нём реализации моих вариантов 1 и 3. Причём если вариант 2 я просто не видел, но могу изобразить что-то подобное на JS, то как реализовать вариант 4 (это тот самый, который мы давно обсуждали и который есть в C#, тривиально делается в C++ и т.д.) на JS я даже не представляю.
P.S. А вообще я уже что-то потерял нить данной дискуссии — о чём мы вообще спорим сейчас? ) И какое отношение к языку D имеет реализация асинхронности в C++ и JS?
Re[27]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
C>>Точнее, наоборот — нет возможности сделать граф объектов и после этого работать с ним как с immutable. В Rust — именно это гениальный штрих. DM>А вот есть такой гениальный штрих в D:
Не получится, нет borrow-checker'а.
DM>То все компиляется и работает. Результат чистой функции может быть легально переведен из мутабельного в иммутабельный, т.к. чистота подразумевает, что лишних ссылок на эти данные мы не сделали. Вот и решение не хуже этого вашего Раста.
Хуже. Чистые функции не могут делать никакого IO, их нельзя распараллеливать и т.д. Фактически, они используются только в метапрограммировании в D.
Sapienti sat!
Re[29]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>В Java используются контейнеры ссылок. Как и в большинстве софта на D. _>Так это же ещё хуже. Кроме оверхеда на java-заголовок объекта в памяти, получаем расход ещё и на ссылки.
В D оно ровно так же.
_>А вообще я намекал на подобные http://vanillajava.blogspot.ru/2011/07/java-how-much-memory-do-different.html цифры — часть их них ужасает. )
Бредятина. Строка в 1024 элемента будет занимать примерно 2100 байт, например. Никак не 50Кб.
C>>D без GC может называться только "Rust". _>Rust пока не тянет даже на замену C++, максимум на замену C. Просто по набору возможностей. Хотя их естественно можно нарастить в будущем, если заложен хороший базис. Но на данный момент ситуация именно такая.
1) Что не так в Rust с возможностями?
2) Чем чистый С хуже по возможностям C++?
C>>Все ошибки — времени компиляции. _>Ну так если не считать запрета на мутацию массива внутри итерации по нему, то всё остальное точно так же работает и на D и на C++.
Не работает. Я уже примеры даже привёл. В D объекты обязаны сразу создаваться иммутабельными, из-за чего возникает необходимость натянуть презерватив на глобус — создавать их в функциональном стиле в императивном языке.
Sapienti sat!
Re[28]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Не получится, нет borrow-checker'а.
Уже получилось. В смысле, это не тот же самый штрих, что в расте, но все ж способ легально строить иммутабельные структуры из мутабельных. То, что ты продолжаешь называть невозможным несмотря на уже два продемонстрированных способа.
Re[29]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, D. Mon, Вы писали:
C>>Не получится, нет borrow-checker'а. DM>Уже получилось. В смысле, это не тот же самый штрих, что в расте, но все ж способ легально строить иммутабельные структуры из мутабельных. То, что ты продолжаешь называть невозможным несмотря на уже два продемонстрированных способа. Оба способа дырявые. ЧТД.
Sapienti sat!
Re[30]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
_>>Rust пока не тянет даже на замену C++, максимум на замену C. Просто по набору возможностей. Хотя их естественно можно нарастить в будущем, если заложен хороший базис. Но на данный момент ситуация именно такая. C>1) Что не так в Rust с возможностями? C>2) Чем чистый С хуже по возможностям C++?
нет нормальных исключений.
Re[25]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Во-первых ты похоже не умеешь внимательно читать. Во всех примерах специально показана именно реализация (внутренности), а не внешний интерфейс. Но при этом везде в комментариях указано, как эти внутренности прячутся в удобный интерфейс.
Ты не сделал самого главного — надо было показать чем именно будет обеспечен внешний интерфейс. Ты же показал чтото своё, наболевшее.
Из твоих примеров совершенно не ясно, как получить цепочку вида x().y().z()
Объясняю еще раз — что бы вызвать метод y, x() должен вернуть некоторый враппер. Ты нигде не показал даже необходимость этого враппера.
Далее, раз дело в метапрограммировании, ты не показал, как же именно будет генерироваться такой код
_>Далее, если ты считаешь, что идеалом является генерация для каждой асинхронной функции некой обёртки, реализующей подобие синхронного кода, то это сомнительное решение.
Ты сказал про классное метапрограммирование и сказал, что похожий результат в D можно получить обычными средствами. При этом показал пример промисов, но забыл показать, как будет сформирован апи.
На деле оказалось, что метапрограммирование ты понимаешь как копипаст:
"очевидно что соответствующие синхронные обёртки делаются из тех моих примеров банальным копипастом"
А между тем джаваскрипт не требует никакого копипаста.
_>Ну и наконец если сравнивать с JavaScript (кстати, не пойму откуда у наз возникла эта идея, ну да ладно), то я видел в нём реализации моих вариантов 1 и 3.
Ты показал совсем не то что требовалось. Твои примеры даже не функции и ничего не возвращают. А значит и цепочку сорганизовать не выйдет.
_>P.S. А вообще я уже что-то потерял нить данной дискуссии — о чём мы вообще спорим сейчас? ) И какое отношение к языку D имеет реализация асинхронности в C++ и JS?
Ты сказал, что D классное метапрограммирование. И шота пока не ясно, как же сделать мой пример, который в джаваскрипте работает сам собой.
P.S. про копипаст повторяться не нужно.
Re[30]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В D оно ровно так же.
Нет, там совсем другой расклад с массивами. Уже не говоря о возможности расположения любых данных на стеке. И отсутствие лишней рантайм информации.
C>Бредятина. Строка в 1024 элемента будет занимать примерно 2100 байт, например. Никак не 50Кб.
Одной подобной фразы недостаточно для опровержения серьёзной статьи. Я конечно это сам не измерял, но пока поверю скорее им, а не голословным утверждениям на форуме. )
C>1) Что не так в Rust с возможностями?
Банальная бедность на фичи. Их тут намного меньше чем даже в C++. Что уж говорить про D, который богаче C++.
C>2) Чем чистый С хуже по возможностям C++?
Уууу. ) Странно видеть такой вопрос на этом форуме. Я конечно же могу подробно ответить... Но это будет на много много пунктов, причём мне кажется, что большинство из них тут общеизвестны, так что этот вопрос как-то попахивает троллизмом.
C>Не работает. Я уже примеры даже привёл. В D объекты обязаны сразу создаваться иммутабельными, из-за чего возникает необходимость натянуть презерватив на глобус — создавать их в функциональном стиле в императивном языке.
Создание сразу иммутабельных — это всего лишь один вариант из трёх (см раздел Creating Immutable Data http://dlang.org/const3.html). Можно ещё копировать (кстати, у массивов есть уже готовый метод idup для таких дел). Ну и наконец можно сделать каст — это уже только для профи, которые не опасаются работать без страховки компилятора.
Re[26]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Из твоих примеров совершенно не ясно, как получить цепочку вида x().y().z()
Так тебе надо цепочку или функцию вида "promise<Document> GetDocument()"? А то ты вроде как заказывал именно её в описание к тому API. Я потому и спрашиваю, что никак не могу понять что ты собственно хочешь увидеть.
Если же говорить про цепочку, то чем тебе не нравится последовательность из .then().then()?
I>Далее, раз дело в метапрограммировании, ты не показал, как же именно будет генерироваться такой код
Я же говорил уже, что метапрограммирование не является обязательным для такого кода. Оно позволяет всего лишь перевести динамические вызовы (по виртуальным функциям) в статические, которые оптимизатор может заинлайнить и т.п.
I>Ты сказал, что D классное метапрограммирование. И шота пока не ясно, как же сделать мой пример, который в джаваскрипте работает сам собой.
Ну да, в D оно сильнее чем в C++. А уже того, что есть в C++ достаточно для написание того же Sprit'a (который является примером реализации статического похода для подобных цепочек, хотя и не связанных с асинхронностью). Правда в C++ Spirit уже написан, а в D пока нет...
Что касается JS, то интересно, есть ли для него хоть одна нормальная реализация сопрограмм? )
Re[31]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>В D оно ровно так же. _>Нет, там совсем другой расклад с массивами. Уже не говоря о возможности расположения любых данных на стеке. И отсутствие лишней рантайм информации.
В Java по факту делается escape analysis, так что значительная часть объектов располагается на стеке. Автоматически. И это работает.
C>>Бредятина. Строка в 1024 элемента будет занимать примерно 2100 байт, например. Никак не 50Кб. _>Одной подобной фразы недостаточно для опровержения серьёзной статьи. Я конечно это сам не измерял, но пока поверю скорее им, а не голословным утверждениям на форуме. )
Я не очень понял что они измеряли, но точно не память.
C>>1) Что не так в Rust с возможностями? _>Банальная бедность на фичи. Их тут намного меньше чем даже в C++. Что уж говорить про D, который богаче C++.
Каких конкретно фич у него нет?
C>>2) Чем чистый С хуже по возможностям C++? _>Уууу. ) Странно видеть такой вопрос на этом форуме. Я конечно же могу подробно ответить... Но это будет на много много пунктов, причём мне кажется, что большинство из них тут общеизвестны, так что этот вопрос как-то попахивает троллизмом.
Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка.
C>>Не работает. Я уже примеры даже привёл. В D объекты обязаны сразу создаваться иммутабельными, из-за чего возникает необходимость натянуть презерватив на глобус — создавать их в функциональном стиле в императивном языке. _>Создание сразу иммутабельных — это всего лишь один вариант из трёх (см раздел Creating Immutable Data http://dlang.org/const3.html).
Я не очень понял где там два остальных метода.
Sapienti sat!
Re[32]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Каких конкретно фич у него нет?
Генерики уступают по мощности плюсовым шаблонам. Нет исключений и перегрузки функций.
C>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка.
Ну это несерьёзно.
Да и рукопашные "виртуальные функции", например, ужасны.
Re[32]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>>>2) Чем чистый С хуже по возможностям C++? _>>Уууу. ) Странно видеть такой вопрос на этом форуме. Я конечно же могу подробно ответить... Но это будет на много много пунктов, причём мне кажется, что большинство из них тут общеизвестны, так что этот вопрос как-то попахивает троллизмом. C>Я серьёзно. Единственная реальная отсутствующая фича — это исключения.
man longjmp
а вообще, это хороший пример того, как можно по-разному определить наличие какой-то возможности.
The God is real, unless declared integer.
Re[33]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>Каких конкретно фич у него нет? DE>Генерики уступают по мощности плюсовым шаблонам. Нет исключений и перегрузки функций.
С++-ные шаблоны — не нужны. В Rust'е вместо них нормальные генерики и макросы. К примеру, printf! в Rust реализован в виде макроса и проверяет корректность параметров во время компиляции.
Исключения есть — в виде fail! и Any. Они по своему дизайну могут быть отловлены на границе задачи. Кстати говоря, в язык встроена и модель супервизора задач из Erlang'а.
Чистая перегрузка функций — тоже не нужна. Есть её аналог с помощью impl'ов:
C>>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка. DE>Ну это несерьёзно.
Что именно?
DE>Да и рукопашные "виртуальные функции", например, ужасны.
Чем ужасны? Ну кроме жуткого синтаксиса в С для указателей на функции.
Sapienti sat!
Re[33]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, netch80, Вы писали:
C>>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. N>man longjmp
Это не исключения, так как longjmp никак не связан с деструкторами. Понятно, что на его основе можно сделать SJLJ-исключения, но вот уже DWARF-овые не получится в чистом С.
Sapienti sat!
Re[34]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>С++-ные шаблоны — не нужны. В Rust'е вместо них нормальные генерики и макросы. К примеру, printf! в Rust реализован в виде макроса и проверяет корректность параметров во время компиляции.
С таким же успехом, могу заявить, что "кастрированные генерики не годятся как замена нормальным темплейтам". Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять. Нормальные макросы — это отлично, но они темплейтам не замена.
Единственный минус темплейтов — длинные и "сложные" сообщения об ошибках. Зато по возможностям, особенно при написании обобщённого кода, они выигрывают.
C>Исключения есть — в виде fail! и Any. Они по своему дизайну могут быть отловлены на границе задачи. Кстати говоря, в язык встроена и модель супервизора задач из Erlang'а.
Вот именно, что "на границе задачи". То есть при необходимости "просто" обработать исключение нельзя.
Насчёт "Any" — можно ссылку на подробное описание?
C>Чистая перегрузка функций — тоже не нужна.
Это не конструктивно.
C>Есть её аналог с помощью impl'ов:
А можно функции типа min/max так изобразить?
Тут меня ещё смущает, что в С++ нормальные макросы когда-то, возможно, и появятся. Вместе с модулями и т.д. А вот в Раст, к примеру, перегрузку функций вряд ли добавят. Именно потому что кто-то решил, что она "не нужна".
DE>>Ну это несерьёзно. C>Что именно?
Не переносимо.
C>Чем ужасны? Ну кроме жуткого синтаксиса в С для указателей на функции.
По моему, очевидно, что встроенные в язык в 99% случаев удобнее, чем наколеночные реализации. Последние ещё и выглядеть сильно по разному могут, затрудняя чтение кода.
Re[35]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
DE>С таким же успехом, могу заявить, что "кастрированные генерики не годятся как замена нормальным темплейтам".
Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень.
DE>Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять.
А можно его увидеть?
DE>Нормальные макросы — это отлично, но они темплейтам не замена.
Ну читаем. Что мы видим:
1) Пример с факториалом — в Расте делается с помощью макроса. Намного прямее, чем в С++.
2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки.
3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++?
DE>Единственный минус темплейтов — длинные и "сложные" сообщения об ошибках. Зато по возможностям, особенно при написании обобщённого кода, они выигрывают.
Не выигрывают даже близко. И если что, я добавлял свои расширения в Boost.Spirit и Phoenix.
C>>Исключения есть — в виде fail! и Any. Они по своему дизайну могут быть отловлены на границе задачи. Кстати говоря, в язык встроена и модель супервизора задач из Erlang'а. DE>Вот именно, что "на границе задачи". То есть при необходимости "просто" обработать исключение нельзя.
Задачи в Расте — очень легковесные. Ну и если очень хочется, то есть обёртка try!, которая внутри создаёт задачу.
DE>Насчёт "Any" — можно ссылку на подробное описание?
Вот тут: http://static.rust-lang.org/doc/master/std/any/index.html
На практике, просто делается fail!(<что-то-там>), а на принимающей стороне по нему делается match.
C>>Чистая перегрузка функций — тоже не нужна. DE>Это не конструктивно.
Какие плюсы от перегрузки функций?
C>>Есть её аналог с помощью impl'ов: DE>А можно функции типа min/max так изобразить?
Можно.
DE>Тут меня ещё смущает, что в С++ нормальные макросы когда-то, возможно, и появятся. Вместе с модулями и т.д. А вот в Раст, к примеру, перегрузку функций вряд ли добавят. Именно потому что кто-то решил, что она "не нужна".
А зачем она нужна? Ну вот реально, какие use-case'ы?
Rust во многом содран с OCaml'а, где перегрузки тоже не было отродясь. И таки прекрасно всё и без неё работает, во вполне реальных программах.
DE>>>Ну это несерьёзно. C>>Что именно? DE>Не переносимо.
Что непереносимо? GNOME — вон весь написан в таком стиле, и ничего.
C>>Чем ужасны? Ну кроме жуткого синтаксиса в С для указателей на функции. DE>По моему, очевидно, что встроенные в язык в 99% случаев удобнее, чем наколеночные реализации. Последние ещё и выглядеть сильно по разному могут, затрудняя чтение кода.
Линксовый VFS с указателями на функции, например, читается сильно лучше, чем 100500 интерфейсов из одной функции.
Sapienti sat!
Re[32]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В Java по факту делается escape analysis, так что значительная часть объектов располагается на стеке. Автоматически. И это работает.
Это всё равно не сравнимо с прямым указанием. Не говоря уже о лишнем расходе памяти на заголовки.
C>Я не очень понял что они измеряли, но точно не память.
Как раз память, но суммарную. Т.е. в случае массивов объектов там идёт двойной расход (на сам массив и отдельно на объекты). И всё это с лишними заголовками...
Я помнится видел разные выкладки на эту тему. Типа таких http://habrahabr.ru/post/134102/ — для C++'ка это всё конечно же дико выглядит. Ну а D в этом смысле ближе к C++...
C>Каких конкретно фич у него нет?
Я сейчас не готов выдать подробный анализ по Rust'у (в отличие от C/C++/D и т.д), т.к. давно не смотрел его и собственно уже даже забыл подробности. Но я точно помню, что когда первый раз глянул на него, то у меня было абсолютно ясное ощущение, что я вижу "C без ужасов". Точно так же как при взгляде на D возникает ощущение "C++ без ужасов".
C>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка.
Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП. Уже одно это является полным приговором. Но кроме этого есть ещё и отдельные фичи: исключения, пространства имён, строгая типизация. Ну и в дополнение ко всему этому из плюсов доступны как все C библиотеки, так и с++ библиотеки (а там же есть сильнейшие вещи, начиная от стандартной STL и заканчивая Boost'ом), а в обратную сторону совместимости обычно нет.
C>Я не очень понял где там два остальных метода.
Здравствуйте, Cyberax, Вы писали:
C>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень.
Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. Причём именно этот нюанс определил направление развитие современного C++, который уже абсолютно не похож на "C с классами". Правда синтаксис подобного метапрограммирования конечно места ужасен и как раз это во многом исправлено в языке D, сохранив при этом (и даже увеличив) всю мощь шаблонов.
DE>>Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять. C>А можно его увидеть?
Например вот http://www.boost.org/doc/libs/1_55_0/libs/format/doc/format.html. И кроме этого есть ещё варианты.
C>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки.
Вообще то обычно ошибки в шаблонах выводятся как раз в первой же строке сообщения об ошибке. Просто обычно после этого ещё может следовать несколько страниц всякого мусора. )))
Да, и кстати аналог концептов в шаблонах C++ давным давно есть (см. например enable_if), просто т.к. оно не обязательно к использованию, то и далеко не все тратят время на добавление подобного (тем более что на быстродействие или надёжность кода это никак не влияет).
C>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++?
Здравствуйте, alex_public, Вы писали:
C>>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень. _>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования.
Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
DE>>>Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять. C>>А можно его увидеть? _>Например вот http://www.boost.org/doc/libs/1_55_0/libs/format/doc/format.html. И кроме этого есть ещё варианты.
Небезопасен.
cout << format("Hello, are you feeling lucky, punk? %d\n") % "Nope";
cyberax@cybmac:~/some$ rustc test.rs
test.rs:3:38: 3:45 error: failed to find an implementation of trait std::fmt::Signed for &'static str
test.rs:3 println!("Hello, world! {:d}\n", "Hello");
^~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
test.rs:3:5: 3:47 note: expansion site
Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е.
C>>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки. _>Вообще то обычно ошибки в шаблонах выводятся как раз в первой же строке сообщения об ошибке. Просто обычно после этого ещё может следовать несколько страниц всякого мусора. )))
Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода.
_>Да, и кстати аналог концептов в шаблонах C++ давным давно есть (см. например enable_if), просто т.к. оно не обязательно к использованию, то и далеко не все тратят время на добавление подобного (тем более что на быстродействие или надёжность кода это никак не влияет).
Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно.
C>>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++? _>http://www.boost.org/doc/libs/1_55_0/doc/html/xpressive.html
Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения.
cyberax@cybmac:~/some$ time clang++ -O2 -I /opt/local/include/ regtest.cpp
real 0m2.584s
user 0m2.334s
sys 0m0.210s
cyberax@cybmac:~/some$ time ./a.out
real 0m9.922s
user 0m9.873s
sys 0m0.017s
На Расте:
#![feature(phase)]
#[phase(syntax)]
extern crate regex_macros;
extern crate regex;
static tst: &'static str = " 123-451";
fn main() {
let re = regex!(r"\s+\d+--\d+\s*");
for r in range(0,10000000) {
re.is_match(tst);
}
}
cyberax@cybmac:~/some$ time rustc -O test.rs
test.rs:10:9: 10:10 warning: unused variable: `r`, #[warn(unused_variable)] on by default
test.rs:10 for r in range(0,10000000) {
^
real 0m0.118s
user 0m0.071s
sys 0m0.027s
cyberax@cybmac:~/some$ time ./test
real 0m4.459s
user 0m4.436s
sys 0m0.011s
Итак, имеем — регэкспы на Rust работают быстрее С++, при том, что компиляция примерно в 20 раз быстрее. И не нужно учить другой синтаксис.
Sapienti sat!
Re[33]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>В Java по факту делается escape analysis, так что значительная часть объектов располагается на стеке. Автоматически. И это работает. _>Это всё равно не сравнимо с прямым указанием. Не говоря уже о лишнем расходе памяти на заголовки.
Для escape'нутых объектов заголовок становится меньше, там остаётся только hashcode и слово для флагов и монитора.
C>>Я не очень понял что они измеряли, но точно не память. _>Как раз память, но суммарную. Т.е. в случае массивов объектов там идёт двойной расход (на сам массив и отдельно на объекты). И всё это с лишними заголовками...
В D точно так же.
C>>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка. _>Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП.
Вообще-то, там всё есть, кроме нормального метапрограммирования.
C>>Я не очень понял где там два остальных метода. _>1. immutable int[] i=[1, 2, 3]; _>2. int[] m=[1, 2, 3]; immutable int[] i=m.idup; _>3. int[] m=[1, 2, 3]; immutable int[] i= cast(immutable)m; _>Первые два метода очевидно безопасные по построению. А за отсутствие ошибок в 3-ем случае отвечает программист.
Ну то есть, вариантов нет — только небезопасный код. О чём я и говорил.
Sapienti sat!
Re[38]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
C>Небезопасен. C>
C>cout << format("Hello, are you feeling lucky, punk? %d\n") % "Nope";
C>
C>Выносите.
Ну так здесь же подразумевается использовать в виде cout << format("Hello, are you feeling lucky, punk? %1\n") % "Nope"; Оно в таком стиле и работает собственно (выводит всё корректно, в соответствие с типом).
Кстати, в языке D встроенная writef работает аналогично (на шаблонах), только там всё намного удобнее.
C>Для сравнения: C>... C>Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е.
Ну так а если строка форматирования определяется в рантайме (что чаще всего и происходит, если в программу встроена поддержка многих языков)?
C>Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода.
В глубине кода относительно определения шаблона, но не "на пятой странице листинга ошибки".
C>Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно.
Причём тут концепты и printf, если проверка соответствия строки форматирования входным типам происходит в рантайме?
C>Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения.
А что подразумевается под предкомпиляцией тогда? )
C>real 0m9.922s
C>user 0m9.873s
C>sys 0m0.017s
C>real 0m4.459s
C>user 0m4.436s
C>sys 0m0.011s
О, вот это интересно. Любопытно глянуть за генерируемый код, чтобы понять за счёт чего такая разница.
Re[34]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В D точно так же.
Ещё раз повторяю:
1. Единственный оверхед в D относительно C++ может возникать от использования GC (в отличие от Java).
2. При этом использование GC в коде на D не обязательно, хотя и упрощает код для многих случаев.
_>>Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП. C>Вообще-то, там всё есть, кроме нормального метапрограммирования.
В таком смысле всё есть и в ассемблере.
Re[39]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности.
_>Ну так здесь же подразумевается использовать в виде cout << format("Hello, are you feeling lucky, punk? %1\n") % "Nope"; Оно в таком стиле и работает собственно (выводит всё корректно, в соответствие с типом).
Не подразумевается. Так как может быть, например, и "%02d".
Но даже если и так:
cout << format("Hello, are you feeling %2, punk? %1\n") % "Nope";
Упс.
_>Причём это работает даже в древнем стандарте языка. Ну а если мы возьмём современный C++, то там вообще всё просто: http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf
Ну так где безопасный printf?
C>>Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е. _>Ну так а если строка форматирования определяется в рантайме (что чаще всего и происходит, если в программу встроена поддержка многих языков)?
Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой.
C>>Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода. _>В глубине кода относительно определения шаблона, но не "на пятой странице листинга ошибки".
Ну вот как будто я не знаю. Пишу какой-нибудь: "std::vector<thread> blah(thread(...))", и он падает внутри кода вектора из-за того, что у std::thread нет конструктора копирования, а перемещение по каким-то причинам не сработало.
C>>Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно. _>Причём тут концепты и printf, если проверка соответствия строки форматирования входным типам происходит в рантайме?
А в Rust оно может быть в compile-time. Хочу такое же в С++.
C>>Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения. _>А что подразумевается под предкомпиляцией тогда? )
Создание КА.
_>О, вот это интересно. Любопытно глянуть за генерируемый код, чтобы понять за счёт чего такая разница.
Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения. Т.е. оно превращается в:
...
#[allow(unused_variable)]
#[inline]
fn step(&self, groups: &mut Captures, nlist: &mut Threads,
caps: &mut Captures, pc: uint) -> StepState {
match pc {
0u => { },
1u => {
if self.chars.prev.is_some() {
let c = self.chars.prev.unwrap();
let found =
match c {
'\t' ..'\n' => true,
'\x0c' ..'\r' => true,
' ' ..' ' => true,
'\xa0' ..'\xa0' => true,
'\u1680' ..'\u1680' => true,
'\u2000' ..'\u200a' => true,
'\u2028' ..'\u2029' => true,
'\u202f' ..'\u202f' => true,
'\u205f' ..'\u205f' => true,
'\u3000' ..'\u3000' => true,
_ => false
};
if found { self.add(nlist, 2u, caps); }
}
},
2u => { },
3u => {
if self.chars.prev.is_some() {
let c = self.chars.prev.unwrap();
let found =
match c {
'0' ..'9' => true,
'\u0660' ..'\u0669' => true,
'\u06f0' ..'\u06f9' => true,
'\u07c0' ..'\u07c9' => true,
:
...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Cyberax, Вы писали:
C>>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
_>Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать.
Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь.
constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.
Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.
Макросы в Rust/Nemerle/Scala и т.п. имеют всю информацию о типах и могут сгенерировать наиболее оптимальный код.
Ну и читабельность намного выше, т.к. код макросов не более чем вызов API компилятора, что можно сравнить с вызовом функций библиотеки.
Здравствуйте, Cyberax, Вы писали:
C>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень.
Нужны для большей гибкости. В расте ведь необходимо указывать все необходимые "трейты", так? Тут сразу шарп вспоминается, где уже хз сколько времени нет арифметических операций для генериков. В С++ оно же просто работает, если для типа нужные операции определены, независимо от того реализует ли он указанные трейты/"интерфейсы".
C>А можно его увидеть?
Да хотя бы типа такого.
C>1) Пример с факториалом — в Расте делается с помощью макроса. Намного прямее, чем в С++.
Ага, читаем:
They exist in a separate, global namespace.
Exporting macros feels like a hack.
Importing macros feels like a hack.
Насчёт "выглядит как хак" ничего не скажу, то невозможность в неймспейс засунуть — уже нефига не "намного прямее".
C>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки.
Ну дык, я и говорю — проблема только с ошибками. А концепты пытаются осилить — прогресс, вроде, есть. Разумеется, концепты — это удобно и хорошо. Но зачем их делать обязательными?
C>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++?
Возможно, на constexpr что-то и можно нагородить. Но что это доказывает? Я где-то заявлял, что в С++ вычисления на этапе компиляции удобнее/лучше?
C>Ну и если очень хочется, то есть обёртка try!, которая внутри создаёт задачу.
Не знал. Ну тогда эта "претензия" снимается.
C>Вот тут: http://static.rust-lang.org/doc/master/std/any/index.html
Это нашел, но не понял как оно применяется для обработки ошибок.
C>Какие плюсы от перегрузки функций?
Удобство для обобщённого программирования. Например, begin/end в С++ существуют и в виде свободных функций перегруженных отдельно для массивов. Ну и таких примеров не так уж мало.
А недостатки какие?
DE>>А можно функции типа min/max так изобразить? C>Можно.
Правильно я понимаю, что функция будет "членом" одного из объектов? То есть вызываться так: а.min(b)?
C>А зачем она нужна? Ну вот реально, какие use-case'ы?
Понимаешь, так спорить можно долго и неконструктивно. Я буду приводить какие-то примеры, ты — заявлять, что это "не нужно" и можно сделать иначе. Да, можно. Это справедливо для 90% возможностей. Но иногда удобнее их иметь.И если аргументы против "не нужно, потому что я (создатели языка) так решил", то это очень уныло. Тем более, что у любой фичи найдутся противники.
C>Rust во многом содран с OCaml'а, где перегрузки тоже не было отродясь. И таки прекрасно всё и без неё работает, во вполне реальных программах.
Ага, есть куча языков без перегрузки. И без макросов. И без темплейтов/генериков.
C>Что непереносимо? GNOME — вон весь написан в таком стиле, и ничего.
Издеваешься что ли? (Нестандартные) расширения языка — это всегда непереносимо. Да, иногда пофиг.
C>Линксовый VFS с указателями на функции, например, читается сильно лучше, чем 100500 интерфейсов из одной функции.
Ну-ну.
Тогда сишные макросы ничем не уступают растовым. Аргумент одного порядка. Да и откуда взялись "100500 интерфейсов из одной функции"?
Re[38]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
_>>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. C>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял:
#include <iostream>
using namespace std;
template <int m, int n>
struct ack
{
enum {value = ack<m - 1, ack<m, n - 1>::value>::value};
};
template <int n>
struct ack<0, n>
{
enum {value = n + 1};
};
template <int m>
struct ack<m, 0>
{
enum {value = ack<m - 1, 1>::value};
};
int main()
{
constexpr int x = ack<3, 6>::value;
cout << x << endl;
}
def ack(m, n):
if m == 0:
return n + 1
if(m > 0 and n == 0):
return ack(m - 1, 1)
if(m > 0 and n > 0):
return ack(m - 1, ack(m, n - 1))
assert(0)
print ack(3, 6)
$time g++-4.8 -pedantic -Os -std=c++0x ack_template_cpp.cpp -o ack_template_cpp
real 0m0.199s
user 0m0.176s
sys 0m0.023s
$time clang++ -std=c++1y -pthread ack_template_cpp.cpp -o ack_template_cpp
real 0m0.195s
user 0m0.162s
sys 0m0.032s
$
$
$time python -u "ack_py.py"
509
real 0m0.045s
user 0m0.036s
sys 0m0.011s
Всего около пяти раз разница.
Да и по рекурсии что питон что компиляторы с++ вылетают на ack(4, 1) с переполнением стека,
хотя для gcc это лечится ключами компилятора.
Re[37]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень. DE>Нужны для большей гибкости.
Если мне хотелось бы изгибаться — я бы взял динамический язык.
DE>В расте ведь необходимо указывать все необходимые "трейты", так? Тут сразу шарп вспоминается, где уже хз сколько времени нет арифметических операций для генериков. В С++ оно же просто работает, если для типа нужные операции определены, независимо от того реализует ли он указанные трейты/"интерфейсы".
В Расте есть перегрузка операторов. А явное указание трейтов позволяет, например, разделять публичный интерфейс и реализацию. Так что не нужно включать в каждый файл пару миллионов строк Буста.
В результате, код на Rust'е строится что-то в 20 раз быстрее С++-ного.
C>>А можно его увидеть? DE>Да хотя бы типа такого.
Это игрушка, где настоящее-то? С поддержкой полной форматной строки. В теории оно возможно, но что-то мне подсказывает, что компиляторы это пока ниасиливают.
DE>Насчёт "выглядит как хак" ничего не скажу, то невозможность в неймспейс засунуть — уже нефига не "намного прямее".
Уже можно. Хотя не очень понятно зачем. Ну и макросы действуют только в пределах файла при явном их импорте, так что не стоит преувеличивать их глобальность.
DE>Ну дык, я и говорю — проблема только с ошибками. А концепты пытаются осилить — прогресс, вроде, есть. Разумеется, концепты — это удобно и хорошо. Но зачем их делать обязательными?
А какие реальные плюсы от их необязательности?
C>>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++? DE>Возможно, на constexpr что-то и можно нагородить. Но что это доказывает? Я где-то заявлял, что в С++ вычисления на этапе компиляции удобнее/лучше?
Нет, высказвалось мнение, что шаблоны С++ лучше за счёт того, что делают вычисления во времени компиляции. В С++ это единственный метод.
C>>Вот тут: http://static.rust-lang.org/doc/master/std/any/index.html DE>Это нашел, но не понял как оно применяется для обработки ошибок.
Можно по нему делать PM и практически повторить стандартный механизм исключений. На практике, опять же, практически никогда не нужен.
C>>Какие плюсы от перегрузки функций? DE>Удобство для обобщённого программирования. Например, begin/end в С++ существуют и в виде свободных функций перегруженных отдельно для массивов. Ну и таких примеров не так уж мало.
Но и не особо много.
DE>А недостатки какие?
Возможная неоднозначность и изменение поведения. Т.е.:
//int frob(int a);int frob(float a);
int frob(double a);
int res = frob(11);
Какая функция вызовется? А если раскомментировать первую (в одном из включаемых файлов)?
Rust стараются делать так, чтобы поведение существующего кода не менялось при добавлении нового.
DE>>>А можно функции типа min/max так изобразить? C>>Можно. DE>Правильно я понимаю, что функция будет "членом" одного из объектов? То есть вызываться так: а.min(b)?
Необязательно. Первый параметр в Rust может указываться вручную, как и в Питоне. Так что этот вызов будет аналогичен: Ord::min(a, b). Если нужна конкретная спецификация, то можно так: f64::min(11, 12).
C>>А зачем она нужна? Ну вот реально, какие use-case'ы? DE>Понимаешь, так спорить можно долго и неконструктивно. Я буду приводить какие-то примеры, ты — заявлять, что это "не нужно" и можно сделать иначе. Да, можно. Это справедливо для 90% возможностей.
Именно так. И потому 90% возможностей С++ стоит выкинуть нафиг, оставив только то, что реально нужно.
DE>Но иногда удобнее их иметь.И если аргументы против "не нужно, потому что я (создатели языка) так решил", то это очень уныло. Тем более, что у любой фичи найдутся противники.
С каждой фичей матрица их взаимодействий растёт квадратично. В результате, сейчас С++ полностью не может знать никто.
C>>Rust во многом содран с OCaml'а, где перегрузки тоже не было отродясь. И таки прекрасно всё и без неё работает, во вполне реальных программах. DE>Ага, есть куча языков без перегрузки. И без макросов. И без темплейтов/генериков.
И тех, которые могут заменить С++? Таких не знаю.
C>>Что непереносимо? GNOME — вон весь написан в таком стиле, и ничего. DE>Издеваешься что ли? (Нестандартные) расширения языка — это всегда непереносимо. Да, иногда пофиг.
То есть? GNOME написан на стандартном чистом C. Там объектная модель сделана полностью на ручных vtbl.
C>>Линксовый VFS с указателями на функции, например, читается сильно лучше, чем 100500 интерфейсов из одной функции. DE>Ну-ну.
Что "ну-ну"? ООП на чистом С делается без проблем — это совершенно неоспоримый факт.
Sapienti sat!
Re[39]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Cyberax, Вы писали:
_>>>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. C>>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
FR>Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял:
Аккерман — это немного нечестно. Он уходит в стороны, а не вглубь.
#include <iostream>
using namespace std;
template <int m>
struct ack
{
enum {value = ack<m-1>::value+m};
};
template <>
struct ack<0>
{
enum {value = 0};
};
int main()
{
constexpr int x = ack<256>::value;
cout << x << endl;
}
Так оно отваливается на 258 штуках. Что уже сильно лучше, чем 32 уровня несколько лет назад, но уровень ZX-Spectrum'а всё ещё не достигнут.
По времени да, стало лучше.
cyberax@cybmac:~/some$ time clang++ -std=c++1y -pthread test2.cpp
real 0m0.407s
user 0m0.372s
sys 0m0.031s
cyberax@cybmac:~/some$ cat test.py
num = 0
for i in range(0, 256):
num += i
cyberax@cybmac:~/some$ time python test.py
real 0m0.025s
user 0m0.013s
sys 0m0.010s
Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск.
Sapienti sat!
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
FR>>Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял: C>Аккерман — это немного нечестно. Он уходит в стороны, а не вглубь.
Ну почему вполне нормально, скорость мерить.
....
C>Так оно отваливается на 258 штуках. Что уже сильно лучше, чем 32 уровня несколько лет назад, но уровень ZX-Spectrum'а всё ещё не достигнут.
gcc 4.8 на >900 отваливается и есть ключик -fconstexpr-depth можно хоть миллион задать.
Для шланга наверно тоже есть ключик.
C>По времени да, стало лучше. C>
C>cyberax@cybmac:~/some$ time clang++ -std=c++1y -pthread test2.cpp
C>real 0m0.407s
C>user 0m0.372s
C>sys 0m0.031s
C>cyberax@cybmac:~/some$ cat test.py
C>num = 0
C>for i in range(0, 256):
C> num += i
C>cyberax@cybmac:~/some$ time python test.py
C>real 0m0.025s
C>user 0m0.013s
C>sys 0m0.010s
C>
C>Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск.
Ну тоже чуть мухлюешь , итеративный конечно шустрее будет, надо на D попробовать, там и итеративный
можно сделать.
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
C>>Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск. FR>Ну тоже чуть мухлюешь , итеративный конечно шустрее будет, надо на D попробовать, там и итеративный FR>можно сделать.
А без разницы, рекурсивный столько же ровно работает:
cyberax@cybmac:~/some$ cat test.py
def summer(num):
if num == 0:
return 0
return num+summer(num-1)
summer(256)
cyberax@cybmac:~/some$ time python test.py
real 0m0.025s
user 0m0.013s
sys 0m0.010s
Sapienti sat!
Re[42]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности.
Ну я с этим собственно и не спорил, хотя бы уже потому, что не претендую на какие-то знания макросов Rust'a. Более того, если это действительно так, то для меня это является очень существенным аргументом в пользу использования этого языка. Естественно если и остальные возможности языка не подведут (на фоне C++/D).
_>>Причём это работает даже в древнем стандарте языка. Ну а если мы возьмём современный C++, то там вообще всё просто: http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf C>Ну так где безопасный printf?
Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
C>Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой.
Не очень понятно как это сделать, ведь gettext будет возращать обычную строку, а не что-то вроде constexpr.
C>А в Rust оно может быть в compile-time. Хочу такое же в С++.
Теоретически возможно и на C++, но практике это будет очень извращённо в связи с кривизной работы со строками во время компиляции. Соответственно на D это без проблем.
C>Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения.
Аааа, понял как это на Rust'е сделано. Если подобное может препроцессор, то понятно почему такая разница в быстродействие. Интересные в Rust'е макросы конечно...
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, _NN_, Вы писали:
_NN>В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать. _NN>Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь. _NN>constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.
Я бы сказал что дело далеко не только в интроспекции, хотя она действительно нужна (времени компиляции естественно). На мой взгляд одно из самых убийственных, это отсутствие возможности нормально работать с различными типа данных (и главное строками!) во время компиляции. Плюс ещё замечательная функция mixin в D, которая замешиваясь на различные другие нюансы язык (типа устройства перегрузки операторов через строковый параметр шаблона) позволяет творить чудеса... В общем даже если и дадут интроспекцию в C++, то до D всё равно будет ещё очень далеко.
_NN>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.
_NN>Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.
Не спорю. ) Вопрос в том какие альтернативы у нас есть...
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
Это не то настоящий суровый printf должен практически все ошибки отлавливать во время компиляции, например как в OCaml:
open Printf
let _ = printf "%d" "compile time fail"
File "printf_tst.ml", line 3, characters 20-39:
Error: This expression has type string but an expression was expected of type
int
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности. _>Ну я с этим собственно и не спорил, хотя бы уже потому, что не претендую на какие-то знания макросов Rust'a.
Ну вот как раз кто-то спорил
C>>Ну так где безопасный printf? _>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
Там описано, что так сделать можно, но конкретного кода нет. Я в целом вполне верю, что это возможно, но вот на constexpr и шаблонах сделать полный разбор строки printf — совсем нетривиально.
C>>Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой. _>Не очень понятно как это сделать, ведь gettext будет возращать обычную строку, а не что-то вроде constexpr.
Будет специальная функция, назовём её "T" с такой сигнатурой: "fn T(initial: str) -> &'static str". Т.е. в программе будет что-то типа: "println!(T("Hello, world"), ...)". Макрос println! будет знать про то, что T будет возвращать исходную строку и для проверки валидности форматной строки просто возьмёт её аргумент. Ну а во время исполнения оно будет работать всё как обычно.
Ещё, вместо hard-coded имени T можно сделать специальную аннотацию на функцию.
C>>Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения. _>Аааа, понял как это на Rust'е сделано. Если подобное может препроцессор, то понятно почему такая разница в быстродействие. Интересные в Rust'е макросы конечно...
Я его ускорил ещё на 20%, кстати. Там внутри всегда считается, что для regexp'а нужно будет получать результирующие capture groups, из-за чего делаются ненужные динамические аллокации, я их просто убрал для простого is_match. Ещё можно вместо новых строк возвращать slice'ы. Да и в целом код регэкспов в Rust пока не очень оптимизировали.
Sapienti sat!
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_NN>>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
_>А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.
Все надеемся и ждем.
Правда боюсь представить что там будет
_>Не спорю. ) Вопрос в том какие альтернативы у нас есть...
Тут уже прозвучали известные альтернативы, мне кажется только Template Haskell еще не звучал
Здравствуйте, Cyberax, Вы писали:
C>Если мне хотелось бы изгибаться — я бы взял динамический язык.
Ну тогда макросы Раста слишком гибки — немедленно выпиливаем их, ведь есть динамические языки.
C>В Расте есть перегрузка операторов. А явное указание трейтов позволяет, например, разделять публичный интерфейс и реализацию.
Не понял. Можно мысль развернуть?
C>Так что не нужно включать в каждый файл пару миллионов строк Буста. C>В результате, код на Rust'е строится что-то в 20 раз быстрее С++-ного.
Буст тут вообще к чему? И зачем его в каждый файл включать?
А для ускорения помогает модульность, а не "указание трейтов".
C>Это игрушка, где настоящее-то? С поддержкой полной форматной строки. В теории оно возможно, но что-то мне подсказывает, что компиляторы это пока ниасиливают.
Нашел несколько реализаций. Признаюсь, глубоко не копал. В стандарте нет, да. Но что значит "компиляторы не осиливают"?
Они (некоторые, по крайней мере) даже стандартный принтф проверять осилили.
C>Уже можно. Хотя не очень понятно зачем. Ну и макросы действуют только в пределах файла при явном их импорте, так что не стоит преувеличивать их глобальность.
Понятно зачем. Чтобы это был нормальный языковый инструмент, а не как в С, где макросам префикс либы лепят.
C>А какие реальные плюсы от их необязательности?
По моему, мы ходим по кругу. Ну не "наследует"/реализует тип нужный трейт, но нужные операции там имеются. Всё могло бы работать, но не в расте. Только не надо рассказывать, что одноимённые функции/операторы могут делать совсем разные вещи в разный трейтах. Могут, но это бывает ещё реже, а уж чтобы создавало проблемы с темплейтами так вообще редкость.
C>Нет, высказвалось мнение, что шаблоны С++ лучше за счёт того, что делают вычисления во времени компиляции. В С++ это единственный метод.
Во первых, не единственный (constexpr ещё).
Во вторых, мнение высказывал не я.
В третьих, не собираюсь отрицать, что сложные вычисления выглядят страшно и нормальные макросы лучше. Но шаблоны не только для этого.
C>Можно по нему делать PM и практически повторить стандартный механизм исключений. На практике, опять же, практически никогда не нужен.
В смысле пусть функция возвращает Ани а там будет или результат или "исключение"? Ну это коряво и не слишком естественно.
"Стандартные" Option/Result куда лучше в этом плане.
C>Но и не особо много.
Но есть.
C>Возможная неоднозначность и изменение поведения. Т.е.: C>
C>Какая функция вызовется? А если раскомментировать первую (в одном из включаемых файлов)?
В первом случае, я бы предпочёл неоднозначность и ошибку на этапе компиляции. В С++ так и происходит.
Если раскомментировать, то понятно что вызовется. И почему это удивительно? В конце концов, в коде типа такого тоже совершенно непонятно, что будет делать вызов (мало ли кто и что там переопределил!):
void test(some_interface *i)
{
i->do_work();
}
И точно так же новый код может "поломать" старый.
C>Необязательно. Первый параметр в Rust может указываться вручную, как и в Питоне. Так что этот вызов будет аналогичен: Ord::min(a, b). Если нужна конкретная спецификация, то можно так: f64::min(11, 12).
С питоном слабо знаком, можно чуть подробнее? "Ord" тут имя класса или неймспейс? И чем второй вызов отличается?
C>Именно так. И потому 90% возможностей С++ стоит выкинуть нафиг, оставив только то, что реально нужно.
Это только твоё мнение. Из Pаста тоже многое можно повыкидывать и без ущерба к надёжности. Если фантазировать, то из С++ было бы отлично повыкидывать всякие кривости имеющиеся из-за обратной совместимости. А вот возможности (модули, нормальные макросы, рефлексию и т.д.) наоборот добавить неплохо было бы.
Да и если на другие языки посмотреть — они тоже развиваются и увеличивают количество фич. Тот же С# скоро по "сложности" догонит С++ (если уже не обогнал).
C>С каждой фичей матрица их взаимодействий растёт квадратично. В результате, сейчас С++ полностью не может знать никто.
Ложное утверждение. Во первых, не все фичи взаимодействуют. Во вторых, в Расте фич гораздо больше, чем в С. Тем не менее язык получается "надёжнее" и удобнее.
C>И тех, которые могут заменить С++? Таких не знаю.
Не прикидывайся, что не понял. (Практически?) любую фичу можно выкинуть и язык всё равно может быть успешным.
C>То есть? GNOME написан на стандартном чистом C. Там объектная модель сделана полностью на ручных vtbl.
Изначально ты говорил про расширения языка. Они — непереносимы.
"Рукопашные реализации" без расширений переносимы, но имеют другие недостатки.
C>Что "ну-ну"? ООП на чистом С делается без проблем — это совершенно неоспоримый факт.
За указателями можно самому следить и "килер-фича" раста "не нужна" — неоспоримый факт такого же уровня.
Хватит передёргивать и выдирать из контекста. Давай ещё раз — хочешь спорить с тем, что встроенные в язык решения не лучше/удобнее/проще непонятных реализаций? Особенно если в языке отсутствуют инструменты упрощающие такие вещи (типа макросов).
Re[39]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>В Расте есть перегрузка операторов. А явное указание трейтов позволяет, например, разделять публичный интерфейс и реализацию. DE>Не понял. Можно мысль развернуть?
В С++ компилятор _обязан_ иметь полное тело шаблона при каждом его инстанцировании. Так как ошибка может возникнуть в любом месте шаблона, если у его параметра не окажется нужного метода.
В Rust каждый generic может компилироваться отдельно — всё что нужно сделать компилятору, это просто подставить адреса реальных функций, реализующих trait'ы. В этом Rust похож на C#, где то же самое делается на уровне байт-кода.
C>>Так что не нужно включать в каждый файл пару миллионов строк Буста. C>>В результате, код на Rust'е строится что-то в 20 раз быстрее С++-ного. DE>Буст тут вообще к чему? И зачем его в каждый файл включать?
Ну вот подключил ты тот же самый Boost.Xpressive — и сразу же затянулось примерно 100000 строк include'ов. В Rust'е у меня подтянется только внешний модуль из пакета regex (300 строк, не считая пустых и комментариев).
DE>А для ускорения помогает модульность, а не "указание трейтов".
Каким образом модульность будет помогать с шаблонами С++? Эксперимент с "extern template" показал, что сильно шаблоны ускорить таким образом нельзя.
DE>Нашел несколько реализаций. Признаюсь, глубоко не копал. В стандарте нет, да. Но что значит "компиляторы не осиливают"? DE>Они (некоторые, по крайней мере) даже стандартный принтф проверять осилили.
Стандартный printf проверяется в качестве специального случая, в виде магии компилятора. А вот полный разбор форматной строки и проверка совпадения типов параметров — пока нигде не делается.
C>>Уже можно. Хотя не очень понятно зачем. Ну и макросы действуют только в пределах файла при явном их импорте, так что не стоит преувеличивать их глобальность. DE>Понятно зачем. Чтобы это был нормальный языковый инструмент, а не как в С, где макросам префикс либы лепят.
В С макросы часто попадают во внешний интерфейс, т.е. если я объявлю макрос min, использую его в .h-файле (пользуясь случаем, хочу передать привет windows.h), то все пользователи .h-файла будут материться. В Rust это исключено — макрос будет действовать на уровне единицы трансляции.
Возможно столкновение имён макросов, но на практике маловероятно. Нет фундаментальных причин, запрещающих делать namespace для макросов, просто оно пока разработчикам не нужно.
C>>Можно по нему делать PM и практически повторить стандартный механизм исключений. На практике, опять же, практически никогда не нужен. DE>В смысле пусть функция возвращает Ани а там будет или результат или "исключение"? Ну это коряво и не слишком естественно.
Нет, можно ловить fail по Any.
C>>Какая функция вызовется? А если раскомментировать первую (в одном из включаемых файлов)? DE>В первом случае, я бы предпочёл неоднозначность и ошибку на этапе компиляции. В С++ так и происходит.
Не всегда происходит. В случае с double/float — да. А вот в случае с раскомментированием int — нет.
DE>Если раскомментировать, то понятно что вызовется. И почему это удивительно? В конце концов, в коде типа такого тоже совершенно непонятно, что будет делать вызов (мало ли кто и что там переопределил!) DE>И точно так же новый код может "поломать" старый.
Нет. В случае с виртуальной функцией код поломается, если изменится именно реализация виртуальной функции. Это нормально. В случае с добавлением реализации frob() сломается совершенно посторонний код.
Далее, в Rust серьёзно относятся к модульной компиляции. Предположим, что у нас есть модуль clink. Он использует модуль bling, внутри которого определена функция "frob(double)". Послезавтра в модуль bling добавили "frob(int)" — нужно ли в этом случае перекомпилировать clink? Если нужно, то как это обнаружить? А что если этот модуль binary-only?
C>>Необязательно. Первый параметр в Rust может указываться вручную, как и в Питоне. Так что этот вызов будет аналогичен: Ord::min(a, b). Если нужна конкретная спецификация, то можно так: f64::min(11, 12). DE>С питоном слабо знаком, можно чуть подробнее? "Ord" тут имя класса или неймспейс? И чем второй вызов отличается?
Ord — это имя трейта ('Ordered'). Второй вариант — это вызов непосредственной реализации.
C>>Именно так. И потому 90% возможностей С++ стоит выкинуть нафиг, оставив только то, что реально нужно. DE>Это только твоё мнение. Из Pаста тоже многое можно повыкидывать и без ущерба к надёжности.
А вот нельзя. Всё что можно выкинуть, уже почти выкинули. Пару лет назад там были зависимые типы, глобальный GC и т.п.
DE>Да и если на другие языки посмотреть — они тоже развиваются и увеличивают количество фич. Тот же С# скоро по "сложности" догонит С++ (если уже не обогнал).
В C# стараются не добавлять кривых фич, чтобы "лишь бы було". И начали с того, что взяли и выкинули 90% C++. И это работает, кстати.
C>>С каждой фичей матрица их взаимодействий растёт квадратично. В результате, сейчас С++ полностью не может знать никто. DE>Ложное утверждение. Во первых, не все фичи взаимодействуют.
Да ну? Можешь рассказать как будет работать "private virtual blah() volatile const"?
DE>Во вторых, в Расте фич гораздо больше, чем в С. Тем не менее язык получается "надёжнее" и удобнее.
Фундаментальных фич — не так сильно больше.
C>>И тех, которые могут заменить С++? Таких не знаю. DE>Не прикидывайся, что не понял. (Практически?) любую фичу можно выкинуть и язык всё равно может быть успешным.
В нише системных языков?
C>>То есть? GNOME написан на стандартном чистом C. Там объектная модель сделана полностью на ручных vtbl. DE>Изначально ты говорил про расширения языка. Они — непереносимы.
Расширения я упоминал только для RAII (__attribute(cleanup)__ из GCC/Clang). Всё остальное делается стандартным C.
DE>Хватит передёргивать и выдирать из контекста. Давай ещё раз — хочешь спорить с тем, что встроенные в язык решения не лучше/удобнее/проще непонятных реализаций? Особенно если в языке отсутствуют инструменты упрощающие такие вещи (типа макросов).
Да, встроенные в язык решения часто хуже библиотечных.
Sapienti sat!
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В Rust каждый generic может компилироваться отдельно — всё что нужно сделать компилятору, это просто подставить адреса реальных функций, реализующих trait'ы. В этом Rust похож на C#, где то же самое делается на уровне байт-кода.
Теперь понял о чём ты. А оптимизироваться/инлайниться при этом будет одинаково?
C>Каким образом модульность будет помогать с шаблонами С++? Эксперимент с "extern template" показал, что сильно шаблоны ускорить таким образом нельзя.
Как минимум, тем что хедеры не будут 100500 раз парситься.
Признаюсь честно — не особо вчитывался в описание модулей в С++. Тем не менее, заявлено ускорение и для темплейтов. Возможно, просто из-за того, что одни и те же инклюды не будут 100500 раз парситься.
В любом случае, я готов платить временем компиляции за производительность в рантайме (и дополнительную гибкость).
C>Возможно столкновение имён макросов, но на практике маловероятно. Нет фундаментальных причин, запрещающих делать namespace для макросов, просто оно пока разработчикам не нужно.
Что-то я не понял. Ты же сам нахваливал растовский принтф, который является макросом? Вполне пример внешнего интерфейса. В таком случае "столкновение имён" просто дело времени.
C>Не всегда происходит. В случае с double/float — да. А вот в случае с раскомментированием int — нет.
И это правильно. Неоднозначности ведь нет.
C>Нет. В случае с виртуальной функцией код поломается, если изменится именно реализация виртуальной функции. Это нормально. В случае с добавлением реализации frob() сломается совершенно посторонний код.
Не вижу существенной разницы.
C>Далее, в Rust серьёзно относятся к модульной компиляции. Предположим, что у нас есть модуль clink. Он использует модуль bling, внутри которого определена функция "frob(double)". Послезавтра в модуль bling добавили "frob(int)" — нужно ли в этом случае перекомпилировать clink? Если нужно, то как это обнаружить? А что если этот модуль binary-only?
В других языках это как-то решают.
C>А вот нельзя. Всё что можно выкинуть, уже почти выкинули. Пару лет назад там были зависимые типы, глобальный GC и т.п.
Да ладно. Если поискать, наверняка, что-то найдётся. К сожалению, с языком практически не знаком, так что сам привести примеры не смогу.
C>В C# стараются не добавлять кривых фич, чтобы "лишь бы було".
Да ладно? Давай заглянем в тему про С#6
От синтаксического сахара скоро что-нибудь слипнется.
Опасная это тенденция: чем больше всяких разных таких фишек, тем сложнее читать код неподготовленному человеку, тем медленнее изучение языка.
И тем проще написать плохо читаемый и ещё хуже работающий код.
Хотя, некоторые вещи и правда полезные, даже странно, что их сразу не сделали.
Кстати, перегрузка функция в С# есть...
C>И начали с того, что взяли и выкинули 90% C++. И это работает, кстати.
Заодно выкинули то из-за чего С++ вообще нужен. Язык получился абсолютно другой.
C>>>С каждой фичей матрица их взаимодействий растёт квадратично. В результате, сейчас С++ полностью не может знать никто. DE>> Ложное утверждение. Во первых, не все фичи взаимодействуют. C>Да ну?
Ну да. Не надо вырывать из контекста.
C>Можешь рассказать как будет работать "private virtual blah() volatile const"?
Что конкретно интересует?
В С# "private protected" тоже забавно смотрится.
C>Фундаментальных фич — не так сильно больше.
Тем не менее, больше. Да и сами фичи "более навороченные", по сравнению с простым до примитивности С.
Ну и дальше ты демагогией занимаешься.
DE>>Хватит передёргивать и выдирать из контекста. Давай ещё раз — хочешь спорить с тем, что встроенные в язык решения не лучше/удобнее/проще непонятных реализаций? Особенно если в языке отсутствуют инструменты упрощающие такие вещи (типа макросов). C>Да, встроенные в язык решения часто хуже библиотечных.
Опять передёргивание. Если в язык встроена нормальная возможность к расширению, то да, предпочтительнее библиотечное решение. Если нет, то рукодельные варианты будут уступать или производительностью или читабельностью или и тем и другим.
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>В Rust каждый generic может компилироваться отдельно — всё что нужно сделать компилятору, это просто подставить адреса реальных функций, реализующих trait'ы. В этом Rust похож на C#, где то же самое делается на уровне байт-кода. DE>Теперь понял о чём ты. А оптимизироваться/инлайниться при этом будет одинаково?
Да, есть возможность LTO — link time optimization, как и в С/C++.
C>>Каким образом модульность будет помогать с шаблонами С++? Эксперимент с "extern template" показал, что сильно шаблоны ускорить таким образом нельзя. DE>Как минимум, тем что хедеры не будут 100500 раз парситься.
И всё. Больше улучшений не планируется.
DE>В любом случае, я готов платить временем компиляции за производительность в рантайме (и дополнительную гибкость).
Тут уже есть примеры, когда Rust был быстрее кода на С++ за счёт более умного решения.
DE>Что-то я не понял. Ты же сам нахваливал растовский принтф, который является макросом? Вполне пример внешнего интерфейса. В таком случае "столкновение имён" просто дело времени.
println! — это пример системного макроса (их штук 10 всего), он включается в каждый файл автоматически. Остальные макросы должны подключаться явно самим пользователем.
C>>Нет. В случае с виртуальной функцией код поломается, если изменится именно реализация виртуальной функции. Это нормально. В случае с добавлением реализации frob() сломается совершенно посторонний код. DE>Не вижу существенной разницы.
Существенная разница в том, что добавление совершенно левого кода ломает не относящийся к нему код.
C>>Далее, в Rust серьёзно относятся к модульной компиляции. Предположим, что у нас есть модуль clink. Он использует модуль bling, внутри которого определена функция "frob(double)". Послезавтра в модуль bling добавили "frob(int)" — нужно ли в этом случае перекомпилировать clink? Если нужно, то как это обнаружить? А что если этот модуль binary-only? DE>В других языках это как-то решают.
В каких? Я их не знаю. В чистом С нет перегрузки функций. В C#/Java нет раздельной компиляции. Что ещё у нас остаётся?
C>>И начали с того, что взяли и выкинули 90% C++. И это работает, кстати. DE>Заодно выкинули то из-за чего С++ вообще нужен. Язык получился абсолютно другой.
Ага. А в Rust выкинули так, чтобы всё равно можно было использовать его как системный язык.
C>>Можешь рассказать как будет работать "private virtual blah() volatile const"? DE>Что конкретно интересует?
Их взаимодействие и что курил автор этого куска Стандарта.
C>>Да, встроенные в язык решения часто хуже библиотечных. DE>Опять передёргивание. Если в язык встроена нормальная возможность к расширению, то да, предпочтительнее библиотечное решение. Если нет, то рукодельные варианты будут уступать или производительностью или читабельностью или и тем и другим.
Встроенные в язык фичи означают, что у языка недостаточная выразительность, чтобы сделать их удобными библиотечными.
Sapienti sat!
Re[42]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Да, есть возможность LTO — link time optimization, как и в С/C++.
В С++ темплейты всё-таки могут легко инлайнится без привлечения линкера.
C>Тут уже есть примеры, когда Rust был быстрее кода на С++ за счёт более умного решения.
Кодегенерация для регэкспов? Ну да, хороший пример. Только это ведь возможно не из-за дополнительных ограничений генериков, а наоборот за счёт более мощной возможности (макросы).
C>println! — это пример системного макроса (их штук 10 всего), он включается в каждый файл автоматически. Остальные макросы должны подключаться явно самим пользователем.
Подключаться должны именно макросы? Не модули/либы их экспортирующие?
Если второе, то вполне вероятны конфликты. Если первое, то получше так как можно будет обойти, но тоже удобным это сложно назвать.
C>Существенная разница в том, что добавление совершенно левого кода ломает не относящийся к нему код.
Да нет существенной разницы. В худшем случае, оба вараинта вызовут проблемы.
Ну и я ни разу не сталкивался с такой проблемой с перегрузкой. Честно говоря, даже сложно представить когда это может вылезти, да ещё и так, чтобы было не очевидно.
C>Если нужно, то как это обнаружить?
Можно с модулем какие-то метаданные иметь.
C>В C#/Java нет раздельной компиляции.
Разве дотнетовские "сборки" (assembly) — это не то?
C>В чистом С нет перегрузки функций.
В С11 есть _Generic.
C>Их взаимодействие и что курил автор этого куска Стандарта.
Вроде, всё логично: констом ты объявляешь, что не будешь менять состояние класса внутри, а volatile говорит, что оно всё-таки может поменяться извне. Единственная практическая польза, которую вижу — компилятор даст по рукам при попытке всё-таки изменить что-то внутри метода.
Насчёт "что курил автор" — подозреваю просто для полноты добавили, примерно как протектед наследование. Проблемы в этом не вижу. Впрочем, я и просто volatile методы очень редко видел.
C>Встроенные в язык фичи означают, что у языка недостаточная выразительность, чтобы сделать их удобными библиотечными.
Тем не менее, совсем без встроенных фич не обойтись. Ну и популярные библиотечные решения часто в стандарт попадают.
Ну и злосчастную перегрузку функций ты вряд ли библиотекой добавишь.
Re[27]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Из твоих примеров совершенно не ясно, как получить цепочку вида x().y().z()
_>Так тебе надо цепочку или функцию вида "promise<Document> GetDocument()"? А то ты вроде как заказывал именно её в описание к тому API. Я потому и спрашиваю, что никак не могу понять что ты собственно хочешь увидеть.
Я хочу увидеть аналог x().y().z()
_>Если же говорить про цепочку, то чем тебе не нравится последовательность из .then().then()?
Это не то, что я просил. По существу, сравни две строки
1й это очевидный отстой, и я думал, что это не нужно объяснять, но у тебя наверняка своё видение и десятикратное увеличение кода не помеха
Напоминаю, x, y и z в либе объявлены вот так —
function x(success, error) {}
Как видишь, обычные колбеки. а вызвать цепочку надо вот так x().y().z()
I>>Далее, раз дело в метапрограммировании, ты не показал, как же именно будет генерироваться такой код
_>Я же говорил уже, что метапрограммирование не является обязательным для такого кода. Оно позволяет всего лишь перевести динамические вызовы (по виртуальным функциям) в статические, которые оптимизатор может заинлайнить и т.п.
Ты лучше покажи хоть одно решение, что бы выдавало именно то, что я просил. Не надо больше обших слов — или показывый или просто ничего не пиши, всё ведь и так ясно
I>>Ты сказал, что D классное метапрограммирование. И шота пока не ясно, как же сделать мой пример, который в джаваскрипте работает сам собой.
_>Ну да, в D оно сильнее чем в C++. А уже того, что есть в C++ достаточно для написание того же Sprit'a (который является примером реализации статического похода для подобных цепочек, хотя и не связанных с асинхронностью). Правда в C++ Spirit уже написан, а в D пока нет...
Неинтересный аргумент, это общие слова.
_>Что касается JS, то интересно, есть ли для него хоть одна нормальная реализация сопрограмм? )
Разумеется, как stackless так и stackfull. Осенью ты уже задавал этот же вопрос, кстати говоря. Воспользуйся поиском.
Сегодня в 8 вечера по Москве Scott Meyers выступит с загадочной речью "The Last Thing D Needs". Онлайн-трансляцию можно будет посмотреть здесь: http://www.ustream.tv/channel/dconf-2014
Затем будет выступление бородатой женщины про написанный на D JIT-компилятор JS, потом другие акробаты, клоуны и жонглеры.
Это сейчас в логове Фейсбука проходит DConf 2014: http://dconf.org/2014/schedule/
Я вчера первые три выступления посмотрел, трансляция очень качественно сделана. В онлайне было около 150 зрителей, в аудитории раза в 3-4 меньше.
Все это будет потом на ютюбе, но позже.
Re[42]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
_>>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
FR>Это не то настоящий суровый printf должен практически все ошибки отлавливать во время компиляции, например как в OCaml: FR>...
Ну так это уже будет совсем другая функция с другим прототипом — там первым параметром должно идти что-то типа constexpr. На D естественно пишется без проблем. Ну а на C++ теоретически тоже можно поизвращаться, но будет очень криво из-за отсутствия возможности передавать строки как параметры шаблонов.
Re[42]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
_>>Ну я с этим собственно и не спорил, хотя бы уже потому, что не претендую на какие-то знания макросов Rust'a. C>Ну вот как раз кто-то спорил
Не помню тут критических отзывов о них. )
_>>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам. C>Там описано, что так сделать можно, но конкретного кода нет. Я в целом вполне верю, что это возможно, но вот на constexpr и шаблонах сделать полный разбор строки printf — совсем нетривиально.
Не, там был как раз конкретный код (на странице 21). Только там разбор то идёт в рантайме (а иначе и не возможно для функции с прототипом как у printf, не переделывая первый параметр на что-то типа constexpr), так что вообще никаких сложностей нет.
А вот сделать разбор во время компиляции на C++ действительно очень не просто из-за его ограничений работы со строками в шаблонах (соответственно на D эта задачка решается элементарно). Однако подобные извращённые решения я тоже видел... Только там строку соответственно надо по странному задавать (макросом например и т.п.), т.е. это не прямая замена нормальному printf'у.
_>>Не очень понятно как это сделать, ведь gettext будет возращать обычную строку, а не что-то вроде constexpr. C>Будет специальная функция, назовём её "T" с такой сигнатурой: "fn T(initial: str) -> &'static str". Т.е. в программе будет что-то типа: "println!(T("Hello, world"), ...)". Макрос println! будет знать про то, что T будет возвращать исходную строку и для проверки валидности форматной строки просто возьмёт её аргумент. Ну а во время исполнения оно будет работать всё как обычно.
C>Ещё, вместо hard-coded имени T можно сделать специальную аннотацию на функцию.
Хы, модно. Такие вещи уже действительно только макросами делаются (если действительно делаются — я пока не видел сам, а верю на слово), а не метапрограммированием на шаблонах.
Re[43]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>Да, есть возможность LTO — link time optimization, как и в С/C++. DE>В С++ темплейты всё-таки могут легко инлайнится без привлечения линкера.
Только вот далеко не всегда это надо. В Rust есть опциональная возможность добавить force_inline аннотацию, кстати.
C>>Тут уже есть примеры, когда Rust был быстрее кода на С++ за счёт более умного решения. DE>Кодегенерация для регэкспов? Ну да, хороший пример. Только это ведь возможно не из-за дополнительных ограничений генериков, а наоборот за счёт более мощной возможности (макросы).
В Rust нет причин, по которым generics будут сильно тормознее С++. Ну разве что, сейчас в кодогенераторе многое ещё не оптимизировано.
C>>println! — это пример системного макроса (их штук 10 всего), он включается в каждый файл автоматически. Остальные макросы должны подключаться явно самим пользователем. DE>Подключаться должны именно макросы? Не модули/либы их экспортирующие?
Да, именно макросы. Выглядит так:
//Подключаем макрос из внешней библиотеки на стадию разбора синтаксиса
#[phase(syntax)]
extern crate regex_macros;
В соседнем файле этот макрос может и не подключаться.
C>>Существенная разница в том, что добавление совершенно левого кода ломает не относящийся к нему код. DE>Да нет существенной разницы. В худшем случае, оба вараинта вызовут проблемы.
Где?
DE>Ну и я ни разу не сталкивался с такой проблемой с перегрузкой. Честно говоря, даже сложно представить когда это может вылезти, да ещё и так, чтобы было не очевидно.
Я встречался.
C>>Если нужно, то как это обнаружить? DE>Можно с модулем какие-то метаданные иметь.
Каким образом? А что если нет исходников?
C>>В C#/Java нет раздельной компиляции. DE>Разве дотнетовские "сборки" (assembly) — это не то?
Не то.
C>>В чистом С нет перегрузки функций. DE>В С11 есть _Generic.
Оно работает на заранее перечисленных типах. Это не перегрузка.
DE>Насчёт "что курил автор" — подозреваю просто для полноты добавили, примерно как протектед наследование. Проблемы в этом не вижу. Впрочем, я и просто volatile методы очень редко видел.
Ну вот С++ весь такой. И D тоже приближается к нему.
C>>Встроенные в язык фичи означают, что у языка недостаточная выразительность, чтобы сделать их удобными библиотечными. DE>Тем не менее, совсем без встроенных фич не обойтись. Ну и популярные библиотечные решения часто в стандарт попадают.
Стандартная библиотека, если она не в виде компиляторной магии, — это не проблема.
DE>Ну и злосчастную перегрузку функций ты вряд ли библиотекой добавишь.
И не надо.
Sapienti sat!
Re[28]: Язык D - действительно красота и эффективность в одном ф
I>1й это очевидный отстой, и я думал, что это не нужно объяснять, но у тебя наверняка своё видение и десятикратное увеличение кода не помеха
Безусловно второй вариант красивее. Однако это единственное их отличие. Т.е. если у нас есть реализация для then, то это полностью решает твою задачу. А все твои претензии сводятся уже не к возможности решения, а к красоте, т.е. по сути синтаксическому сахару.
Что касается синтаксического сахара... На C++ сделать точную копию данного кода конечно не просто. Точнее это легко делается для глобальных функций. Получится что-то вроде "x()|y|z;" (просто переопределяем оператор | для future и засовываем then туда). Однако для функций-членов (как в твоём примере) это будет выглядеть заметно страшнее, типа "x()|XR::y|YR::z;", так что наверное лучше обычным then'ом обойтись и не мутить лишнего сахара.
А вот на D, благодаря наличию в нём перегрузки оператора вызова функции-члена, можно в одну строчку реализовать синтаксический сахар в точности, как ты хочешь.
Re[44]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Только вот далеко не всегда это надо.
А когда это может мешать?
Ну и запретить тоже можно.
C>В Rust есть опциональная возможность добавить force_inline аннотацию, кстати.
И оно заинлайнит, если исходников нет?
C>В Rust нет причин, по которым generics будут сильно тормознее С++. Ну разве что, сейчас в кодогенераторе многое ещё не оптимизировано.
Во первых, "сильно" понятие растяжимое. Так можно заявить, что "нет причин, по которым компиляция С++ кода будет сильно тормознее".
Во вторых, речь шла про возможности, а не скорость.
C>Я встречался.
Можешь рассказать подробнее?
Желательно с уточнением насколько сложно и долго это было обнаружить.
C>Каким образом? А что если нет исходников?
Что-то типа комовских "type libraries", наверное, можно сделать.
Ну и вон с длл-ками либ-файлы тоже нужны. В чём проблема так дополнительную информацию хранить?
C>Не то.
Почему?
C>Оно работает на заранее перечисленных типах. Это не перегрузка.
Ну да. Тем не менее, люди вот так извращаются. И запросто может оказаться, что кто-то "переопределил" таким образом, ты включаешь какой-то файл и поведение меняется.
C>Ну вот С++ весь такой. И D тоже приближается к нему.
Все "развивающиеся" языки приближаются.
Конечно, можно делать это более или менее удачно. В С++ корявых мест хватает, но то, к чему ты придрался — вообще ерунда и проблем не вызывает.
Кстати, я не занимаюсь доказательством преимуществ D, если что.
C>Стандартная библиотека, если она не в виде компиляторной магии, — это не проблема.
Если "компиляторная магия" позволяет сделать что-то удобнее/быстрее, то почему бы и нет.
Да и некоторые фичи являются основными для языка. Скажем, невозможность объявить функцию без подключения (пусть и стандартной) библиотеки выглядит дурацки. Если вдруг забыл, то мы говорили о том хорошо ли что-то "встраивать в язык".
C>И не надо.
Надо или нет — не важно. Факт, что далеко не всё ты сможешь сделать.
Re[29]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Безусловно второй вариант красивее. Однако это единственное их отличие. Т.е. если у нас есть реализация для then, то это полностью решает твою задачу. А все твои претензии сводятся уже не к возможности решения, а к красоте, т.е. по сути синтаксическому сахару.
начиная с ассемблера всё есть сахар
_>А вот на D, благодаря наличию в нём перегрузки оператора вызова функции-члена, можно в одну строчку реализовать синтаксический сахар в точности, как ты хочешь.
Напомню, мы подключаем внешнюю либу, у ней как глобальные так и все остальные функции сделаны на колбеках.
У кого ты собираешься перегружать оператор вызова?
Re[30]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Напомню, мы подключаем внешнюю либу, у ней как глобальные так и все остальные функции сделаны на колбеках.
I>У кого ты собираешься перегружать оператор вызова?
У future естественно. Так что у него можно будет вызвать произвольную функцию член (и оператор соответственно форвардит этот вызов к внутреннему типу, через then). Т.е. благодаря этой фичи языка D у класса future<XR> будет иметься метод y, который будет возвращать future<YR> (делая при этом внутри вызов настоящего y через then). И всё это ровно в одну строчку и для всех типов сразу.
Но опять же, это всё просто синтаксический сахар, а работающий вариант мы имеем и на C++, просто он выглядит чуть длиннее.
Re[31]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>У кого ты собираешься перегружать оператор вызова?
_>У future естественно. Так что у него можно будет вызвать произвольную функцию член (и оператор соответственно форвардит этот вызов к внутреннему типу, через then). Т.е. благодаря этой фичи языка D у класса future<XR> будет иметься метод y, который будет возвращать future<YR> (делая при этом внутри вызов настоящего y через then). И всё это ровно в одну строчку и для всех типов сразу.
У тебя решение, как сделать второй и последующие вызовы. А как сделать первый ?
т.е. вместо x(success, error) надо x() и он должен вернуть тот же тип, что приходит в success колбеке.
Re[32]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>У тебя решение, как сделать второй и последующие вызовы. А как сделать первый ?
Ну да. Так вроде мы только на проблеме организации цепочек вложенных асинхронных вызовов и остановились, т.к. с просто вызовами давно всё обсудили. И кстати надо признать, что на C++ организовать цепочку с точно такими фичами, как ты хотел, не выходит. Только несколько более громоздкая выходит на плюсах, хотя по смыслу естественно всё тоже самое. А вот на D уже всё в точности как ты хочешь.
I>т.е. вместо x(success, error) надо x() и он должен вернуть тот же тип, что приходит в success колбеке.
Ну во-первых x() будет возвращать не тот тип, что приходит в success, а future<> от него.
. Применительно конкретно к нашему случаю, внутри x() будет просто один вызов x(success, error) с лямбдами, в которых будет promise.set_value, ну и соответственно в конце return promise.get_future(). Кстати, этот код вполне универсальный (с точностью до определения нашего асинхронного апи), так что его можно оформить в один шаблон, который будет подходит сразу под все подобные функции (x, y, z).
Re[33]: Язык D - действительно красота и эффективность в одном ф
. Применительно конкретно к нашему случаю, внутри x() будет просто один вызов x(success, error) с лямбдами, в которых будет promise.set_value, ну и соответственно в конце return promise.get_future(). Кстати, этот код вполне универсальный (с точностью до определения нашего асинхронного апи), так что его можно оформить в один шаблон, который будет подходит сразу под все подобные функции (x, y, z).
Применительно к нашему случаю — весь код JS будет в либе. Не нужно даже генерировать код. То есть, вообще. Более того, и руками не нужно будет помогать. Так что в целом смотрится очень смешно.
"Кстати, в том же JS я что-то не помню реализации чего-то подобного..."
Re[34]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Применительно к нашему случаю — весь код JS будет в либе. Не нужно даже генерировать код. То есть, вообще. Более того, и руками не нужно будет помогать. Так что в целом смотрится очень смешно.
А что тебе мешает закинуть весь этот код в либу в D? И зачем где-то помогать руками? )
Re[35]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Применительно к нашему случаю — весь код JS будет в либе. Не нужно даже генерировать код. То есть, вообще. Более того, и руками не нужно будет помогать. Так что в целом смотрится очень смешно.
_>А что тебе мешает закинуть весь этот код в либу в D? И зачем где-то помогать руками? )
Ты же ни решения, ни набросков не показал
Re[36]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Ты же ни решения, ни набросков не показал
Ээээ что? )Я тебе показал как преобразовать коллбэк в асинхронный вызов (и на C++ и на D одинаково) и как организовать цепочку таких вызовов (красиво на D и чуть пострашнее на C++). Причём всё это в виде шаблонов, так что пишется один раз и закидывается в библиотеку. Чего тебе ещё не хватает то? )
Re: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>Ты же ни решения, ни набросков не показал
_>Ээээ что? )Я тебе показал как преобразовать коллбэк в асинхронный вызов (и на C++ и на D одинаково) и как организовать цепочку таких вызовов (красиво на D и чуть пострашнее на C++). Причём всё это в виде шаблонов, так что пишется один раз и закидывается в библиотеку. Чего тебе ещё не хватает то? )
Ты не показал самого главного — как оформить нужный апи. Вместо этого ты показал, что будет унутре.
не надо объяснять, что унутре будет аналог промисов. Покажи как именно будет сделан апи. Что там унутре, было понятно и до твоих объяснений.
Re[2]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, ivanzoid, Вы писали:
I>>Ребята, не то вы обсуждаете. I>>Из новых языков, I>>Github repositories, stars > 10: I>>D I>>Rust I>>Go
DM>Так и PHP популярней хаскеля. Но на этом Вне сам пиши.
Кстати. Правильно ли я понял, что вы утверджаете, что Хаскель лучше чем PHP?)
Re[38]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Ты не показал самого главного — как оформить нужный апи. Вместо этого ты показал, что будет унутре.
I>не надо объяснять, что унутре будет аналог промисов. Покажи как именно будет сделан апи. Что там унутре, было понятно и до твоих объяснений.
Ааа, ну ОК. Хотя мне казалось это гораздо более очевидно, чем внутренняя структура.
И так, в твоей задачке у нас "задан свыше" некий асинхронный api (сомнительная вещь на самом деле, ну да ладно). Зафиксируем его в виде тестового C++ кода:
struct ZR{
string value;
};
struct YR{
double value;
void z(function<void(ZR&)> success, function<void(int)> error);
//внутри может быть например thread([]{s(ZR{to_string(value)};}).detach();
};
struct XR{
int value;
void y(function<void(YR&)> success, function<void(int)> error);
//внутри может быть например thread([]{s(YR{value/10.0};}).detach();
};
void x(function<void(XR&)> success, function<void(int)> error);
//внутри может быть например thread([]{s(XR{42};}).detach();
И нам соответственно надо получить результат вычисления цепочки этих асинхронных вызовов. Для этого подключаем один маленький библиотечный (т.е. ничего не знающий про x, y, z) hpp файл и тогда можем написать например так:
auto f=async()|x|&XR::y|&YR::z;
//тут спокойно занимаемся другими делами, а f вычисляется где-то в других потоках
cout<<f.get().value<<endl;
Конечно код не особо красивый, но на C++ у нас маловато инструментов для украшательств. А вот на D без проблем можно получить при аналогичном раскладе такой код:
auto f=async().x().y().z();
//тут спокойно занимаемся другими делами, а f вычисляется где-то в других потоках
writeln(f.get().value);
Re[4]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, alex_public, Вы писали:
>Ааа, ну ОК. Хотя мне казалось это гораздо более очевидно, чем внутренняя структура.
_>И так, в твоей задачке у нас "задан свыше" некий асинхронный api (сомнительная вещь на самом деле, ну да ладно). Зафиксируем его в виде тестового C++ кода: _>
_>auto f=async().x().y().z();
_>
Вот этот async как сделан ?
Re[5]: Язык D - действительно красота и эффективность в одном флаконе
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, ivanzoid, Вы писали:
I>>Кстати. Правильно ли я понял, что вы утверджаете, что Хаскель лучше чем PHP?)
DM>Зависит от того, как понимать "лучше". В первом языке есть дизайн, логика, красота, безопасность и эффективность, во втором ничего этого нет.
Но позвольте с вами поспорить. Я вообще сам конечно не очень люблю PHP, но этот язык заставляет себя уважать. На PHP работает Фэйсбук и ВКонтакте (оставим в стороне эмоциональную оценку их пользователей и примем во внимание только технический масштаб проектов). Что работает на хаскеле?
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, ivanzoid, Вы писали:
I>Но позвольте с вами поспорить. Я вообще сам конечно не очень люблю PHP, но этот язык заставляет себя уважать. На PHP работает Фэйсбук и ВКонтакте (оставим в стороне эмоциональную оценку их пользователей и примем во внимание только технический масштаб проектов).
Тут следует заметить, что:
1) эти проекты использовали РНР не потому, что сам язык чем-то хорош, а лишь поскольку первоначальные авторы его знали, и он был популярен. Популярность — это важное свойство языка, но оно все же внешнее, нетехническое и неимманентное.
2) И Фейсбук и ВКонтакте по сути отказались от самого РНР и сконструлили свои варианты, лишь отчасти пересекающиеся с РНР и то лишь по историческим причинам (чтобы не все переписывать). Фейсбук сейчас работает на Hack'e, который сам написан на Окамле. При этом некоторые части Фейсбука таки сделаны на хаскеле. ВКонтакте запили свой транслятор в С++: https://github.com/vk-com/kphp-kdb/
I>Что работает на хаскеле?
Например, такой RSS-ридер, замена почившему Google Reader'у: https://bazqux.com/
Плюс некоторые банки его активно используют, http://www.haskell.org/haskellwiki/Haskell_in_industry
плюс всякий десктопный софт на нем делается (оконный менеджер xmonad, конверторы вроде Pandoc, архиватор FreeArc, компиляторы...).
Re[42]: Язык D - действительно красота и эффективность в одном ф
Так мы же передаём эту функцию (или указатель на глобальный метод/функцию-член в C++ или вообще как строку с именем метода в D) как параметр к перегруженному оператору (| в C++ или . в D) future.
I>2 для структур XR, YR должен быть переопределен оператор (), кто его будет переопределять ?
Ээээ что? ) Перегрузки оператора () нет ни в C++ ни в D варианте.
Re[43]: Язык D - действительно красота и эффективность в одном ф
I>>Как это делается ?
_>Так мы же передаём эту функцию (или указатель на глобальный метод/функцию-член в C++ или вообще как строку с именем метода в D) как параметр к перегруженному оператору (| в C++ или . в D) future.
Непонятно
я пишу async(), и это вдруг значит, что my_future<void>(), который унутре либы и про x ничего не знает должен узнать, что x можно вызывать вот вот.
Как узнать, что теперь у этого объекта можно вызвать метод, про который объет не знает ?
если my_future<void>() генерируется текстом, то все понятно. А вот если генерации нет, то непонятно.
I>>2 для структур XR, YR должен быть переопределен оператор (), кто его будет переопределять ?
_>Ээээ что? ) Перегрузки оператора () нет ни в C++ ни в D варианте.
Не важно. Объясни подробно, как будет работать связывание.
Re[44]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>Непонятно
I>я пишу async(), и это вдруг значит, что my_future<void>(), который унутре либы и про x ничего не знает должен узнать, что x можно вызывать вот вот.
I>Как узнать, что теперь у этого объекта можно вызвать метод, про который объет не знает ?
I>если my_future<void>() генерируется текстом, то все понятно. А вот если генерации нет, то непонятно.
Так "my_future<void> f0;" и не умеет ничего. А вот my_future<XR> f1=f0|x; уже всё знает про x и про ХR. Конечно это не изящное решение, но большего в C++ что-то с ходу не придумывается. А вот в D, в котором есть перегрузка оператора ".", которая выглядит как шаблонная функция с параметром string'ом содержащим имя вызываемого метода, можно сделать красивый код вида my_future!void f0; my_future!XR f1=f0.x();
Re[45]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>Непонятно
>А вот в D, в котором есть перегрузка оператора ".", которая выглядит как шаблонная функция с параметром string'ом содержащим имя вызываемого метода, можно сделать красивый код вида my_future!void f0; my_future!XR f1=f0.x();
Ну вот, т.е. ты имел ввиду opDispatch, правильно ?
Re[46]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
I>>Ну вот, т.е. ты имел ввиду opDispatch, правильно ?
_>Конечно. А внутри него then на соответствующий mixin и всё.
А без async() сможешь ?
Re[48]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Ikemefula, Вы писали:
I>А без async() сможешь ?
Это в смысле чтобы был x().y().z() без какой-либо сущности слева, в начале цепочки? Боюсь такое без дополнительной подготовки (типа какого-нибудь макроса предварительно вызванного для х и автоматом создающего нужную x без параметров) уже не получится...