| Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум на Исходниках.RU > Holy Wars > D vs C++ |
| Автор: applegame 11.02.14, 06:53 |
| Создаю эту тему ради пропаганды замечательного языка D. Отвечу на вопросы, сравню с C++ ну и все такое. Вдруг кому-то покажется интересным. Для начала хочу отметить, что D стремительно набирает популярность в мире. По версии tiobe.com, индекс D за один год поднялся с 36-места до 18-го и теперь язык входит в топ-20. На него все больше и больше обращают внимание крупные коммерческие организации, например: - швейцарская компания CSCS специализирующая на разработке ПО для суперкомпьютеров; - Facebook; Кроме "родного" кроссплатформенного компилятора DMD, существуют также компилятор на базе LLVM: LDC и на базе GCC: GDC. В чем основное преимущество D перед C++ лично для меня? В первую очередь - это значительно более мощные возможности метапрограммирования, поверьте, C++ до такого уровня, как пешком до Луны. При этом конструкции в D, как правило, выглядят намного проще аналогов из C++, даже учитывая долгожданные нововведения стандарта C++11. Преимущества перед C++: - встроенные ассоциативные массивы. - тип real (идеален для математических вычислений); - мощный и в тоже время простой синтаксис шаблонов; - примеси (mixins); - отсуствие необходимости в заголовочных файлах (это свобода, вы плюсовики, просто не знаете как это прекрасно); - Настоящая условная компиляция в зависимости от ключей в командной строке, процессора, кода, версии и т.п.; - настоящий CTFE, вплоть до compile-time импорта в строку и парсинга файла в код на D; - встроенные делегаты; - нормальные лямбды, тип которых зависит напрямую от сигнатуры, а не как компилятор на душу положит. Кроме того имеется прекрасный сокращенный стиль их написания; - встроенный TLS (thread local storage) - это реально круто; - встроенный compile-time reflection: можно разобрать по косточкам класс/структуру/функцию и на основании этого сгенерить нужный код; - ???? - PROFIT!!!! Справедливости ради, минусы D: - сборщик мусора, к тому же еще и не самый продвинутый; - сам язык, к сожалению, еще до конца строго не определен, из-за чего при смене версий, могут вылезать предупреждения об устаревании. - некоторые части стандартной библиотеки Phobos - ужасающи, и некому их переписать. - слабая "обвязка": мало библиотечек, IDE. компиляторов, инструментов и т.д; хотя, надо признать, сейчас ситуация весьма лучше чем пару лет назад. Для начала холивара, вот вам сравнение двух идентичных кусков кода на C++ и D: C++ <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> #include <type_traits> #include <iostream> template<class T> typename std::enable_if<std::is_floating_point<T>::value, T>::type foo1(T t) { std::cout << "foo1: float\n"; return t; } template<class T> typename std::enable_if<std::is_integral<T>::value, T>::type foo1(T t) { std::cout << "foo1: int\n"; return t; } int main() { foo1(1.2); foo1(10); } D вариант 1 <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.stdio; import std.traits; T foo1(T)(T t) if(isFloatingPoint!T) { writeln("foo1: float"); return t; } T foo1(T)(T t) if(isIntegral!T) { writeln("foo1: int"); return t; } void main() { foo1(1.2); foo1(10); } D вариант 2 <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.stdio; import std.traits; T foo1(T)(T t) { static if(isFloatingPoint!T) { writeln("foo1: float"); } else static if(isIntegral!T) { writeln("foo1: int"); } else { static assert(false, "type: '" ~ T.stringof ~ "' is not allowed"); } return t; } void main() { foo1(1.2); foo1(10); foo1("test"); // static assert with message } |
| Автор: D_KEY 11.02.14, 07:11 |
У меня дежавю? |
| Автор: applegame 11.02.14, 07:13 |
Ну времени прошло много, многое поменялось. Пора снова просвещать массы |
| Автор: Мяут-Настоящий 11.02.14, 07:22 |
D это такая Java с плюшками как в Scal'е для C++сников? Ну я как раз-таки и люблю (правда не пользую C++) за то, что там не нужно ждать мегавещей от компилятора, т.к. многие вещи пилятся шаблонами. |
| Автор: D_KEY 11.02.14, 07:23 |
| Встроенные ассоциативные массивы? Зачем? Не ПХП вроде. А есть выбор между хэш-таблицами и деревьями? Тип real? Это который long double? Плюшки шаблонов не в синтаксисе. Надо задачки решать, чтоб сравнивать. Примеси там не из-за отсутствия множественного наследования, случаем? Не, так неудобно отвечать, чуть позднее напишу с компа |
| Автор: Wound 11.02.14, 07:24 |
| А что на счет тестов производительности? |
| Автор: Повстанець 11.02.14, 07:27 |
| Опоздал язык D в своём явлении миру лет эдак на 10, минимум. Времена языков общего назначения давно прошли. Но это так.. к слову. А вообще достоинства D выглядят хорошо только на первый взгляд. На самом деле в средненьком таком проекте никто не пишет сложный, сверхгибкий шаблонный код. Весь он уходит в библиотеки. В лучшем случае -- в утилитарный код, либо куда нить на нижние слои архитектуры, для придания гибкости. В остальном -- стандартненькое ООП, где шаблоны и прочие плюшки по большей части юзаются, нежели создаются. И будь эти все фишки хоть в 10 раз проще, это не сэкономило так уж много времени. В остальном, С++ ценится за хороший контроль потребления ресурсов и за совместимость с С. Там где не надо так уж заботится о ресурсах и не нужна совместимость с С (частенько это просто идёт рука об руку), легче использовать всякие явашарпы, в зависимости от области. ИМХО, очень тяжело подобрать задачи, где нужен был бы язык, более высокоуровневый, чем С++ и менее высокоуровневый, чем явашарпы всякие. |
| Автор: Flex Ferrum 11.02.14, 07:33 |
applegame, с учётом того, что сейчас творится в рабочих группах комитета по стандартизации C++ - все эти плюшки весьма сомнительные. |
| Автор: applegame 11.02.14, 07:41 |
| Не знаю, как в Scala. На жабу не похоже. Гораздо ближе к плюсам, да и компилится в нативный код. Цитата D_KEY @ Ассоциативные массивы очень часто используются, так что сделать их одним из базовых типов, ИМХО, верный ход. Выбора нет, в D ассоциативные массивы - это всегда хэш-таблицы. Для деревьев есть стандартная библиотека с соответствующими шаблонами.Близок. Стандарт четко его описывает как максимально большой тип поддерживаемый железом.Давай задачу, или я могу дать. Я решаю в D, ты в плюсах Встроенные ассоциативные массивы? Зачем? Не ПХП вроде. А есть выбор между хэш-таблицами и деревьями? , вот и сравним.В частности, но они и сами по себе весьма хороши, я тебе скажу.Вполне достойно: раз, два. Добавлено Цитата Повстанець @ Это свойство присуще C++. Из-за его крайне громоздкого и корявого синтаксиса шаблонов (посмотрите в буст и ужаснитесь), плюсовое метапрограммирование стало эдаким развлечением для суровых челябинских программистов. В D шаблоны намного проще и мощнее. Благодаря этому они используются повсеместно. В C++ мне приходилось напрягаться чтобы написать очередной относительно сложный шаблон, в D это делается настолько легко и непринужденно, что я даже местами забываю, что это не обычная функция, а шаблонная. На самом деле в средненьком таком проекте никто не пишет сложный, сверхгибкий шаблонный код. Весь он уходит в библиотеки. В лучшем случае -- в утилитарный код, либо куда нить на нижние слои архитектуры, для придания гибкости. В остальном -- стандартненькое ООП, где шаблоны и прочие плюшки по большей части юзаются, нежели создаются. Добавлено Цитата Flex Ferrum @ Это мы еще посмотрим. Комитет по стандартизации - дикий тормоз, а еще ведь нужно ждать пока все эти новшества будут добавлены в компиляторы. А в D - это уже есть: здесь и сейчас. applegame, с учётом того, что сейчас творится в рабочих группах комитета по стандартизации C++ - все эти плюшки весьма сомнительные. ![]() |
| Автор: OpenGL 11.02.14, 08:03 |
| Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов. В яве и шарпе интерфейс по-сути предъявляет требования к наличию методов, но откуда они были получены - неважно. Пример: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> interface IFoo { void f(); void g(); }; class Base { void f(); }; class Derived : Base, IFoo { void g(); // Этого достаточно - f реализована в базовом классе }; В D же такое не компилится - говорит, что интерфейс реализован не до конца. Имхо, это не совсем корректное поведение |
| Автор: Flex Ferrum 11.02.14, 08:08 |
| Цитата applegame @ В C++ мне приходилось напрягаться чтобы написать очередной относительно сложный шаблон, в D это делается настолько легко и непринужденно, что я даже местами забываю, что это не обычная функция, а шаблонная. Это сомнительное преимущество. Простой шаблон и в C++ несложно написать. А вот когда речь заходит о чём-то более сложном - тут уже проблема не столько в синтаксисе, сколько в том, чтобы это сложное адекватно спроектировать. Сейчас он достаточно активно жмёт на газ. Разбиение на рабочие группы и комитеты пошло явно на пользу.Цитата applegame @ а еще ведь нужно ждать пока все эти новшества будут добавлены в компиляторы. А в D - это уже есть: здесь и сейчас. Сейчас два из трёх mainstream-компилятора идут ноздря-в-ноздрю с комитетом. Что gcc, что clang уже активно запиливают новые фичи. |
| Автор: applegame 11.02.14, 08:12 |
| Цитата OpenGL @ Это фича. Почему так сделано не знаю, описано здесь - http://dlang.org/interface.html Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов. Добавлено Цитата Flex Ferrum @ Ну таки не ноздря в ноздрю. Да и сlang + windows = головная боль.Сейчас два из трёх mainstream-компилятора идут ноздря-в-ноздрю с комитетом. Что gcc, что clang уже активно запиливают новые фичи. Короче, как говорится: поживем - увидим. |
| Автор: D_KEY 11.02.14, 08:28 |
| Цитата applegame @ отсуствие необходимости в заголовочных файлах (это свобода, вы плюсовики, просто не знаете как это прекрасно) Плюсовики пишут и на других языках, поэтому представляют Нормальные модули это хорошо, но вот отделение объявлений и определений - штука полезная. По крайней мере это вопрос дискуссионный. Кстати, я помню времена, когда в агитках по D писали, что модель с разделением файлов поддерживается тоже и можно писать в том стиле, в котором хочешь. Цитата Настоящая условная компиляция в зависимости от ключей в командной строке, процессора, кода, версии и т.п. А при использовании препроцессора она не настоящая? А для D я смогу задать какие-то константы через систему сборки? Цитата настоящий CTFE, вплоть до compile-time импорта в строку и парсинга файла в код на D Попадались мне разные тесты, которые показывали, что как-то не очень там все. Впрочем, не найду сейчас Цитата встроенные делегаты нормальные лямбды, тип которых зависит напрямую от сигнатуры, а не как компилятор на душу положит. Кроме того имеется прекрасный сокращенный стиль их написания Мы вроде даже на форуме выясняли, что преимуществ перед лямбдами и std::function нет. Единственная фича - сохранение захваченного контекста, а не как в C++, где захват по ссылке локальной переменной приведет к проблемам, если лямбда будет жить дольше локального фрейма. Цитата встроенный TLS (thread local storage) - это реально круто Чем это принципиально отличается от возможностей C и C++? Цитата встроенный compile-time reflection: можно разобрать по косточкам класс/структуру/функцию и на основании этого сгенерить нужный код Это гуд. А можно парочку примеров? Цитата сборщик мусора, к тому же еще и не самый продвинутый Недостатком является его плохая степень опциональности. Сам по себе сборщик это хорошо, если он не вездесущий. |
| Автор: applegame 11.02.14, 08:34 |
| Цитата OpenGL @ Короче покопал тему. В плюсах сделано также как и в D: http://ideone.com/q5rgmu, И это сделано правильно.Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов. В яве и шарпе интерфейс по-сути предъявляет требования к наличию методов, но откуда они были получены - неважно. Интерфейс - это требование реализации, а не просто наличия. Кроме того, интерфейс - это еще и базовый тип с виртуальными функциями f() и g(). Класс Base в твоем примере никакого отношения к IBoo не имеет, соответственно функция интерфейса f() в классе Derived не реализована и не может быть вызвана через тип интерфейса. Хз как это сделано в этих ваших явах и шарпах. Наличие можно проверить по другому и интерфейсы здесь вообще-то не нужны. |
| Автор: D_KEY 11.02.14, 08:45 |
| Цитата applegame @ Ассоциативные массивы очень часто используются, так что сделать их одним из базовых типов, ИМХО, верный ход. Какие плюсы от встраивания в язык? Цитата Близок. Стандарт четко его описывает как максимально большой тип поддерживаемый железом. У D, если что, нет стандарта. Цитата Это свойство присуще C++. Из-за его крайне громоздкого и корявого синтаксиса шаблонов (посмотрите в буст и ужаснитесь), плюсовое метапрограммирование стало эдаким развлечением для суровых челябинских программистов. Не согласен Шаблоны, как правило, действительно наиболее полезны в библиотеках и "утилитарном" коде. Хотя и не всегда.Цитата А в D - это уже есть: здесь и сейчас. Вопрос в том, есть ли здесь и сейчас сам D и в каком он состоянии. Добавлено Цитата applegame @ Цитата OpenGL @ Это фича.Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов. Плохая фича. Добавлено Нет, не так же. В плюсах нет интерфейсов. |
| Автор: trainer 11.02.14, 08:46 |
| Ты в прошлом дельфист? Это характерная кодовая фраза. |
| Автор: D_KEY 11.02.14, 08:47 |
| Цитата applegame @ Кроме того, интерфейс - это еще и базовый тип с виртуальными функциями f() и g(). А не должен быть Иначе это не интерфейс, а обычный плюсовый абстрактный класс. Вот только множественного наследования в D нет |
| Автор: sergioK 11.02.14, 08:49 |
| IDE какие для D , кроме Code Blocks ? |
| Автор: applegame 11.02.14, 08:58 |
| Цитата D_KEY @ Да, такая модель поддерживается, но не обязательна и, реально имеет смысл, только для библиотек с закрытым исходным кодом.Кстати, я помню времена, когда в агитках по D писали, что модель с разделением файлов поддерживается тоже и можно писать в том стиле, в котором хочешь. Цитата D_KEY @ Препроцессор - кривой костыль. В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык:А при использовании препроцессора она не настоящая? А для D я смогу задать какие-то константы через систему сборки? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Версию можно задать и кастомную через аргументы командной строки, Затем проверять ее. Раскрыто здесь: http://dlang.org/version.htmlversion(Windows) { ... } version(linux) { ... } Цитата D_KEY @ Когда-то было худо. Сейчас есть небольшие проблемы с производительностью при очень больших объёмах CTFE-кода. В проекте над которым я тружусь вовсю используются compile-time веб-шаблоны написаные на Diet. Они компиляться прямо в D-код, из-за чего чрезвычайно быстры.Попадались мне разные тесты, которые показывали, что как-то не очень там все. Впрочем, не найду сейчас Цитата D_KEY @ Лямбдами в D просто удобней пользоваться. В D я знаю тип лямбды и могу его использовать, а в C++ у лямбды тип compiler specific, то бишь, фактически, неизвестен. std::function - имеет заметный оверхед по сравнению с лямбдами.Сейчас уже возможно особо ничем, так как вроде реализовали уже в GCC даже под вынь.Мы вроде даже на форуме выясняли, что преимуществ перед лямбдами и std::function нет. Единственная фича - сохранение захваченного контекста, а не как в C++, где захват по ссылке локальной переменной приведет к проблемам, если лямбда будет жить дольше локального фрейма. Цитата D_KEY @ Полностью согласен. Недостатком является его плохая степень опциональности. Сам по себе сборщик это хорошо, если он не вездесущий. Добавлено Фу-фу. Я в прошлом плюсовик, как ни странно. Даже фанат можно сказать. Цитата D_KEY @ Дык, интерфейсы в D - это по сути и есть плюсовый абстрактный класс, в котором все виртуальные функции - чисто виртуальные. Я могу создать переменную с типом интерфейса и хранить в ней любой объект унаследовавший данный интерфейс. Если мне нужно просто проверить наличие функций, я это сделаю без всяких интерфейсов, причем compile-time, так-то. Множественное наследование - не нужно. А не должен быть Иначе это не интерфейс, а обычный плюсовый абстрактный класс. Вот только множественного наследования в D нет ![]() |
| Автор: Wound 11.02.14, 09:05 |
| А что, тот же NetBeans никак не прикрутить? Да и IDE по мойму самая последняя проблема. В блокноте пиши ну или Far юзай |
| Автор: D_KEY 11.02.14, 09:06 |
Цитата В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> version(Windows) { ... } version(linux) { ... } Если честно, это выглядит как детский сад. Какие-то зашитые названия ОС прямо в среду. С препроцессором все совсем иначе - это обычные define'ы в системных заголовочных файлах. Цитата Версию можно задать и кастомную через аргументы командной строки, Затем проверять ее. Так чем это отличается от того, что все делают в C и C++? Цитата Цитата D_KEY @ Лямбдами в D просто удобней пользоваться. В D я знаю тип лямбды и могу его использовать, а в C++ у лямбды тип compiler specific, то бишь, фактически, неизвестен. std::function - имеет заметный оверхед по сравнению с лямбдами.Мы вроде даже на форуме выясняли, что преимуществ перед лямбдами и std::function нет. Единственная фича - сохранение захваченного контекста, а не как в C++, где захват по ссылке локальной переменной приведет к проблемам, если лямбда будет жить дольше локального фрейма. Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю? Цитата Сейчас уже возможно особо ничем, так как вроде реализовали уже в GCC даже под вынь. А раньше чем отличалось? Давно уже использовали tls на разных платформах. Да и boost::thread_specific_ptr появился очень давно. В Qt тоже есть что-нибудь на эту тему наверняка. Добавлено Так в D же есть абстрактные классы Зачем им плюсовые? Что мешало сделать интерфейсы такими же, как в других языках, где они есть? Зачем людей путать? Ради NVI? |
| Автор: applegame 11.02.14, 09:12 |
| Выбор негуст, но есть: - плагин для MSVS - VisualD; - аддон к Monodevelop - Mono-D; - IDE на базе Eclipse - DDT Добавлено Цитата D_KEY @ Ага, а потом эти заголовочные файлы надо еще правильно подключить в зависимости от ОС. Привет системам сборки а-ля make, cmake, scons - тысячи их С препроцессором все совсем иначе - это обычные define'ы в системных заголовочных файлах. Скорей это выглядит как старперский пережиток прошлого. ![]() Цитата D_KEY @ Мы забросили тесты. Там был слишком простой код, который G++ оптимизировал просто в нуль. Он это умеет, да, также как и GDC. Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю? В том что это делает "умный" компилятор, а не "тупой" препроцессор. Что позволяет, например, намного лучше диагностировать ошибки.Цитата D_KEY @ Раньше не было встроено в язык. В D, по умолчанию, все глобальные переменные - в TLS. А если рассуждать так как ты, то C++ ничем не лучше ассемблера. А что? Там тоже можно пользоваться TLS, через API OS.А раньше чем отличалось? Давно уже использовали tls на разных платформах. Да и boost::thread_specific_ptr появился очень давно. В Qt тоже есть что-нибудь на эту тему наверняка. Цитата D_KEY @ Они похожи, но таки разные вещи. В D можно наследоваться от нескольких интерфейсов, но нельзя от нескольких классов. Класс, в отличие от интерфейса, может содержать еще и данные. Так в D же есть абстрактные классы Зачем им плюсовые? Что мешало сделать интерфейсы такими же, как в других языках, где они есть? Зачем людей путать? Ради NVI? Добавлено D_KEY, ты задаешь слишком много вопросов , я не успеваю на них отвечать. Давай лучше разберем каждый аспект по очереди, не торопясь |
| Автор: D_KEY 11.02.14, 09:35 |
| Цитата applegame @ Ага, а потом эти заголовочные файлы надо еще правильно подключить в зависимости от ОС. Привет системам сборки а-ля make, cmake, scons - тысячи их ![]() Так эти задачи и должна решать система сборки В языке это смотрится как излишек. Да и всех проблем не решить заранее в языке. По схожим причинам мне не нравится зашитая в D поддержка юнит-тестов.Цитата Цитата D_KEY @ Мы забросили тесты. Там был слишком простой код, который G++ оптимизировал просто в нуль. Он это умеет, да, также как и GDC. Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю? ![]() Ну давай продолжим. Придумай тестик с демонстрацией преимуществ D. Цитата В том что это делает "умный" компилятор, а не "тупой" препроцессор. Что позволяет, например, намного лучше диагностировать ошибки. Пример? Цитата А если рассуждать так как ты, то C++ ничем не лучше ассемблера. А что? Там тоже можно пользоваться TLS, через API OS. Во-первых, API нормальных ОС описано на Си. Во-вторых, C++ высокоуровнее ассемблера а не хуже/лучше. Цитата В D можно наследоваться от нескольких интерфейсов, но нельзя от нескольких классов. Класс, в отличие от интерфейса, содержит еще и данные. Это все понятно. Не понятно, почему было не сделать интерфейсы такими, к каким привыкли люди. Цитата D_KEY, ты задаешь слишком много вопросов , я не успеваю на них отвечать. Давай более последовательно разберем каждый аспект по очереди ![]() Странно, у меня на подробных разбор одного аспекта будет времени больше уходить, чем вот так вот отвечать. "Письмо это вышло более длинным только потому, что мне некогда было написать его короче"(с) Блез Паскаль Добавлено applegame, ладно, выбирай аспект |
| Автор: applegame 11.02.14, 09:42 |
Давай про интерфейсы ![]() Цитата D_KEY @ Какие люди? К чему привыкли? Я вообще ни к чему не привыкал. В C++ интерфейсов не было, вместо них юзались абстрактные классы, в похапе я даже не помню были ли интерфейсы. Это все понятно. Не понятно, почему было не сделать интерфейсы такими, к каким привыкли люди. На форуме D кстати этот вопрос поднимался. Одна из причин - отсутствие множественного наследования. Интерфейсы могут помочь, когда такое наследование необходимо. |
| Автор: OpenGL 11.02.14, 09:42 |
| В плюсах-то как раз понятно - там в качестве интерфейсов используются абстрактные классы, не являющиеся интерфейсами. Поэтому плюсовое поведение в данном случае вполне логично. Реализация тоже есть же - в базовом классе. Видел для студии соответствующий плагин Visual D называется.Цитата applegame @ Дык, интерфейсы в D - это по сути и есть плюсовый абстрактный класс, в котором все виртуальные функции - чисто виртуальные. Странное решение. Интерфейс показывает, грубо говоря - "что экземпляр класса умеет делать", а наследование - "кем является объект этого класса". Первое связано со вторым, но им, очевидно, не является. Добавлено Люди, пишущие на языках, где есть интерфейсы, привыкли пользоваться ими как интерфейсами, а не как абстрактными классами ![]() Кстати, ЕМНИП, Qraizer как-то выкладывал код, где множественное наследование было в тему, и интерфейсами нельзя было обойтись |
| Автор: applegame 11.02.14, 09:46 |
| Насчет плюсов встроенных ассоциативных массивов. Мне достаточно того, что вместо <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> я пишуstd::unordered_map<int, std::string> var; <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> string[int] var; |
| Автор: D_KEY 11.02.14, 09:47 |
| Программисты, использующие языки, в которых есть интерфейсы. Привыкли к тому, что описал OpenGL. Цитата На форуме D кстати этот вопрос поднимался. Одна из причин - отсутствие множественного наследования. Интерфейсы могут помочь, когда такое наследование необходимо. Это причина для добавления в язык интерфейсов, да. Так поступили в Java и в C#. Правда scala показала немного другой путь с trait'ами, но это к делу не относится. Но зачем же наделять интерфейсы свойствами абстрактных базовых классов? Так, пожалуй, их проще реализовать. Но это не аргумент. |
| Автор: OpenGL 11.02.14, 09:48 |
| Кстати, да - объявление массивов в D мне нравится Очень удобно и однотипно объявляются статические, динамические и ассоциативные массивы. |
| Автор: D_KEY 11.02.14, 09:49 |
| Цитата applegame @ Насчет плюсов встроенных ассоциативных массивов. Мне достаточно того, что вместо <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> я пишуstd::unordered_map<int, std::string> var; <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> string[int] var; А я typedef'ы использую. В D бы тоже использовал. Добавлено Кстати, мне попадался на глаза какой-то фичебаг с alias'ами в D... Вспомнить бы... |
| Автор: applegame 11.02.14, 09:51 |
| Цитата OpenGL @ Интерфейс в D - в целом то же самое. Но со своими особенностями. Я не знаю, является ли в C# интерфейс отдельным типом? Можно ли там создать переменную с типом интерфейса? Странное решение. Интерфейс показывает, грубо говоря - "что экземпляр класса умеет делать", а наследование - "кем является объект этого класса". Первое связано со вторым, но им, очевидно, не является. Добавлено Зачем? string[int] выглядит очень наглядно и понятно. |
| Автор: OpenGL 11.02.14, 10:01 |
| Создать где? В шарпе вроде как в интерфейсах вообще полей не можкт быть - только методы. А если ты имеешь ввиду IFoo tmp = new Derived(), то да, конечно. |
| Автор: applegame 11.02.14, 10:05 |
| Цитата D_KEY @ Можно попытаться ответить на этот вопрос. Рассмотрим код:Но зачем же наделять интерфейсы свойствами абстрактных базовых классов? Так, пожалуй, их проще реализовать. Но это не аргумент. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Функция IFoo.g() - фактически виртуальная функция. Класс Base вообще ничего не знает об IFoo и Base.g() вообще может быть реализована в стороннем модуле чужим дядей. Ну и как компилятор должен выкручиваться из такой ситуации? Автоматически создать в Derived виртуальную функцию g(), в которой автоматически же вставить вызов базовой функции из Base? interface IFoo { void g(); } class Base { void g(); } class Derived : Base, IFoo { } ... IFoo b = new Derived; b.g(); Добавлено Да, я это имел ввиду. Но смотри выше. |
| Автор: OpenGL 11.02.14, 10:08 |
| Выдать ошибку компиляции Ты же не указал, что Derived реализует IFoo. |
| Автор: D_KEY 11.02.14, 10:08 |
| Кажется, вспомнил. alias как-то странно работает с ref. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> foreach (ref int x; arr) не тоже самое, что <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> alias ref int ref_int; foreach (ref_int x; arr) http://ideone.com/zbUG0A При этом ref является частью типа функции, например. |
| Автор: applegame 11.02.14, 10:13 |
Я уже поправил Добавлено Ситуация со ссылками в D мне тоже не нравится. ref почему-то не является частью типа. Например, нельзя создать переменную-ссылку. Не знаю зачем так сделали, но мне не мешает. |
| Автор: D_KEY 11.02.14, 10:43 |
| Цитата applegame @ Ситуация со ссылками в D мне тоже не нравится. ref почему-то не является частью типа. Например, нельзя создать переменную-ссылку. Не знаю зачем так сделали, но мне не мешает. Так а чего он не ругается на alias с ref, а просто делает какую-то фигню? И почему ref является частью типа возвращаемого значения? |
| Автор: applegame 11.02.14, 10:49 |
| А почему фигню? "alias ref int ref_int;" полностью аналогичен "alias int ref_int;" сейчас уже, кстати можно писать "alias ref_int = int;". Нет, не является. Скорее это некий флажок для компилятора. Если функция возвращает ссылку и ты ее присвоишь переменной с типом auto, то будет создана обычная переменная, а не ссылка. Но вообще, я согласен с тобой, и в свое время задавал аналогичные вопросы на оффоруме. Там сказали, что-то вроде - ну вот так сделано. ref также не являясь частью типа умудряется все же быть частью сигнатуры функции ![]() С другой стороны, как я уже сказал, это не мешает и представляет скорее академический интерес, чем практический. Окай. Перейду к другой части мерлезонского балета. А именно, возможность использовать строковые литералы (и вообще любые строки вычисляемые compile-time) в шаблонах. В качестве стратегий: http://dpaste.dzfl.pl/adb455e76a45 В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26 Добавлено На всякий случай сообщаю, что <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> примерно как (хотя в C++ это невозможно)class Container(string type) { } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<string type> class Container { }; |
| Автор: D_KEY 11.02.14, 10:56 |
Чего окай-то? мне вот подобных косяков со ссылками и интерфейсами уже достаточно. Наверняка там ещё есть |
| Автор: applegame 11.02.14, 11:01 |
Ну а что дальше? Этот вопрос рассмотрен и закрыт или у тебя еще есть вопросы? Кстати ты не ответил на пост про интерфейсы.Цитата D_KEY @ С интерфейсами - это не косяк. Если ты к чему-то привык, то это не значит, что так и должно быть. В каждом языке свои особенности.мне вот подобных косяков со ссылками и интерфейсами уже достаточно. Наверняка там ещё есть ![]() Что касается других косяков, то там их достаточно. Но тем не менее, почему-то меня не тянет назад на плюсы. |
| Автор: applegame 11.02.14, 11:13 |
| Далее, обещаный compile-time reflection, шаблонная функция printMembers печатает имена и значения членов структуры, переданной в качестве аргумента. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.stdio; struct Foo { int i; string s; float f; } void printMembers(T)(T t) { foreach(identifier; __traits(allMembers, T)) { writefln("%s = %s", identifier, mixin("t." ~ identifier)); } } void main() { Foo f = Foo(1, "test", 0.5); printMembers(f); } результат - http://dpaste.dzfl.pl/be97ba78d54f Добавлено Цитата D_KEY @ Кстати, не согласен с этим категорически. Приведи пример проблемы, которая решается включением/выключением/заменой куска исходников, и которую нельзя решить способом предлагаемым в D, но можно системой сборки. Так эти задачи и должна решать система сборки В языке это смотрится как излишек. Да и всех проблем не решить заранее в языке. |
| Автор: trainer 11.02.14, 11:35 |
| является. interface - ключевое слово Это ссылка. Почему нет? Добавлено Цитата applegame @ Так и препроцессор в C/C++ встроен в язык. В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык |
| Автор: applegame 11.02.14, 11:46 |
Ну и как при помощи только лишь препроцессора узнать тип ОС? |
| Автор: MyNameIsIgor 11.02.14, 11:47 |
| Никаких преимуществ перед библиотечными, одни минусы: ни хэш не задать, ни аллокатор. Чем он так идеален, что в мире плюсов нет ничего похожего? Эти !() просто ужасны и нечитаемы. Следовало идти по пути Scala. И да, что такое "мощный синтаксис" - моя не понимайт. Костыль при отсутствии множественного наследования. Цитата applegame @ отсуствие необходимости в заголовочных файлах (это свобода, вы плюсовики, просто не знаете как это прекрасно) Пишу на C#, Java, C++, Objective-C - я люблю заголовочные файлы. ЧЯДНТ? Цитата applegame @ Настоящая условная компиляция в зависимости от ключей в командной строке, процессора, кода, версии и т.п. Препроцессор не менее настоящий. Но то, что static if - часть языка, что плюс, да. Цитата applegame @ настоящий CTFE, вплоть до compile-time импорта в строку и парсинга файла в код на D Парсинг из строки - это убожество. Александреску преподносит это как манну небесную, но мне абсолютно непонятно для чего использовать строки, если нужно записывать код - должна быть нормальная возможность описать AST в стандартном синтаксисе языка, как это сделано в макросах Nemerle. Как и было доказано, они не нужны. Цитата applegame @ нормальные лямбды, тип которых зависит напрямую от сигнатуры, а не как компилятор на душу положит. Кроме того имеется прекрасный сокращенный стиль их написания Т.е. встроенная в язык std::function, но опять таки без возможности параметризации аллокатором. А т.к. тип зависит только от сигнатуры, то прощай тотальное встраивание. Не нужно. Есть и в C++11. Другое дело, что в D надо наоборот указывать тот факт, что переменная глобальная - в этом плюс есть, да. Полезно. Вроде как обсуждается к C++17. Он не то, что не самый продвинутый...Он самый убогий Потому что для такого языка возможен лишь консервативный сборщик. Сейчас используется boehmgc... который вообще-то для C/C++ ![]() А в итоге в D наличие сборщика привёло к большой путанице с деструкторами и переопределёнными new/delete - это fail. Вообще, D протух ещё до выхода. Когда-то давно я тоже в него верил, но потом разочаровался и понял: D - это говно, очень вонючее говно. Многие из тех, то его тогда поддерживал, сейчас смотрят на Rust или Go. D_KEY, помнишь, ты даже хотел на форуме подраздел создать, чтобы обсудить D? Посмотрел по личным сообщения - 2009 год был ![]() Ну, и правильные посты про D. |
| Автор: trainer 11.02.14, 11:53 |
| Вот так: http://msdn.microsoft.com/en-us/library/b0084kay.aspx http://gcc.gnu.org/onlinedocs/cpp/System-s...edefined-Macros |
| Автор: D_KEY 11.02.14, 11:56 |
| Как оно, кстати? |
| Автор: MyNameIsIgor 11.02.14, 11:57 |
| Кстати, нормально. Не хуже D |
| Автор: D_KEY 11.02.14, 11:58 |
| Цитата MyNameIsIgor @ D_KEY, помнишь, ты даже хотел на форуме подраздел создать, чтобы обсудить D? Посмотрел по личным сообщения - 2009 год был ![]() Ага Цитата Многие из тех, то его тогда поддерживал, сейчас смотрят на Rust или Go. Но и они что-то не очень радуют. Добавлено Пропустил, наверное. Ты о чем? Добавлено А тебя никто и не тянет |
| Автор: applegame 11.02.14, 12:07 |
| Кстати, дела идут гораздо лучше, чем год назад и D стремительно обрастает библиотеками: http://code.dlang.org/ Я пытался несколько раз переползти с C++ на D и каждый раз неудачно: плюясь и ругаясь возвращался к плюсам. Но вот последний раз наконец-то D достиг устраивающего меня уровня. Я не отношусь к тем адептам, которые загорелись, а через неделю прогорели и все забросили. Я уже практически полгода пилю относительно большой коммерческий веб-проект (заодно по мере возможности участвую в разработке vibe.d), с относительно высокой посещаемостью (первая версия работает прямо сейчас на рубях). Как только я его закончу, обязательно покажу. Будет вам саксесс-стори. |
| Автор: MyNameIsIgor 11.02.14, 12:13 |
| Так это вам не с C++ надо будет тягаться, а со всякими Python/Ruby/C#/Scala/Clojure/Go. Вот им и расскажете про успех, а плюсы на веб не претендуют. |
| Автор: D_KEY 11.02.14, 12:14 |
| Что-то "убийцы" С++ в вебе применяются, с Go та же история. |
| Автор: MyNameIsIgor 11.02.14, 12:24 |
| Ну, именно поэтому ты и написал в кавычках |
| Автор: korvin 11.02.14, 12:27 |
| Цитата applegame @ В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык: Лучше бы сделали как в Go -- суффикс в имени файла, перед расширением, например: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> % ls package package_linux.go package_windows.go package_darwin.go common.go ... И грепать содержимое кучи сырцов не надо, чтобы найти весь платформозависимый код. |
| Автор: applegame 11.02.14, 12:28 |
| Это будет моя саксесс-стори. А вообще D используют такие гиганты геймдева, как Remedy Games. Не как основной, а вспомогательный для обработки игровой логики. Вот, презентация одного из разработчиков об этом: http://www.youtube.com/watch?v=FKceA691Wcg |
| Автор: D_KEY 11.02.14, 12:29 |
| А если у меня зависимость от версии ОС, архитектуры, конкретной POSIX'овой или SUS-константы? |
| Автор: applegame 11.02.14, 12:31 |
| Никто не мешает разбить код на отдельные модули для каждой платформы, а затем при помощи version импортировать уже нужные части в зависимости от платформы сборки. |
| Автор: MyNameIsIgor 11.02.14, 12:34 |
| Цитата applegame @ А вообще D используют такие гиганты геймдева, как Remedy Games. Не как основной, а вспомогательный для обработки игровой логики В геймдеве вообще проблемы с тем, на чём пилить игровую логику. А причина проста - нет строго статически типизированного языка, который был бы столь же выразителен, как сриптовые динамические, кроссплатформенный и при этом легко встраивался в приложение. К C++ сей "успех" не имеет никакого отношения. |
| Автор: applegame 11.02.14, 12:39 |
| Цитата D_KEY @ Архитектуру тоже можно определить через version. А версия ОС, во время сборки? Спрашивается нафига? А если у меня зависимость от версии ОС, архитектуры, конкретной POSIX'овой или SUS-константы? |
| Автор: OpenGL 11.02.14, 12:42 |
| Цитата MyNameIsIgor @ А в итоге в D наличие сборщика привёло к большой путанице с деструкторами и переопределёнными new/delete - это fail. Кстати, что с ними в D? Считал, что там есть нормальные деструкторы как в плюсах. Это неверно? |
| Автор: D_KEY 11.02.14, 12:43 |
| Внезапно, в разных версиях могут быть разные API(если мы о винде) или разная степень и подход к реализации стандартов(если мы о *nix). |
| Автор: applegame 11.02.14, 12:44 |
| Цитата OpenGL @ Неверно. Деструкторы есть, но используются они гораздо реже, чем в C++. Кстати, что с ними в D? Считал, что там есть нормальные деструкторы как в плюсах. Это неверно? |
| Автор: korvin 11.02.14, 12:46 |
| Цитата applegame @ Никто не мешает разбить код на отдельные модули для каждой платформы, а затем при помощи version импортировать уже нужные части в зависимости от платформы сборки. Ну т.е. в итоге получится тоже самое, что и в Go, только с добавочным костылем в языке, ОК. Цитата D_KEY @ А если у меня зависимость от версии ОС, архитектуры, конкретной POSIX'овой или SUS-константы? Если у тебя какие-то сложные правила сборки, то ты всегда можешь воспользоваться make. В большинстве случаев этого достаточно: http://golang.org/pkg/go/build/ Кстати, что за POSIX/SUS-константы? |
| Автор: MyNameIsIgor 11.02.14, 12:47 |
| Цитата OpenGL @ Кстати, что с ними в D? Считал, что там есть нормальные деструкторы как в плюсах. Это неверно? Есть там деструкторы, но классические плюсовые деструкторы с GC не уживаются, ибо он недетерминирован. Я когда книжку читал, был разочарован. Сейчас уже забыл за ненадобность. Могу потом написать, когда добирусь до дома и открою книгу. Или вон D_KEY может вспомнить - он тоже читал. |
| Автор: applegame 11.02.14, 12:50 |
| Цитата D_KEY @ Внезапно, версия ОС важна для системы, на которой запускается проект, а не на которой собирается, а значит это не может входит в задачи ни системы сборки, ни компилятора. Это параметры задаваемые вручную при помощи соответствующих ключей.Внезапно, в разных версиях могут быть разные API(если мы о винде) или разная степень и подход к реализации стандартов(если мы о *nix). Задача системы сборки проверять наличие нужных библиотек и модулей, а не сообщать исходному коду тип платформы, так как тип платформы всегда известен компилятору. Добавлено Цитата korvin @ Это смотря с какой стороны смотреть. С одной стороны костыль, с другой стороны гибкость. Кроме того version позволяет условно компилять не только в зависимости от платформы, но и как классический #ifdef в зависимости от аргументов командной строки, или в зависимости от режима debug/release и т.п. Ну т.е. в итоге получится тоже самое, что и в Go, только с добавочным костылем в языке, ОК. Добавлено Для объектов созданных с помощью new (читай классов) деструкторы практически бесполезны, так как действительно не детерминированы, то бишь вызываются, когда приспичит GC, причем в одному ему ведомом порядке. Для объектов создаваемых на стеке (читай структур) деструкторы детерминированы и работают аналогично плюсовым. Поэтому на базе структуры можно создать аналог shared_ptr, который будет вызывать деструктор уже вполне детерминировано. |
| Автор: korvin 11.02.14, 13:11 |
| Цитата applegame @ зависимости от платформы, но и как классический #ifdef в зависимости от аргументов командной строки, или в зависимости от режима debug/release и т.п. Да-да, и снова греп и каша в сорцах... =) |
| Автор: D_KEY 11.02.14, 13:14 |
| Цитата applegame @ Внезапно, версия ОС важна для системы, на которой запускается проект, а не на которой собирается, а значит это не может входит в задачи ни системы сборки, ни компилятора. Внезапно, это зависит от проекта. Да и от политики установки программ в ОС. Скажем, порты во FreeBSD собирают софт перед установкой Добавлено Цитата applegame @ а значит это не может входит в задачи ни системы сборки, ни компилятора. Это параметры задаваемые вручную при помощи соответствующих ключей. Нет, спасибо. Я предпочитаю автоматизацию. Даже разворачивать систему автоматически, при помощи того же ansible, например. Может и это в язык сунуть? |
| Автор: applegame 11.02.14, 13:19 |
А как по другому? Отдельные файлы с исходниками для дебаг-версии, отдельно для релиз? |
| Автор: MyNameIsIgor 11.02.14, 13:19 |
| Согласен, кстати. Воюю со всеми, в том числе и с коллегами, пытаясь объяснить, что это всё - задача системы сборки и не должно быть с исходниках. Они же должны быть разложены по директориям, а вместо #ifdef должны использоваться либо порождающие паттерны, либо языковые механизмы типа одного .h и по .cpp на конкретную реализацию. Война проигрывается |
| Автор: applegame 11.02.14, 13:20 |
| Вообще в D вставлено ровно две вещи: тип OS и архитектура, остальное внешними ключами. |
| Автор: MyNameIsIgor 11.02.14, 13:21 |
| Вот, ещё один... А у вас разный код исполняется в debug и в realese? Тогда тестирование debug версии не имеет смысла - у клиента будет работать другой код. |
| Автор: applegame 11.02.14, 13:23 |
| В релиз версии не выполняются некоторые проверки, которые делаются в дебаг-версии. Так что код, да, слегка различается. Добавлено Продолжаем тему используемости D. Вот эта контора - http://www.funatics.de/en/ делающая, насколько я понял браузерные MMO игры, начала миграцию игрового бэкенда с NodeJS на D. |
| Автор: korvin 11.02.14, 13:28 |
| Цитата applegame @ В релиз версии не выполняются некоторые проверки, которые делаются в дебаг-версии. Так что код, да, слегка различается. Сколько видел библиотек и программ, они все позволяют запускать себя в режиме отладки, дабы, если у пользователя возникнет проблема, он мог ее понятней описать разработчику/мейнтейнеру. Т.е. необходимость этих проверок определяется в рантайме и остается в "релизной" версии. |
| Автор: MyNameIsIgor 11.02.14, 13:30 |
| Цитата applegame @ В релиз версии не выполняются некоторые проверки, которые делаются в дебаг-версии. Контракты - особая тема. Но и в этом случае условная компиляция должна быть скрыта от программиста. Если проверки не относятся к контрактам, то они должны быть одинаковыми. |
| Автор: korvin 11.02.14, 13:32 |
| Не удивительно, с NodeJS грех не мигрировать. При этом практически не важно на что. Даже Ryan Dahl ненавидит NodeJS. =) |
| Автор: applegame 11.02.14, 13:36 |
| Цитата korvin @ Да ну? Много ли скажем игр с такой возможностью? Для этих целей сама программа делает краш-репорт. Из релизной версии могут выпиливаться контракты, юниттесты (которые опять же могут лежать в отдельных файлах) или другие проверки. Которые не считаются необходимыми в релизной версии, для которой важна максимальная производительность. Сколько видел библиотек и программ, они все позволяют запускать себя в режиме отладки, дабы, если у пользователя возникнет проблема, он мог ее понятней описать разработчику/мейнтейнеру. Т.е. необходимость этих проверок определяется в рантайме и остается в "релизной" версии. |
| Автор: korvin 11.02.14, 13:43 |
| Цитата applegame @ Из релизной версии могут выпиливаться контракты, юниттесты (которые опять же могут лежать в отдельных файлах) или другие проверки. Про контракты уже Игорь сказал, юнит-тесты всегда идут отдельно. О каких других проверках речь? Опять же, если от софта требуется надежность, то проверки придется оставлять, если не требуется, то зачем вообще тратить на них время? |
| Автор: D_KEY 11.02.14, 13:43 |
| Цитата MyNameIsIgor @ Они же должны быть разложены по директориям, а вместо #ifdef должны использоваться либо порождающие паттерны, либо языковые механизмы типа одного .h и по .cpp на конкретную реализацию. Хм. Не очень себе это представляю в header only библиотеке, например. |
| Автор: MyNameIsIgor 11.02.14, 13:45 |
| Настройка путей include'а. |
| Автор: D_KEY 11.02.14, 13:47 |
| В системе сборки? Ну можно, в принципе, да. Но это придется делать каждому пользователю библиотеки. |
| Автор: applegame 11.02.14, 13:48 |
| Далее. Sociomatic Labs специализируется на, хз как это перевести - real-time bidding for online display advertising. Вся их кодовая база написана на D. Правда, справедливости ради, надо отметить что на D1/Tango. |
| Автор: korvin 11.02.14, 13:50 |
| Почему же? Система сборки не может определить текущую ОС и архитектуру? |
| Автор: applegame 11.02.14, 13:53 |
| EMSI компания занимающаяся моделированием экономики. На D написана высокопроизводительный экономический симулятор и некоторый инструментарий. На данный момент продолжают мигрировать на D и планируют полностью перейти на него. |
| Автор: MyNameIsIgor 11.02.14, 13:54 |
| Как определили, что он высоко производительный? |
| Автор: D_KEY 11.02.14, 13:55 |
| Ну да, в принципе, можно именно полностью управлять точным набором хидеров и ставить только их, если ты об этом. И для текущей ОС и архитектуры это не будет большой проблемой, но вот всякие флаги компиляции и конфигурации(boost.config например)... В общем случае, как мне кажется, это не сделать. Но во многом я с вами согласен. Добавлено Торги реального времени для показа рекламы Это известная шляпа, система для проведения аукциона между рекламными сетями. |
| Автор: applegame 11.02.14, 14:03 |
Эй, не отклоняемся от темы. |
| Автор: MyNameIsIgor 11.02.14, 14:05 |
| Да, в общем случае для плюсовых header only библиотек этого не сделать. Но даже если #ifdef будет только вокруг #include, будет уже хорошо. Добавлено А в чём состоит тема? Чтобы показать в лучшем случае несколько десятков проектов на D против стопитсот проектов на C++? |
| Автор: Wound 11.02.14, 14:08 |
| Ой как меня тоже бесят, как некоторые любят кучу дефайнов трехэтажных намудрить, а потом когда все это глючит, охото найти и оторвать руки писавшему... |
| Автор: applegame 11.02.14, 14:08 |
| D так устроен, что для небольших проектов можно легко обойтись без системы сборки вообще. В D встроен JIT компилятор, так что скрипт занимающийся сборкой может быть на самом D. Это часто очень удобно. В линупсе просто стартуем скрипт, в Windows стартуем через rdmd. |
| Автор: MyNameIsIgor 11.02.14, 14:10 |
| Цитата applegame @ D так устроен, что для небольших проектов можно легко обойтись без системы сборки вообще. Неинтересно. Для небольших проектов хоть Brainfuck прокатит. |
| Автор: applegame 11.02.14, 14:13 |
А некоторые еще любят замутить такие вложенные замороченные макросы, что потом когда вылезает ошибка компиляции, приходится мучительно искать, где-же именно это говно вылезло. Ведь компилер бодренько показывает строку в которой макрос был задействован. Это к вопросу D_KEY, почему макросы говно. А потому, что препроцессор - тупой, а компилятор - умный. Поэтому замена препроцессора компилятором - отличная идея. Но упоротые "старики" будут гнуть свое, хотя практически все учебники по C++ говорят одно и тоже: макросы - зло. |
| Автор: D_KEY 11.02.14, 14:17 |
| Цитата applegame @ А некоторые еще любят замутить такие вложенные замороченные макросы, что потом когда вылезает ошибка компиляции, приходится мучительно искать, где-же именно это говно вылезло. Ведь компилер бодренько показывает строку в которой макрос был задействован. Это к вопросу D_KEY, почему макросы говно. А потому, что препроцессор - тупой, а компилятор - умный. Поэтому замена препроцессора компилятором - отличная идея. Но упоротые "старики" будут гнуть свое, хотя практически все учебники по C++ говорят одно и тоже: макросы - зло. ![]() Совсем этим я согласен как раз. Мы тогда говорили о выигрыше при переходе с C++ на D. |
| Автор: Wound 11.02.14, 14:18 |
| Цитата applegame @ А некоторые еще любят замутить такие вложенные замороченные макросы, что потом когда вылезает ошибка компиляции, приходится мучительно искать, где-же именно это говно вылезло. Ведь компилер бодренько показывает строку в которой макрос был задействован. Это к вопросу D_KEY, почему макросы говно. А потому, что препроцессор - тупой, а компилятор - умный. Поэтому замена препроцессора компилятором - отличная идея. Но упоротые "старики" будут гнуть свое, хотя практически все учебники по C++ говорят одно и тоже: макросы - зло. Макросы зло - когда ими злоупотребляют. Когда их используют вместо банальных констант, когда ими пытаются выражение на 5 строчек реализовать макросом в одну строчку, странно почему не функцией и т.д. А так то макросы сами по себе нормальные. Просто есть макрофанаты отдельные... |
| Автор: applegame 11.02.14, 14:18 |
| Сами пишите на Brainfuck. А мелкие вспомогательные тулзины крутятся вокруг любого крупного проекта. |
| Автор: D_KEY 11.02.14, 14:19 |
| Так они на каких-нибудь питонах, как правило. |
| Автор: Wound 11.02.14, 14:22 |
| applegame, вот ты там писал гдето про GC и деструкторы, мол для структор что на стэке - обычные деструкторы, а в остальном GC. А как эта солянка вместе работает? Вот например что там в плане исключений? finally какие нибудь писать нужно? или как? |
| Автор: MyNameIsIgor 11.02.14, 14:23 |
| +1 Есть куча языков, на которых можно сделать мелкие тулзы, и языки эти знает куча народу. Зачем мне D? |
| Автор: applegame 11.02.14, 14:23 |
| Цитата Wound @ Да, но самое интересное, что главное преимущество препроцессора - это как раз городить костыли, которые нормальным способом не сделать. Например Boost.Foreach. В остальных случаях он не нужен при достаточной поддержке языка. В том же D, например. Макросы зло - когда ими злоупотребляют. Когда их используют вместо банальных констант, когда ими пытаются выражение на 5 строчек реализовать макросом в одну строчку, странно почему не функцией и т.д. А так то макросы сами по себе нормальные. Просто есть макрофанаты отдельные... |
| Автор: applegame 11.02.14, 14:32 |
| Я не знаю питона и изучать его нет никакого желания. Я использую D. Цитата Wound @ Все нормально работает. finally - в D нет и он там не нужен. При выходе из scope деструктор для структуры вызовется автоматически, как и в плюсах. Но, если нужно, то можно мутить какие-то особые правила при выходе из scope:applegame, вот ты там писал гдето про GC и деструкторы, мол для структор что на стэке - обычные деструкторы, а в остальном GC. А как эта солянка вместе работает? Вот например что там в плане исключений? finally какие нибудь писать нужно? или как? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(void) { scope(exit) writeln("это выполнится при любом выходе из scope (в данном случае - функции)"); scope(success) writeln("это выполнится только при выходе без исключений"); scope(failure) writeln("это выполнится только при выходе по исключению"); try { ... } catch(Exception e) { ... } } |
| Автор: Wound 11.02.14, 14:37 |
| Да его изучать и не приходится както, просто берешь и пишешь как тебе нравится и все )) |
| Автор: MyNameIsIgor 11.02.14, 14:38 |
| Лолшто? Цитата TryStatement: try ScopeStatement Catches try ScopeStatement Catches FinallyStatement try ScopeStatement FinallyStatement Catches: LastCatch Catch Catch Catches LastCatch: catch NoScopeNonEmptyStatement Catch: catch ( CatchParameter ) NoScopeNonEmptyStatement CatchParameter: BasicType Identifier FinallyStatement: finally NoScopeNonEmptyStatement Ага, не нужен. Но в D нет общей идеи, это просто бессистемный набор фич. |
| Автор: D_KEY 11.02.14, 14:39 |
| Есть |
| Автор: applegame 11.02.14, 14:39 |
| Цитата Wound @ Как нравится не получится. Я однажды писал маленький плагин для Blender. Нужно было импортировать/экспортировать модельки для игры. Так вот помучался немного. Написал в итоге, но язык не понравился. Да его изучать и не приходится както, просто берешь и пишешь как тебе нравится и все )) |
| Автор: D_KEY 11.02.14, 14:41 |
| Цитата applegame @ При выходе из scope деструктор для структуры вызовется автоматически, как и в плюсах. Но, если нужно, то можно мутить какие-то особые правила при выходе из scope: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(void) { scope(exit) writeln("это выполнится при любом выходе из scope (в данном случае - функции)"); scope(success) writeln("это выполнится только при выходе без исключений"); scope(failure) writeln("это выполнится только при выходе по исключению"); try { ... } catch(Exception e) { ... } } Кстати, мне кажется, что D очень удобен для холиваров. Можно мимикрировать под разные языки. |
| Автор: applegame 11.02.14, 14:41 |
Да, ты прав, есть. Я был уверен, что нет |
| Автор: D_KEY 11.02.14, 14:43 |
| Не нужен, но есть. Прямо как сам D. |
| Автор: applegame 11.02.14, 14:44 |
| Цитата D_KEY @ Холивара не получается. Всем насрать хорош или плох C++, всем важно насколько плох D. Кстати, мне кажется, что D очень удобен для холиваров. Можно мимикрировать под разные языки. ![]() Я привел два примера в чем D однозначно переплюнул C++, но всем пофиг. |
| Автор: Wound 11.02.14, 14:44 |
| Вызовутся ли эти деструкторы в случае, если сработает GC и/или вызовется ли GC при выходе из этих scope'ов 146% ? Цитата applegame @ <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> scope(exit) writeln("это выполнится при любом выходе из scope (в данном случае - функции)"); scope(success) writeln("это выполнится только при выходе без исключений"); scope(failure) writeln("это выполнится только при выходе по исключению"); |
| Автор: D_KEY 11.02.14, 14:45 |
| Цитата applegame @ Цитата D_KEY @ Холивара не получается. Всем насрать хорош или плох C++, всем важно насколько плох D. Кстати, мне кажется, что D очень удобен для холиваров. Можно мимикрировать под разные языки. ![]() Так ты с первого сообщения оборонительную позицию занял. Чего ты ждал? |
| Автор: MyNameIsIgor 11.02.14, 14:45 |
| Эммм... Где? |
| Автор: D_KEY 11.02.14, 14:46 |
| Про строки в параметрах шаблонов тебя спросили зачем, а рефлексия во время компиляции вроде как все нравится. Проблема в том, что она легко может появиться в C++ |
| Автор: applegame 11.02.14, 14:48 |
| Цитата Wound @ GC не занимается объектами на стеке. Для них вызовутся 146%. Для объектов созданных при помощи new, нет. Они будут жить и после выхода из функции как минимум до тех пор пока в программе есть ссылки на них. После того как все ссылки исчезли, деструктор вызовется, когда GC соблагоизволит прибить данный объект. Это может случиться когда угодно. Поэтому деструктор для классов, как правило бесполезен. Вызовутся ли эти деструкторы в случае, если сработает GC и/или вызовется ли GC при выходе из этих scope'ов 146% ? |
| Автор: D_KEY 11.02.14, 14:48 |
| И да, ты мне там писал, что я не ответил про интерфейсы, а я не нашел. |
| Автор: korvin 11.02.14, 14:49 |
| Наверное на любом языке можно привести пару примеров, в чем этот язык переплюнет плюсы, так что не очень интересно. Вот если бы D хотя бы в половине случаев однозначно переплевывал плюсы, было бы интересней. =) |
| Автор: applegame 11.02.14, 14:50 |
| Я там привел, два примера, повторю: В качестве стратегий: http://dpaste.dzfl.pl/adb455e76a45 В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26 В реальной жизни, это может быть все что угодно, названием функции или просто тэгом. В C++ для этого юзают классы-пустышки, что является ничем иным, как костылем. |
| Автор: korvin 11.02.14, 14:51 |
| Цитата applegame @ После того как все ссылки исчезли, деструктор вызовется, когда GC соблагоизволит прибить данный объект. Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы? |
| Автор: Wound 11.02.14, 14:53 |
| Цитата applegame @ Как нравится не получится. Я однажды писал маленький плагин для Blender. Нужно было импортировать/экспортировать модельки для игры. Так вот помучался немного. Написал в итоге, но язык не понравился. На питоне и мучился? )) Или на чем? Я писал на С++ плагин ждя 3DMax Studio, который экспортирует модель из 3DMax в мой собственный формат, который я даже сам придумал как мне в голову пришло, и даже на С++ не долго мучился, а в питоне, так там и мучится не нужно. Там же выбирай что хочешь, списки, кортежи, массивы, мапы и т.д. какое там мучение и в каком месте то? |
| Автор: MyNameIsIgor 11.02.14, 14:54 |
| Помимо того, что запись кода в строковом литерале этого же языка для парсинга compile-time - это убожество, есть следующие вопросы Чем это лучше задания типа-стратегии? Чем это лучше просто передачи функтора в find? Добавлено Цитата korvin @ Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы? Потому что для D возможен лишь консервативный сборщик. |
| Автор: applegame 11.02.14, 14:55 |
| Цитата korvin @ Он в большинстве случаев не хуже, а во многом лучше. Я поставлю пару простых задач, тут сидят плюсовики посмотрим, как они их решат, на C++. И сравним, какое решение изящней.Вот если бы D хотя бы в половине случаев однозначно переплевывал плюсы, было бы интересней. =) Цитата korvin @ Зачем и куда копировать достижимые ресурсы? Сразу предупреждаю, я не очень большой специалист в алгоритмах работы GC. Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы? |
| Автор: MyNameIsIgor 11.02.14, 14:56 |
| Как минимум сдвигать для борьбы с фрагментацией. |
| Автор: korvin 11.02.14, 14:57 |
| Как-то странно смотреть на это строко-ковыряние при наличии compile-time рефлексии и «значительно более мощных возможностей метапрограммирования». Разработчики D фанаты тикля что ли? |
| Автор: applegame 11.02.14, 14:59 |
| Есть два проекта более продвинутых сборщиков для D:A Precise Garbage Collector for DConcurrent Garbage Collection for DНе знаю, являются ли они консервативными, но более продвинутыми точно. |
| Автор: korvin 11.02.14, 15:02 |
| Вообще-то в плюсах теперь, как и во всех нормальных языках для этого используются лямбды теперь. Ты вот скажи, то строковое выражение что, компилируется в рантайме? Или как оно работает? Цитата applegame @ Зачем и куда копировать достижимые ресурсы? Сразу предупреждаю, я не очень большой специалист в алгоритмах работы GC. Это основа работы практически всех (полноценных) GC: http://en.wikipedia.org/wiki/Garbage_colle..._vs._non-moving |
| Автор: D_KEY 11.02.14, 15:04 |
| Ну это не стратегия, а имя стратегии. В плюсах можно использовать типы-теги, например или еще что-то такое. Цитата В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26 В сложных случаях будет запутано(и вообще интуитивно мне кажется это очень странной фичей), в обычных можно сделать на шаблонах и constexpr. |
| Автор: korvin 11.02.14, 15:07 |
| Реализацию метода find(!) покажи. |
| Автор: D_KEY 11.02.14, 15:08 |
| Цитата korvin @ Цитата applegame @ После того как все ссылки исчезли, деструктор вызовется, когда GC соблагоизволит прибить данный объект. Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы? Копировать сборщик в D не умеет. Но вот вызов деструктора(если он есть) таки приходится как-то делать при любом сборщике. Это та же история(почти), что и с финализаторами в явашарпах. |
| Автор: applegame 11.02.14, 15:21 |
| Цитата korvin @ Да, оно компиляется, только компиле-тайм, а не рантайм в лямбду-предикат. Эдакий синтаксический сахарок, для простеньких предикатов. Но можно пихать, естественно и функторы и лямбды. Ты вот скажи, то строковое выражение что, компилируется в рантайме? Или как оно работает? |
| Автор: MyNameIsIgor 11.02.14, 15:23 |
| korvin, как ты считаешь, нужно ли такой "сахарок", прости за выражение, сделать в CL: будем парсить sexp прямо из строки? |
| Автор: applegame 11.02.14, 15:24 |
| Итак, господа. Первая простейшая задача. Написать функцию-шаблон isOneOf(a, b1, b2, b3, b4, ...) возвращающую true если аргумент a равен хотя бы одному из аргументов b. Иначе false. Количество аргументов b от одного и далее. Типы аргументов могут быть разными, но подразумевается, что операция сравнения определена для a и любого из b. Два решения на D, итеративное и рекурсивное: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Итеративно, насколько я знаю в плюсах вообще невозможно сделать, сделайте хотя бы рекурсивно. Я бы и сам мог бы сделать, но вы же у нас гуру плюсов bool isOneOf1(A, ARGS...)(A a, ARGS bb) { foreach(b; bb) // это компиле-тайм foreach, не рантайм if(a == b) return true; return false; } bool isOneOf2(A, ARGS...)(A a, ARGS bb) { if(a == bb[0]) return true; static if(bb.length > 1) return isOneOf2(a, bb[1..$]); else return false; } void main() { assert(isOneOf1(1, 2, 3, 1, 5)); // ok 1 == 1 assert(isOneOf2(1, 2, 3, 1, 5)); // ok 1 == 1 assert(isOneOf1("a", "b", "c", "d", "e")); // runtime assertion assert(isOneOf2("a", "b", "c", "d", "e")); // runtime assertion } |
| Автор: korvin 11.02.14, 15:35 |
| Цитата MyNameIsIgor @ korvin, как ты считаешь, нужно ли такой "сахарок", прости за выражение, сделать в CL: будем парсить sexp прямо из строки? CL и так это умеет делать, есть же процедура read, которую можно вызывать хоть в compile-time, хоть в load-time, хоть в read-time. Да и те же reader-макросы. Вот только там это делать не за чем, да и не рекомендуется. =) Цитата D_KEY @ В сложных случаях будет запутано(и вообще интуитивно мне кажется это очень странной фичей), в обычных можно сделать на шаблонах и constexpr. Кстати да, то ли дело тот же питон например, хоть он мне и не нравится. Цитата applegame @ Да, оно компиляется, только компиле-тайм, а не рантайм в лямбду-предикат. Эдакий синтаксический сахарок, для простеньких предикатов. Но можно пихать, естественно и функторы и лямбды. Что, без макросов слишком быстро компилируется после плюсов? =) В чем проблема просто сделать удобный синтаксис для лямбд? Синтаксис хаскелла конечно трудновоспринимаем для тех, кто с ним не знаком, но после знакомства все становится понятным, и не надо ломать голову, почему у тебя параметр «a» вроде как связывается с массивом foo, но обращение к нему идет как к элементу foo. |
| Автор: D_KEY 11.02.14, 15:39 |
| Цитата applegame @ Итак, господа. Первая простейшая задача. Написать функцию-шаблон isOneOf(a, b1, b2, b3, b4, ...) возвращающую true если аргумент a равен хотя бы одному из аргументов b. Иначе false. Количество аргументов b от одного и далее. Типы аргументов могут быть разными, но подразумевается, что операция сравнения определена для a и любого из b. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<typename T, typename U> bool isOneOf(T a, U b) { return a == b; } template<typename T, typename U, typename ... Args> bool isOneOf(T a, U b, Args ... args) { return isOneOf(a, b) || isOneOf(a, args...); } Оно? Добавлено А зачем? |
| Автор: korvin 11.02.14, 15:41 |
| Хотелось бы посмотреть, как ты будешь строить список bb динамически, из пользовательского ввода например. |
| Автор: applegame 11.02.14, 15:43 |
| Не понимаю, к чему это? DMD, кстати компилирует гораздо быстрее GCC. Одна из фишек D - быстрая компиляция. Он есть. Я повторяю, это просто синтаксический сахар. Не нравится - не юзай. Но сама возможность доставляет. Вот вариант с лямбдой: http://dpaste.dzfl.pl/f13179c43403 Кстати как в плюсиках создать подобную шаблоннуя inline-лямбду? Никак, только городить отдельный шаблонный предикат? |
| Автор: MyNameIsIgor 11.02.14, 15:44 |
| D_KEY, ты и показал итеративное решение И для него не нужен компилятор с поддержкой оптимизации хвостовой рекурсии. Добавлено Что я и говорю |
| Автор: applegame 11.02.14, 15:48 |
| Оно, задача была проста. Но теперь сравниваем код, для D и для C++ и смотрим, что наглядней, легче для понимания и проще в написании. В плюсях пришлось городить отдельную вспомогательную функцию, как я и думал. |
| Автор: D_KEY 11.02.14, 15:49 |
| Цитата MyNameIsIgor @ D_KEY, ты и показал итеративное решение И для него не нужен компилятор с поддержкой оптимизации хвостовой рекурсии.Это как посмотреть Определение-то рекурсивное. То, что рекурсивного вызова в рантайме нет - это уже другой разговор. Мне интересно, зачем итеративное определение в такого рода вещах. |
| Автор: applegame 11.02.14, 15:50 |
| Цитата korvin @ Зачем? Это разве входило в условия задачи? Динамически только значения можно передавать. А длина и типы зафиксированы compile-time. Хотелось бы посмотреть, как ты будешь строить список bb динамически, из пользовательского ввода например. |
| Автор: MyNameIsIgor 11.02.14, 15:51 |
| Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном. |
| Автор: D_KEY 11.02.14, 15:52 |
| <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> bool isOneOf2(A, ARGS...)(A a, ARGS bb) { if(a == bb[0]) return true; static if(bb.length > 1) return isOneOf2(a, bb[1..$]); else return false; } vs <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<typename T, typename U> bool isOneOf(T a, U b) { return a == b; } template<typename T, typename U, typename ... Args> bool isOneOf(T a, U b, Args ... args) { return isOneOf(a, b) || isOneOf(a, args...); } Для меня второй вариант проще Хотя тут разницы-то нет.Цитата пришлось городить отдельную вспомогательную функцию, как я и думал. Почему вспомогательную? Это функция, которая берет два аргумента разных типов и сравнивает их |
| Автор: applegame 11.02.14, 15:52 |
| Иногда оно проще в реализации. С точки зрения эффективности разницы никакой. |
| Автор: D_KEY 11.02.14, 15:53 |
| Цитата MyNameIsIgor @ Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном. Ага. А в D второй вариант вырождается именно в рекурсивные функции? |
| Автор: MyNameIsIgor 11.02.14, 15:55 |
| Насколько я знаю, нет, тоже итеративный, не дженерики же Просто applegame не до конца понимают семантику того кода, который сам и написал |
| Автор: korvin 11.02.14, 15:59 |
| Цитата applegame @ Не понимаю, к чему это? DMD, кстати компилирует гораздо быстрее GCC. Одна из фишек D - быстрая компиляция. Там опечатка, поправил. Возможность сделать код непонятным? Кстати, как там с коллизией имен? Если внутри find уже будет переменная с именами «a» или «b» такого же типа, что и твои параметры? Цитата applegame @ Оно, задача была проста. Но теперь сравниваем код, для D и для C++ и смотрим, что наглядней, легче для понимания и проще в написании. Конечно хаскелл и CL: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> isOneOf1 _ [] = False isOneOf1 x (y:ys) = x == y || isOneOf1 x ys <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> (defmacro is-one-of (fn x &rest ys) (find x ys :test fn)) Добавлено Цитата applegame @ Зачем? Это разве входило в условия задачи? Динамически только значения можно передавать. А длина и типы зафиксированы compile-time. Ну так не интересно. |
| Автор: D_KEY 11.02.14, 16:00 |
| Только это другая задача Добавлено Я вот совсем не знаю template haskell. Там никак во время компиляции не сделать? |
| Автор: applegame 11.02.14, 16:05 |
| В debug-режиме, как правило да, как и в GCC например. В release оно разворачивает рекурсию, естественно. Я прекрасно знаю, что такое хвостовая рекурсия. |
| Автор: Wound 11.02.14, 16:06 |
| Ну да, он же там три строчки то съэкономил, пожалел места В принципе так то и выходит что разницы нет =) |
| Автор: korvin 11.02.14, 16:06 |
| Там много чего можно, это ж вроде почти как макросы CL, только типизированные. Т.е. наверное правильней сказать «как в Nemerle». Только в чем сакральный смысл? Часто ты таким образом сравниваешь значения? Обычно, если их довольно много, то это рантайм-коллекция и всё придется делать в рантайме, а если мало, то овчинка выделки не стоит, обход массива в пяток значений просто копеечен по стоимости. |
| Автор: applegame 11.02.14, 16:07 |
| Цитата MyNameIsIgor @ Ошибаешься. Посему тебе, лично - до свидания, не скучай Просто applegame не до конца понимают семантику того кода, который сам и написал |
| Автор: MyNameIsIgor 11.02.14, 16:09 |
| Какая может быть рекурсия, если вызывается другая функция? ![]() Не разворачивает рекурсию, а инлайнит вызовы других функций. Серьёзно? Я не заметил... |
| Автор: applegame 11.02.14, 16:09 |
| Цитата Wound @ Дык это только начало. Ну да, он же там три строчки то съэкономил, пожалел места В принципе так то и выходит что разницы нет =) |
| Автор: D_KEY 11.02.14, 16:09 |
| Цитата applegame @ Цитата MyNameIsIgor @ Ошибаешься. Посему тебе, лично - до свидания, не скучай Просто applegame не до конца понимают семантику того кода, который сам и написал ![]() Рано прощаешься, похоже, что он прав Добавлено Господа, при чем тут вообще хвостовая рекурсия сейчас? Давайте лучше холивар продолжим. |
| Автор: applegame 11.02.14, 16:15 |
| Цитата korvin @ Ты о каких a и b. Вот этих?Кстати, как там с коллизией имен? Если внутри find уже будет переменная с именами «a» или «b» такого же типа, что и твои параметры? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Это переменные локальные для самой лямбды, внутренности find не имеют к ним никакого отношения. Не нравятся a и b, используй другие имена, главное два аргумента и возвращение значения, которое может быть неявно приведено к bool. find!((a, b) => a.key == b)(foo, 1); |
| Автор: korvin 11.02.14, 16:15 |
| applegame, кстати, а если вместо первого аргумента будет вызов функции, она вызовется один раз и сохранит значение или будет вызываться на каждое сравнение? типа <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int foo() { writeln 1; return 1; } void main() { isOneOf(foo(), 2 3, 1, 4, 5); } |
| Автор: D_KEY 11.02.14, 16:17 |
| korvin, это не макросы. Совсем. |
| Автор: korvin 11.02.14, 16:18 |
| Цитата applegame @ Это переменные локальные для самой лямбды, внутренности find не имеют к ним никакого отношения. Не нравятся a и b, используй другие имена, главное два аргумента и возвращение значения, которое может быть неявно приведено к bool. Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int b = 3; find!"a.key == b"(foo, 2); Добавлено Это не значит, что они могут самостоятельно решить, вызывать предварительно foo(), или нет. |
| Автор: applegame 11.02.14, 16:20 |
| sensored, и ты туда же. Я эти рекурсивные шаблоны разбирал по косточкам, вплоть до ассемблера, когда баги в LLVM репортил. Инлайнирование функций (в обсуждаемом случае) полностью равнозначно разворачиванию рекурсии: превратит в тупую цепочку проверок. Причем итеративное решение приведет к такому же результату. То что функций будет много и компилятор их инлайнит - это вообще особенности компиляции, с функциональной точки зрения isOneOf в дешном варианте - одна функция с переменным числом аргументов, а не куча с разными сигнатурами. |
| Автор: D_KEY 11.02.14, 16:24 |
| Цитата applegame @ с функциональной точки зрения isOneOf в дешном варианте - одна функция с переменным числом аргументов, а не куча с разными сигнатурами. оО Кстати, именно это как раз деталь реализации, даже если так D делает. А вот семантически там как раз совершенно разные вызовы. Разве нет? Ты не нервничай так, а то сам понимаешь, что будет с темой Добавлено Цитата korvin @ Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int b = 3; find!"a.key == b"(foo, 2); Присоединяюсь к вопросу. |
| Автор: MyNameIsIgor 11.02.14, 16:26 |
| Цитата applegame @ То что функций будет много и компилятор из инлайнит - это вообще особенности компиляции То, что инлайнит - да, особенность компиляции. То, что функции разные - семантика языка. А если разные, то это не рекурсия просто по определению. Что такое "функциональная точка зрения"? Нет, ибо она параметризуется их типами. И потому это не просто переменное число аргументов - инстанцирование приводит к разным функциям хотя бы из-за проверки типов. |
| Автор: applegame 11.02.14, 16:27 |
| Цитата D_KEY @ Нет D так не делает. Это будут разные функции. Так как CTFE, то фактически рекурсия разворачивается в итеративный вариант (с foreach) с последующим разворачиванием цикла в последовательность проверок.Кстати, именно это как раз деталь реализации, даже если так D делает. А вот семантически там как раз совершенно разные вызовы. Разве нет? Оторвитесь уже, блджад, от плюсов. Представьте это математически: одна функция, рекурсивная, с переменным числом аргументов, вызывает сама себя. |
| Автор: MyNameIsIgor 11.02.14, 16:28 |
| Так а где здесь рекурсия то? |
| Автор: D_KEY 11.02.14, 16:28 |
| Цитата applegame @ Цитата D_KEY @ Нет D так не делает. Это будут разные функции.Кстати, именно это как раз деталь реализации, даже если так D делает. А вот семантически там как раз совершенно разные вызовы. Разве нет? Значит, нет и рекурсии. |
| Автор: MyNameIsIgor 11.02.14, 16:29 |
| Мы представили. Математически мы не видим одной функции, мы видим метафункцию (шаблон), порождающую разные функции. Добавлено Метафункция рекурсивна, да. Порождённые ею функции - нет. |
| Автор: D_KEY 11.02.14, 16:34 |
| Тут вот есть рекурсия? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> bool isOneOf__2(int a, int b) { return a == b; } bool isOneOf__3(int a, int b, int c) { return isOneOf__2(a, b) || isOneOf__2(a, c); } bool isOneOf__4(int a, int b, int c, int d) { return isOneOf__2(a, b) || isOneOf__3(a, c, d); } bool isOneOf__5(int a, int b, int c, int d, int e) { return isOneOf__2(a, b) || isOneOf__4(a, c, d, e); } ... |
| Автор: korvin 11.02.14, 16:37 |
| Цитата korvin @ Это не значит, что они могут самостоятельно решить, вызывать предварительно foo(), или нет. Или «имеют право решать». Пример, конечно, надуманый, но всякое ведь бывает. =) |
| Автор: D_KEY 11.02.14, 16:43 |
| В C++ там идет обычный вызов функции, если что. Т.е. вся магия была на этапе инстанцирования шаблона функции. После инстанцирования ты вызываешь обычную функцию. |
| Автор: korvin 11.02.14, 16:45 |
| Цитата D_KEY @ В C++ там идет обычный вызов функции, если что. Т.е. вся магия была на этапе инстанцирования шаблона функции. После инстанцирования ты вызываешь обычную функцию. Да я как бы вижу по результату и спрашивал не «почему так происходит». =) |
| Автор: applegame 11.02.14, 16:45 |
| Вот специально для вас. Тут будет ровно одна функция, вызывающая сама себя. Математически одно и то же, скажите мне еще, что это не рекурсия: http://dpaste.dzfl.pl/3c5b2e014724 Хз хватит ли ума у компилятора D развернуть эту рекурсию в цикл. Но это не важно, важно чтобы стало понятно, о чем я. Добавлено Цитата korvin @ Эм, я полагаю она вызовется один раз. applegame, кстати, а если вместо первого аргумента будет вызов функции, она вызовется один раз и сохранит значение или будет вызываться на каждое сравнение? типа |
| Автор: MyNameIsIgor 11.02.14, 16:49 |
| Тут да. Потому что здесь нет зависимости аргументов шаблона от аргументов функции. Это есть шаблон функции с переменным числом параметров. А вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> bool isOneOf2(A, ARGS...)(A a, ARGS bb) есть шаблон функции с переменным числом параметров разного типа. Если семантика (а не компилятор) D сводит второе к первому, то D убог. Но я не думаю, что он так делает. Добавлено applegame, можно ли в D сделать такую проверку? (грязный хак, знаю) |
| Автор: applegame 11.02.14, 16:57 |
| Вообще это фактически пошел холивар терминов. Факт в том, что я прекрасно знаю, что такое разворачивание хвостовых рекурсий, как именно работают шаблонные функции, как они инлайнятся (зависит от компилятора и от опций компиляции). Если кто считает, что я в этом деле профан - ваше право так думать и заявлять об этом, а мое право сказать вам: "до свидания". А я тем временем вернусь к основному холивару и подгоню более сложную задачу. |
| Автор: MyNameIsIgor 11.02.14, 16:58 |
| Только её здесь нет |
| Автор: D_KEY 11.02.14, 17:09 |
| Цитата applegame @ Вообще это фактически пошел холивар терминов. Факт в том, что я прекрасно знаю, что такое разворачивание хвостовых рекурсий, как именно работают шаблонные функции, как они инлайнятся (зависит от компилятора и от опций компиляции). Если кто считает, что я в этом деле профан - ваше право так думать и заявлять об этом, а мое право сказать вам: "до свидания". А я тем временем вернусь к основному холивару и подгоню более сложную задачу. А ты мог бы ответить на вопрос korvinа по поводу кода из строки и аргументов/захвата? |
| Автор: applegame 11.02.14, 17:16 |
| Так устроит? http://dpaste.dzfl.pl/1e63ac0de3b5 Цитата D_KEY @ На что-то я уже отвечал, процитируй вопрос еще раз. А ты мог бы ответить на вопрос korvinа по поводу кода из строки и аргументов/захвата? |
| Автор: korvin 11.02.14, 17:19 |
| D vs C++ (сообщение #3413091) Добавлено Я думаю, Игорь имел в виду эту проверку: http://dpaste.dzfl.pl/7ee97716f99f |
| Автор: applegame 11.02.14, 17:28 |
| Цитата korvin @ А, если предикат задан строкой, то имена жестко зафиксированы за "a" и "b". Дело в том, что D умеет компилировать выражение в строке (конечно, только если значение строки вычисляемо compile-time). Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром? Добавлено А в чем принципиальная разница? |
| Автор: MyNameIsIgor 11.02.14, 17:34 |
| Принципиальной разницы нет - функции разные. |
| Автор: korvin 11.02.14, 17:35 |
| Я не знаю, есть ли в D разница между твоим и моим примером, но, думаю, разные адреса намекают на разные функции, а кто-то утверждал, что функция одна. |
| Автор: applegame 11.02.14, 17:42 |
| Это очевидно. При присвоении значения первому указателю, будут сгенерены две функции для двух и трех int. Для второго указателя сгенерится еще одна функция - для четырех int (для трех и двух уже нет необходимости, так как они уже есть). Если включить оптимизацию, то в готовом коде, вероятно, останутся только две функции: для трёх и для четырех int. Причем также вероятно, что та, что с четырмя не будет вызывать ту, что с тремя. Если компилер совсем крут, аки GCC, то в конечном коде функций может не быть совсем, все будет заинлайнено "в нули". Добавлено Господи, я же говорил, с математической точки зрения. Можете обзывать это метафункцией: |
| Автор: D_KEY 11.02.14, 17:46 |
| Цитата applegame @ Цитата korvin @ А, если предикат задан строкой, то имена жестко зафиксированы за "a" и "b". Дело в том, что D умеет компилировать выражение в строке (конечно, только если значение строки вычисляемо compile-time).Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром? Можно подробнее? И есть ли способ захвата контекста в ..эм.. строку? |
| Автор: MyNameIsIgor 11.02.14, 17:51 |
| Собственно, не понятно чем вы тогда весь такой недовольный. Я ведь говорил Цитата MyNameIsIgor @ Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном. |
| Автор: applegame 11.02.14, 17:52 |
| Строка будет скомпилирована в контексте того места, где она собственно скомпилирована, простите за тавтологию. Ща приведу пример, может станет понятней. |
| Автор: korvin 11.02.14, 17:54 |
| Цитата applegame @ Господи, я же говорил, с математической точки зрения. Можете обзывать это метафункцией С «математической» точки зрения у всех функций только один аргумент например. =) Не знаю, зачем вообще надо было приплетать в обсуждение математику и какой «физический смысл» у этой «математической точки зрения» как в контексте обсуждения, так и для компиляторов. |
| Автор: applegame 11.02.14, 17:55 |
| Я против этого не возражал. Случилось, вероятно, недопонимание. Предлагаю закрыть эту тему. Добавлено Да, с ясностью выражения мыслей у меня иногда бывают проблемы, как собственно и у всех. Исключение разве что FlexFerrum, по крайней мере в темах о C++ ![]() Цитата korvin @ Смысл был в ответе на вопрос корректно ли называть второе решение - рекурсивным? То, что оно семантически будет итеративным - вызов нескольких функций одна внутри другой - очевидно, но само решение, я считаю, можно вполне назвать рекурсивным. Не знаю, зачем вообще надо было приплетать в обсуждение математику и какой «физический смысл» у этой «математической точки зрения» как в контексте обсуждения, так и для компиляторов. Добавлено Вот обещанный пример. Обратите внимание на удобство и простоту использования auto в качестве возвращаемого типа: [URL=http://dpaste.dzfl.pl/82aacb91bb0b <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ]http://dpaste.dzfl.pl/82aacb91bb0bimport std.conv; auto foo(string code)(int a, int b) { int c = a - b; return mixin(code); } void main() { assert( foo!("a + b")(1, 2) == 3 ); assert( foo!("a == b")(1, 2) == false ); assert( foo!("a + c")(1, 2) == 0 ); assert( foo!("a.to!string ~ b.to!string")(1, 2) == "12" ); } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> [/URL] import std.conv; auto foo(string code)(int a, int b) { int c = a - b; return mixin(code); } void main() { assert( foo!("a + b")(1, 2) == 3 ); assert( foo!("a == b")(1, 2) == false ); assert( foo!("a + c")(1, 2) == 0 ); assert( foo!("a.to!string ~ b.to!string")(1, 2) == "12" ); } Добавлено И да, на всякий случай, уточню: будет сгенерено четыре функции foo, для разных строковых параметров. |
| Автор: MyNameIsIgor 11.02.14, 18:25 |
| http://en.wikipedia.org/wiki/C%2B%2B14#Fun..._type_deduction По поводу кривости компилирования строк уже высказывался. |
| Автор: applegame 11.02.14, 18:34 |
| Никаких аргументов, кроме "мне не навится" и "зачем?" я не видел. |
| Автор: MyNameIsIgor 11.02.14, 18:39 |
| Так вы на вопрос "зачем?" ответили "доставляет" Это я должен полагать аргументом?И таки да, это криво. Посмотрите как пишутся макросы в Nemerle, и вы меня поймёте. |
| Автор: korvin 11.02.14, 18:48 |
| Цитата applegame @ Обратите внимание на удобство и простоту использования auto в качестве возвращаемого типа Не прошло и сорока лет... =) Жестко заданные имена параметров, отсутствие возможности автоматически захватить контекст вызова. Кстати, количество параметров-то не жестко 2? |
| Автор: applegame 11.02.14, 18:48 |
| Цитата MyNameIsIgor @ Ну вот вы нагло лжете.троллите, а я должен после этого пытаться дискутировать? Никакого вопроса "зачем?" там не было - D vs C++ (сообщение #3413060) Так вы на вопрос "зачем?" ответили "доставляет" Это я должен полагать аргументом?Добавлено Посмотрите на название темы и поймете, что Nemerle тут не нужен. |
| Автор: korvin 11.02.14, 18:50 |
| Цитата applegame @ Ну вот вы нагло лжете.троллите, а я должен после этого пытаться дискутировать? Никакого вопроса "зачем?" там не было Пусть теперь будет: зачем? |
| Автор: applegame 11.02.14, 18:50 |
Это скорее к плюсам В D это уже давно.Цитата korvin @ Это ты о чем вообще? Жестко заданные имена параметров только для предикатов в виде строк. Жирным выделил все необходимые условия. Повторю, для непонятливых магические слова: предикаты в виде строк. Не лямбды вообще, а еще раз, только предикаты в виде строк. Не предикаты вообще, а и еще раз только предикаты в виде строк. Жестко заданные имена параметров, отсутствие возможности автоматически захватить контекст вызова. Кстати, количество параметров-то не жестко 2? |
| Автор: korvin 11.02.14, 18:51 |
| Ах да, для этого кода внутри строк подсветка синтаксиса не работает. А дополнение кода? |
| Автор: D_KEY 11.02.14, 18:55 |
| "Зачем?" - это вопрос, а не аргумент Фича действительно не нравится. И не понятно зачем она |
| Автор: korvin 11.02.14, 18:55 |
| Ну ты же сам говорил, что имена параметров a и b жестко заданные. Добавлено Не буду выделять жирным ответ, просто кратко перечислю: 1) Речь и идет о строках. 2) У предикатов бывает только два параметра? И я хочу их называть например subject и object, как во всяких прологах и графовых БД, а не a и b, можно? |
| Автор: applegame 11.02.14, 18:59 |
| Чтобы упростить код, для простых предикатов. Лямбда всяко будет длиннее даже в D, а в плюсах и подавно. Добавлено Цитата korvin @ Ответы: нет, нет.Не буду выделять жирным ответ, просто кратко перечислю: 1) Речь и идет о строках. 2) У предикатов бывает только два параметра? И я хочу их называть например subject и object, как во всяких прологах и графовых БД, а не a и b, можно? "Строковые" предикаты теряют свои косметические преимущества для сложных случаев. Используй в качестве предиката лямбды, делегаты, функторы, все, что callable и подходит по сигнатуре. У "не строковых" предикатов нет ограничений на название переменных. Количество аргументов зависит не от "строковости" предиката, а от функции, которая его требует. |
| Автор: MyNameIsIgor 11.02.14, 19:05 |
| Это новый тренд на форуме такой? Название темы - это повод отвергать опыт других и творить поделки? А фичу C# с преобразованием лямбд в объекты, представляющие синтаксическое дерево, на которой LINQ работает, вы тоже за пример не рассматриваете? Подозреваю, что проблема не в названии темы, а в том, что вы ничего слащее редьки не пробовали. |
| Автор: korvin 11.02.14, 19:08 |
| На пару-тройку символов? Вообще погоды не делает. От каррирования и то больше разницы. |
| Автор: applegame 11.02.14, 19:10 |
Это ваш личный тренд, которого вы постоянно придерживаетесь ![]() В общем я вас понял, да. Не благодарите за еду - не стоит ![]() С вашего позволения я продолжу с другими участниками. Впрочем, пардон, мне не нужно для этого ваше позволение. |
| Автор: MyNameIsIgor 11.02.14, 19:14 |
| Цитата applegame @ Это ваш личный тренд, которого вы постоянно придерживаетесь ![]() В общем я вас понял, да. Не благодарите за еду - не стоит ![]() С вашего позволения я продолжу с другими участниками. Впрочем, пардон, мне не нужно для этого ваше позволение. ![]() Т.е. на другие языки вы смотреть не хотите и продолжаете жевать редьку? Ну, это вы зря... |
| Автор: applegame 11.02.14, 19:15 |
| Цитата korvin @ Во-первых не пара и не тройка, попробуйте что-ли. Во-вторых, любой синтаксический сахар кому-то нравится, а кому-то нет. Это всего лишь один из вариантов применения строковых литералов в качестве параметра шаблона. На пару-тройку символов? Вообще погоды не делает. От каррирования и то больше разницы. |
| Автор: MyNameIsIgor 11.02.14, 19:17 |
| Цитата applegame @ Это всего-лишь один из вариантов применения строковых литералов в качестве параметра шаблона. Сам сей факт не вызывает отторжения. А вот зачем запихивать в строку код - непонятно. Пример хоть покажите радикальной экономии символов. |
| Автор: korvin 11.02.14, 19:22 |
| Ровно два: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> find!"a.key == b"(foo, 1) find!(a => a.key == 1)(foo) Ведь без строк нам не нужен параметр b. А если бы не !, то вообще один символ. |
| Автор: applegame 11.02.14, 19:23 |
| Впрочем, что-то мы увлеклись строковыми предикатами, пример я привел, чтобы разъяснить как вообще работает компиляция строк, в качестве пояснения к вопросу "Строковый" предикат - это простая строка. Предикатом его делает функция find, поэтому, естественно, никаких захватов контекстов нет. Для захвата контекста - есть обычные лямбды. |
| Автор: applegame 11.02.14, 19:29 |
Если юзать предикат с одним параметром, то и в "строковом" варианте можно убрать b (пять символов ):<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> find!"a.key == 1"(foo) find!(a => a.key == 1)(foo) правда лямбда может захватить внешний контекст, а строка нет: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int b = 1; find!"a.key == b"(foo); // ошибка find!(a => a.key == b)(foo) // все ок Доступен, опять же синтаксический сахар, который, лично мне нравится: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> foo.find!"a.key == b"; Добавлено На сягодня я заканчиваю. Завтра расскажу о других, не менее интересных для обсуждения, возможностей D. |
| Автор: korvin 11.02.14, 20:03 |
| Смотри сахарный диабет не заработай. |
| Автор: MyNameIsIgor 11.02.14, 20:06 |
| Пока такие "киллер фичи" будут продвигаться новыми языками, у C++ обеспеченное будущее. |
| Автор: Qraizer 12.02.14, 03:27 |
| Я что-то не пойму, об чём холивар. Если не ошибаюсь, поправьте, если не если, Александреску задумал D не как убийцу C++, а как язык с ориентацией на парадигму обобщённого программирования и без груза обратной совместимости с чем бы то ни было, а значит и лишённого набившего в C++ оскомину. Так что по определению везде, где требуется ниша мета- и К°, D наверняка предложит сырец покрасивше, где требуется "железный" уровень абстракции, он сольёт, в остальных случаях будет пофик. Остаётся только вопрос практичности результата там, где D якобы превосходит. Собственно и всё. А вы тут какую-то хрень обсуждаете. Возвращаясь к интерфейсам. Интерфейсы в Плюсах всю жизнь прекрасно эмулировались виртуальными базовыми абстрактными классами. Невиртуальный базовый класс, неважно, абстрактный или нет, однозначно не используется как интерфейс. Всё это превосходно дружит с множественным наследованием реализаций. Какие ещё могут быть тут вопросы? Разве что к D. applegame, приведи пример простенького сериализатора на D. Кто не ходит в Общие Плюсы, вот ссылка на предмет измерения длины. Для понять, откуда ноги, там есть первая страничка темы. Интересно посмотреть на D-код в контексте, где он должен быть на коне. |
| Автор: applegame 12.02.14, 05:57 |
| Цитата Qraizer @ Претензия к D, что у него якобы интерфейсы реализованы не совсем так как привычно (ссылаются на прочие языки с интерфейсами). А именно с одной особенностью. Тут не важно виртуальный базовый класс или нет. Виртуальность ничего не меняет:Возвращаясь к интерфейсам. Интерфейсы в Плюсах всю жизнь прекрасно эмулировались виртуальными базовыми абстрактными классами. Невиртуальный базовый класс, неважно, абстрактный или нет, однозначно не используется как интерфейс. Всё это превосходно дружит с множественным наследованием реализаций. Какие ещё могут быть тут вопросы? Разве что к D. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> В D интерфейсы ведут себя аналогично плюсовой эмуляции. Но так как в плюсах эмуляция, то это нормально, а так как в D есть ключевое слово interface, то это уже косяк. По мне так оно яйца выеденного не стоит, но полемику некоторые все равно развели. Холивары, они такие class IFoo { virtual void f() = 0; virtual void g() = 0; }; class Base { void g() {} }; class Derived : public Base, public virtual IFoo { void f() {} }; int main() { Derived derived; // ошибка, Derived - абстрактный } Добавлено Окай, ща набросаю чего-нибудь. |
| Автор: D_KEY 12.02.14, 06:45 |
| Цитата Qraizer @ Если не ошибаюсь, поправьте, если не если, Александреску задумал D не как убийцу C++, а как язык с ориентацией на парадигму обобщённого программирования и без груза обратной совместимости с чем бы то ни было, а значит и лишённого набившего в C++ оскомину. Ну автор темы не Александреску. Решили поспорить о D vs C++, почему бы и нет Цитата Остаётся только вопрос практичности результата там, где D якобы превосходит. Собственно и всё. А вы тут какую-то хрень обсуждаете. По большому счету именно этот вопрос мы и обсуждаем. Что могут дать возможности D и стоит ли оно того. |
| Автор: applegame 12.02.14, 08:44 |
| Набросал сериализатор/десериализатор. Постарался максимально обобщить, но возможны косяки. API простой, как пять копеек: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> stream.serialize(arg1, arg2, arg3 ...); // сериализует аргументы в stream, stream - любой объект для которого выполнима операция stream.rawWrite(const byte[]) stream.deserialize(arg1, arg2, arg3 ...); // десериализует аргументы из stream, stream - любой объект для которого выполнима операция stream.rawRead(byte[]) Из коробки поддерживаются: скаляры, массивы, структуры, классы. Классы и структуры сериализуются поле за полем, причем поля тоже могут быть классами или структурами или массивами и т.п. Если такая сериализация не нужна, можно для конкретных структур/классов сделать специализацию определив внутри функции rawRead и rawWrite (см. тест, структура Preved). сериализатор <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.traits; // сериализация скалярных типов данных void serialize(S, D)(S stream, auto ref const D data) if(isScalarType!D) { stream.rawWrite(cast(const byte[])(&data)[0..1]); } // сериализация структур и классов void serialize(S, D)(S stream, auto ref const D data) if(isAggregateType!D) { // проверяем не определен ли член rawWrite static if(hasMember!(D, "rawWrite")) { data.rawWrite(stream); } else { // перебираем все члены структуры/класса foreach(ident; __traits(allMembers, D)) { // отсекаем функции, перечисления и прочую несериализуемую лабудень static if(is(typeof(mixin("D." ~ ident ~ ".offsetof")))) { mixin("serialize(stream, data." ~ ident ~ ");"); } } } } // сериализация массивов void serialize(S, D)(S stream, auto ref const D data) if(isArray!D) { // тип элемента alias E = typeof(data[0]); // сначала пишем длину serialize(stream, data.length); // если длина больше нуля, то пишем данные. if(data.length) { // если это массив скаляров, то пишем одним куском, иначе сериализуем поэлементно static if(isScalarType!E) { stream.rawWrite(cast(const byte[])data[]); } else { foreach(ref element; data) { serialize(stream, element); } } } } // десериализация, аналогично сериализации void deserialize(S, D)(S stream, ref D data) if(isScalarType!D) { stream.rawRead(cast(byte[])(&data)[0..1]); } void deserialize(S, D)(S stream, ref D data) if(isAggregateType!D) { static if(hasMember!(D, "rawRead")) { data.rawRead(stream); } else { foreach(ident; __traits(allMembers, D)) { static if(is(typeof(mixin("D." ~ ident ~ ".offsetof")))) { mixin("deserialize(stream, data." ~ ident ~ ");"); } } } } void deserialize(S, D)(S stream, ref D data) if(isArray!D) { alias E = typeof(data[0]); size_t length; deserialize(stream, length); if(length) { Unqual!E[] ndata; ndata.length = length; static if(isScalarType!E) { stream.rawRead(cast(byte[])ndata[]); } else { foreach(ref element; ndata) { deserialize(stream, element); } } data = cast(D) ndata; } } // функции-хелперы для сериализации/десериализации сразу нескольких значений void serialize(S, ARGS...)(S stream, auto ref const ARGS args) if(ARGS.length > 1) { foreach(ref arg; args) serialize(stream, arg); } void deserialize(S, ARGS...)(S stream, ref ARGS args) if(ARGS.length > 1) { foreach(ref arg; args) deserialize(stream, arg); } тест <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.stdio; import std.algorithm; import serializer; // примитивная структурв struct Foo { int fi; bool fb; string fs; } // класс с полем-структурой class Bar { int fi; bool fb; string fs; Foo ff; this(int i, bool b, string s, Foo f) { fi = i; fs = s; ff = f; } this() {} bool isSame(const Bar o) const { return fi == o.fi && fb == o.fb && fs == o.fs && ff == o.ff; } } // структура с переопределенными операциями сериализации/десериализации struct Preved { private string m_medved; void rawWrite(S)(S stream) const { stream.serialize("preved", m_medved); } void rawRead(S)(S stream) { string signature; stream.deserialize(signature); assert(signature == "preved"); stream.deserialize(m_medved); } } void main() { // готовим тестовые данные int s_int = 10; string s_string = "hello"; Foo s_foo = Foo(123, true, "foo"); Bar s_bar = new Bar(42, false, "bar", Foo(345, false, "foobar")); Foo[] s_foos = [ Foo(11, true, "foos1"), Foo(22, false, "foos2"), Foo(33, true, "foos3") ]; Preved s_preved = Preved("medved"); auto file = File("test.txt", "w"); // сериализуем в файл file.serialize(s_int, s_foo, s_string, s_bar, s_foos, s_preved); /******************************************************************/ // переменные для десериализации int d_int; string d_string; Foo d_foo; Bar d_bar = new Bar; Foo[] d_foos; Preved d_preved; file = File("test.txt", "rb"); // десериализуем из файла file.deserialize(d_int, d_foo, d_string, d_bar, d_foos, d_preved); // проверяем assert(d_int == s_int); assert(d_foo == s_foo); assert(d_string == s_string); assert(d_bar.isSame(s_bar)); assert(equal(d_foos, s_foos)); assert(d_preved == s_preved); } |
| Автор: MyNameIsIgor 12.02.14, 09:56 |
Ну, вот почему, почему всегда рефлексию показывают на этом тупом примере сериализации всех полей? |
| Автор: D_KEY 12.02.14, 10:20 |
| Ну сериализатор его попросили написать. Если для составного типа не задана функция сериализации, то проход по полям лучше бинарной записи. |
| Автор: MyNameIsIgor 12.02.14, 10:28 |
| fixed. Да и я спрашиваю вообще, а не про именно сейчас. |
| Автор: D_KEY 12.02.14, 11:05 |
| Ну тебя же не смущает дефолтный конструктор копирования, например. Если все поля у объекта сериализуемы, то почему бы и не сериализовать, раз просят. |
| Автор: korvin 12.02.14, 11:05 |
| Описывать метод сериализации для каждого своего типа как-то не очень удобно. Обычно это довольно рутинный copy-paste код. Кстати маршалинг/демаршалинг в xml/json структур в Go не затрагивает скрытые поля структур. ЕМНИП до них и через рефлексию не достучаться. |
| Автор: D_KEY 12.02.14, 11:22 |
| Это смотря какой движок сериализации. Например, в boost.serialization ты фактически просто указываешь, что хочешь сериализовать. Для сериализации/десериализации: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & x; ar & y; ar & z; } Так же есть возможность разделить сохранение и загрузку(определив методы save и load, а не serialize) |
| Автор: applegame 12.02.14, 11:45 |
| Цитата D_KEY @ Кстати, это тоже интересный момент: как указать поля которые нужно сериализовать, или наоборот не нужно. В D есть фича, которую можно для этого применить. Это так называемые UDA - user defined attribute. По сути - это что-то вроде пометок, которые ни на что не влияют, но которые можно читать (compile time) и предпринимать в зависимости от этого какие-то действия. Пример: http://dpaste.dzfl.pl/120ff9a20956 Например, в boost.serialization ты фактически просто указываешь, что хочешь сериализовать. |
| Автор: MyNameIsIgor 12.02.14, 12:12 |
| Потому что если у меня есть поле-мьютекс, то копироваться такой объект не будет. Т.е. поля структуры управляют поведением такого конструктора. А тут не управляют - сериализуемость определяется тем, что мы можем пройтись по типу рефлексией. Для мьютекс эта чудо-сериализация запишет его дескриптор. Меня больше волнует правильность, а не удобство поведения по умолчанию, чреватого детскими грабельками. Это зависит от библиотеки сериализации. Я не замечал копипасты. Кроме того, метаинформацию никто не отменял. Вон и applegame её для себя открыл. |
| Автор: Qraizer 12.02.14, 12:15 |
| А тут и не должно, т.к. как уже говорилось, Base не реализует IFoo. Но вот так должно: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> class IFoo { virtual void f() = 0; virtual void g() = 0; }; class Base : virtual IFoo { void g() {} }; class Derived : public Base, public virtual IFoo { void f() {} }; int main() { Derived derived; // нет ошибки, Derived собирает в себе реализации обоих методов единственного абстрактного класса aka интерфейса } |
| Автор: MyNameIsIgor 12.02.14, 12:22 |
| Кстати, о птичках. В примере на D мы видим рефлексию времени компиляции по типу, а не времени исполнения по объекту, следовательно, если подпихнуть наследника под видом предка, шаблон инстанцируется для предка и сериализует не всё - fail. |
| Автор: Qraizer 12.02.14, 12:27 |
| Вообще, с интерфейсами и в Плюсах следует быть осторожным. Легко запутаться в virtual и не virtual. Пример тут. |
| Автор: D_KEY 12.02.14, 12:49 |
| Цитата MyNameIsIgor @ Потому что если у меня есть поле-мьютекс, то копироваться такой объект не будет. Т.е. поля структуры управляют поведением такого конструктора. Тут согласен, да. Но это же пример, можно будет дать возможность запретить сериализацию для типа или еще как-то решить данную проблему. |
| Автор: korvin 12.02.14, 12:51 |
| Цитата MyNameIsIgor @ Меня больше волнует правильность, а не удобство поведения по умолчанию, чреватого детскими грабельками. А зачем вообще может понадобиться сериализовать такое значение? Я не храню в данных, предназначенных для передачи во вне/приеме извне какие-то служебные объекты, только "plain data". |
| Автор: MyNameIsIgor 12.02.14, 12:55 |
| Да пусть так. Я о другом говорю: чуть заходит разговор за рефлексию, как кричат "сериализация!". Я же говорю, что рефлексия при сериализации чаще всего вредна. Цитата korvin @ Я не храню в данных, предназначенных для передачи во вне/приеме извне какие-то служебные объекты, только "plain data" Погоди, plain data - это детали реализации. Если ты выставил их наружу так, что их видит библиотека сериализации, то я уже считаю это ошибкой проектирования. |
| Автор: Бобёр 12.02.14, 13:35 |
| Цитата - встроенные ассоциативные массивы. Не знаю, звучала ли тут уже эта мысль. std::map и std::hash_map - вполне себе встроенные в язык C++. Метапрограммирование говоришь? Можете закапывать - не нужно. Рефлекшн... ну, бывает полезен. |
| Автор: applegame 12.02.14, 18:31 |
| Цитата Бобёр @ Взаимоисключающие параграфы Не знаю, звучала ли тут уже эта мысль. std::map и std::hash_map - вполне себе встроенные в язык C++. Добавлено Цитата Qraizer @ Вообще, кто-то просил сериализацию, получил сериализацию, но ни одного комментария на эту тему так и не сделал. Вообще, с интерфейсами и в Плюсах следует быть осторожным. Легко запутаться в virtual и не virtual. Пример тут. |
| Автор: MyNameIsIgor 12.02.14, 19:36 |
| Цитата applegame @ Вообще, кто-то просил сериализацию, получил сериализацию, но ни одного комментария на эту тему так и не сделал А вы ошибку то исправлять не собираетесь? |
| Автор: korvin 13.02.14, 04:43 |
| Цитата MyNameIsIgor @ Погоди, plain data - это детали реализации. Если ты выставил их наружу так, что их видит библиотека сериализации, то я уже считаю это ошибкой проектирования. Ты вообще о чем? У меня просто в тех местах, где требуется маршалинг/демаршалинг, нет «объектов» с закрытыми полями, только структуры с открытыми. |
| Автор: jack128 13.02.14, 05:15 |
| Цитата korvin @ У меня просто в тех местах, где требуется маршалинг/демаршалинг, нет «объектов» с закрытыми полями, только структуры с открытыми. прикольно. то есть если бы ты писал excel, то у тебя бы документ представлял бы собой такую вот огромную структуру с открытыми полями? |
| Автор: Qraizer 13.02.14, 05:18 |
| Цитата applegame @ Зачем что-либо говорить ради что-либо сказать? Я посмотрел, даже понял, как работает, ожидания подтвердились. Вообще, кто-то просил сериализацию, получил сериализацию, но ни одного комментария на эту тему так и не сделал. Добавлено Я даже примерно представляю как. Это даже скорее не ошибка, а просто плохо задокументированная инструкция по применению. Но так, как я это представляю, будет неудобно, и вот сие улучшить было бы неплохо. |
| Автор: korvin 13.02.14, 05:41 |
| Цитата jack128 @ прикольно. то есть если бы ты писал excel, то у тебя бы документ представлял бы собой такую вот огромную структуру с открытыми полями? А ты считаешь, что во всех задачах можно использовать один и тот же подход? У меня нет «огромных структур», все довольно небольшие. Впрочем, может быть так оно и было бы, а в чем проблема? |
| Автор: MyNameIsIgor 13.02.14, 09:42 |
| Цитата korvin @ Цитата MyNameIsIgor @ Погоди, plain data - это детали реализации. Если ты выставил их наружу так, что их видит библиотека сериализации, то я уже считаю это ошибкой проектирования. Ты вообще о чем? У меня просто в тех местах, где требуется маршалинг/демаршалинг, нет «объектов» с закрытыми полями, только структуры с открытыми. Гмм... Как это выглядит в жизни? Т.е. пример бы какой-нибудь. |
| Автор: korvin 13.02.14, 12:53 |
| Ну например беру из базы нужные записи(структуры) и на их основе создаю новую структуру (с другими полями) или массив структур и отправлю ее/их по HTTP клиенту. То же самое и в обратном порядке. Сам сервис никаких «объектов с состоянием» не имеет, всё состояние в записях БД. Т.е. всё больше в функциональном стиле. |
| Автор: MyNameIsIgor 13.02.14, 17:52 |
| Цитата korvin @ Ну например беру из базы нужные записи(структуры) и на их основе создаю новую структуру (с другими полями) или массив структур и отправлю ее/их по HTTP клиенту. То же самое и в обратном порядке. Так вместо функций сериализации каждого типа у тебя есть функции преобразования данных, полученных от модуля взаимодействия с БД, в данные, пригодные для простой сериализации. Так какая разница? |
| Автор: korvin 14.02.14, 04:23 |
| Цитата MyNameIsIgor @ Так вместо функций сериализации каждого типа у тебя есть функции преобразования данных, полученных от модуля взаимодействия с БД, в данные, пригодные для простой сериализации. Так какая разница? Разница в том, что функции обработки мне нужны в любом случае, это не просто «преобразование данных», а некоторая бизнес-логика. В простых случаях этих функций нет и данные напрямую передаются клиенту и обратно, безо всякой обработки. Так зачем мне еще описывать функции сериализации/десериализации для каждого типа? |
| Автор: Qraizer 14.02.14, 05:07 |
| А обязательно для каждого? Разве нельзя описывать только исключения, для остальных предложив единый метод? |
| Автор: korvin 14.02.14, 05:24 |
| Цитата Qraizer @ А обязательно для каждого? Разве нельзя описывать только исключения, для остальных предложив единый метод? Ну так у меня так и получается, только в этих «исключительных» случаях вместо одной большой структуры с данными для БД и данными для клиента используются две небольшие структуры — одна для БД, другая для клиента. |
| Автор: applegame 30.03.14, 13:12 |
| Вспомнил про затихший холиворчик. Продолжу продвижение D. Функция должна вернуть несколько значений, и хочется чтобы доступ к значениям был бы как к полям структуры, а не по индексу, как в обычном плюсовом кортеже. Вот эта маленькая магия сама объявляет структуру с полями названными как переменные переданные в параметры и заполняет ее значениями из этих же переменных. Структура объявляется внутри функции (кстати, а плюсы так умеют?), а значит не гадит в глобальную область видимости. Рекурсивный миксин плюс немножко статической рефлексии. Дешево, сердито и красиво, плюсики так не умеют и вряд ли когда сумеют: http://dpaste.dzfl.pl/d09ce6ded86b <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template packTuple(ARGS...) { template Decls(alias value, ARGS...) { mixin("typeof(value)" ~ __traits(identifier, value) ~ ";"); static if(ARGS.length) mixin Decls!ARGS; } struct Tuple { mixin Decls!ARGS; } auto packTuple() { return Tuple(ARGS); } } auto foo() { int fieldInt = 10; string fieldString = "test"; return packTuple!(fieldInt, fieldString); } void main() { auto result = foo(); assert(result.fieldInt == 10); assert(result.fieldString == "test"); } |
| Автор: amk 30.03.14, 13:30 |
| Уметь-то умеют, но эта структура будет видна только внутри этой функции, так что выдать её в качестве результата не получится, поскольку в точке вызова она не будет существовать. Хотя, возможно auto может создать безымянный тип, соответствующий этой структуре, и получится использовать его. |
| Автор: applegame 30.03.14, 13:40 |
| Цитата amk @ Конечно с auto. Без auto и в D невозможно. ЕМНИП в след версии плюсов, появился полноценный auto, а не инвалид который есть в C++11. Хотя, возможно auto может создать безымянный тип, соответствующий этой структуре, и получится использовать его. |
| Автор: amk 30.03.14, 13:45 |
| А что такого инвалидного в С++ auto? |
| Автор: applegame 30.03.14, 13:50 |
| Опять же, ЕМНИП, там запутанный и неприятный синтаксис для auto - возвращаемых типов. Просто вот так написать не получится: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Вроде Qraizer говорил, что в C++14, уже можно будет писать и так. template<typename A, typename B> auto foo(A a, B b) { return a + b; } Добавлено Кстати еще вот некоторым не нравится, что в D для объявления шаблонов используются круглые скобки. А мне вот, наоборот, нравится, благодаря этому, инстанцирование шаблона выглядит похожим на вызов функции. |
| Автор: amk 30.03.14, 13:56 |
| Да, выглядит как недоделка. Если над объекты типов A и B можно сложить, то тип результата а этой точке известен, значит ничего не должно мешать и определению типа возвращаемого значения. |
| Автор: applegame 30.03.14, 14:04 |
| Цитата amk @ Это возможно, но вот таким странным образом:Да, выглядит как недоделка. Если над объекты типов A и B можно сложить, то тип результата а этой точке известен, значит ничего не должно мешать и определению типа возвращаемого значения. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Зачем там нужен этот дурацкий decltype непонятно. template<typename A, typename B> auto hellSum(A a, B b) -> decltype(a + b) { return a + b; } |
| Автор: Qraizer 30.03.14, 16:01 |
| Затем: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Очень информативно увидеть в интерфейсе просто auto без информации о реализации. template<typename A, typename B> auto hellSum(A a, B b) -> decltype(a + b); |
| Автор: Мяут-Настоящий 30.03.14, 17:00 |
| <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> #include <iostream> using namespace std; class C { }; class D: public C { }; class B { }; class A { bool var; public: A(bool var) : var(var) {} C operator*(const B& b) { return C(); } D operator+(const B& b) { return D(); } bool get_var() { return var; } }; template<typename A, typename B> auto hellArithmetics(A a, B b) -> decltype(a * b) { /* auto - C or D */ if(a.get_var()) { return a * b; } return a + b; } int main() { A a1(true); A a2(false); B b; C c1 = hellArithmetics(a1, b); C c2 = hellArithmetics(a2, b); return 0; } |
| Автор: applegame 30.03.14, 17:15 |
| Все прекрасно. Информация дается в комментариях, а не в безумном decltype, который, кстати, может содержать трехэтажные конструкции. Эту работу, ИМХО, может и должен делать компилятор. Особенно есди учесть, что интерфейсы шаблонов функций без тела этих функций полезны в C++ чуть более, чем никогда. Добавлено Мяут-Настоящий, что это? Типа пример зачем нужен decltype? Он не нужен: http://dpaste.dzfl.pl/4333f7a197f7 <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> class C { }; class D: C { }; class B { }; class A { bool m_var; this(bool var) { m_var = var; } C opBinary(string op: "*")(const B b) { return new C(); } D opBinary(string op: "+")(const B b) { return new D(); } bool var() { return m_var; } }; auto hellArithmetics(A, B)(A a, B b) { if(a.var) { return a * b; } return a + b; } int main() { auto a1 = new A(true); auto a2 = new A(false); auto b = new B; C c1 = hellArithmetics(a1, b); C c2 = hellArithmetics(a2, b); return 0; } |
| Автор: MyNameIsIgor 30.03.14, 18:55 |
| Цитата applegame @ Функция должна вернуть несколько значений, и хочется чтобы доступ к значениям был бы как к полям структуры, а не по индексу, как в обычном плюсовом кортеже. А почему не объявить структуру и не вернуть её из функции? Изврата захотелось? Типа Это через какую только жопу гланды не выдирают вместо того, чтобы сделать функции, возвращающие несколько значений, как, например, в Go. Впрочем, хотите через жопу - получите. Гораздо лучше дишных извращений на пустом месте. |
| Автор: applegame 30.03.14, 19:08 |
| Цитата MyNameIsIgor @ У меня таких функций вагон и маленькая тележка, извратом будет как раз объявлять вагон и маленькую тележку структур.А почему не объявить структуру и не вернуть её из функции? Изврата захотелось? Цитата MyNameIsIgor @ О да, это же какая жопа написать packTuple!(...) или просто tuple(...), если обычного кортежа достаточно.Это через какую только жопу гланды не выдирают вместо того, чтобы сделать функции, возвращающие несколько значений, как, например, в Go. Цитата MyNameIsIgor @ Это простите, херня, никакого отношения к сабжу не имеющая.Впрочем, хотите через жопу - получите. Гораздо лучше дишных извращений на пустом месте. Вы батенька, как всегда, пукаете в лужу. "Если C++ что-то не умеет, то это не нужно" - вот ваш девиз. Научитесь уже отвечать по существу. |
| Автор: MyNameIsIgor 30.03.14, 19:37 |
| И зачем? Нет, это будет явная декларация. Не прощаю. А за нецензурную брань модератор взыщет. Т.е. если что-то сделали иным способом, нежели ваш, то к теме это отношения не имеет? ![]() А вы продолжаете нюхать ![]() Нет, я лишь предлагаю делать по-уму. Уже посмотрели как возвращаются несколько значений в Go? Это во-первых. Во-вторых, вы плюсы на уровне второклашки то не осилили, откуда вам знать, что они могут? |
| Автор: Qraizer 30.03.14, 20:21 |
| Цитата applegame @ Молодец! Сам упомянул компилятор. А ну-ка, покажи, как компилятор разгребёт комменты. И с чего он вообще будет это делать. В Плюсах auto с последующим decltype введены для упрощения квалификацированных идентификаторов, каковые становятся возможны только после списка параметров, а отнюдь не для автовывода типа результата. Автовывод, конечно, есть, но для частных случаев.Все прекрасно. Информация дается в комментариях, а не в безумном decltype, который, кстати, может содержать трехэтажные конструкции. Эту работу, ИМХО, может и должен делать компилятор. Цитата applegame @ Та ладно. И как давно это так? Даже без extern template это встречалось нередко. Интерфейс интерфейсом, но параметризация шаблонов отнюдь не ограничивается пользовательскими желаниями, нередко эта параметризация выбирает платформенные специализации, а в этом случае обычная раздельная компиляция вполне применима и легко реализуется. Особенно если учесть, что интерфейсы шаблонов функций без тела этих функций полезны в C++ чуть более, чем никогда. |
| Автор: D_KEY 30.03.14, 20:54 |
| Цитата applegame @ Вспомнил про затихший холиворчик. Продолжу продвижение D. Функция должна вернуть несколько значений, и хочется чтобы доступ к значениям был бы как к полям структуры, а не по индексу, как в обычном плюсовом кортеже. Вот эта маленькая магия сама объявляет структуру с полями названными как переменные переданные в параметры и заполняет ее значениями из этих же переменных. Структура объявляется внутри функции (кстати, а плюсы так умеют?), а значит не гадит в глобальную область видимости. Рекурсивный миксин плюс немножко статической рефлексии. Дешево, сердито и красиво, плюсики так не умеют и вряд ли когда сумеют: http://dpaste.dzfl.pl/d09ce6ded86b <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template packTuple(ARGS...) { template Decls(alias value, ARGS...) { mixin("typeof(value)" ~ __traits(identifier, value) ~ ";"); static if(ARGS.length) mixin Decls!ARGS; } struct Tuple { mixin Decls!ARGS; } auto packTuple() { return Tuple(ARGS); } } auto foo() { int fieldInt = 10; string fieldString = "test"; return packTuple!(fieldInt, fieldString); } void main() { auto result = foo(); assert(result.fieldInt == 10); assert(result.fieldString == "test"); } Не очень понял, что ты этим выиграл. Коллеги твои вряд ли будут довольны. Да и ты сам через полгодика не обрадуешься. |
| Автор: D_KEY 30.03.14, 21:12 |
| В комментариях? Информация о типах? В языке со статической типизацией? Мда.. А как же самодокументируемость? Нет, я за возможность как указания типа, так и явного decltype/typeof. Кстати, в D же это возможно, о чем ты споришь? В C++14 обязательность decltype уходит. |
| Автор: applegame 30.03.14, 22:16 |
| Цитата D_KEY @ Уже больше времени прошло, и никаких проблем. Удобно, всем наоборот нравится. Я же не везде его пихаю. Там где название типа действительно важно, я указываю его явно. Но в проекте много всяких хелперов, мелких вспомогательных функций и шаблонов, где в общем-то глубоко начхать на название типа. Название функции говорит само за себя, а в комментах описано, что именно она возвращает.Не очень понял, что ты этим выиграл. Коллеги твои вряд ли будут довольны. Да и ты сам через полгодика не обрадуешься. Зачем о типах? Описание возвращаемого значения и все. Тип не важен. Типы пусть знает и проверяет компилятор. Одно из преимуществ D, что он при желании позволяет писать в стиле динамических языков. Автоматическое выведение типов, auto и прочие радости. Легкость работы с динамическими языками, но при этом типизация статическая, что позволяет ошибки с типами находить compile-time. Можно до последнего цепляться за древний уродливый стиль с громоздкими иерархиями классов, тоннами типов объявленных явно и т.п., но это прошлый век. Даже сам C++ эволюционирует, внезапно, может и не совсем по пути D, но явно в туже сторону Цитата D_KEY @ Обязательность и напрягает. Представь что функция возвращает тип, который можно вывести, но только этот тип будет занимать три строчки кода. Информативность таких кракозябров (особенно в C++) - нулевая. Какая-нибудь лямбда со страшной сигнатурой. А может и не лямбда, может быть функтор, да что угодно, главное что callable. Плевать на тип, главное, что потом с этим значением можно делать.Кстати, в D же это возможно, о чем ты споришь? В C++14 обязательность decltype уходит. Ага, я же говорю дрейфуем туда, куда D ушел уже давным давно. |
| Автор: D_KEY 30.03.14, 22:43 |
Так о толку то от твоего "давным давно"? Эволюционное развитие - один из козырей C++. Принимается новый стандарт, я обновляю компилятор и, возможно, добавляют флажок поддержки нового стандарта в свой проект и начинаю применять новые полезные для меня фишки, ничего не переписывая и ничего не ломая. Добавлено Имена полей - это тоже информация о типе. Добавлено Возможно, ты и прав, но лично я никакого профита от D не вижу... Даже от Go больше потенциальной пользы, как мне кажется. За счёт простоты. Хотя и от него я не в восторге. |
| Автор: applegame 30.03.14, 22:59 |
| http://habrahabr.ru/post/183488/ Цитата D_KEY @ Дело вкуса, наверное. Для меня профит прост: один и тот же код я пишу на C++ значительно медленнее, чем на D.Возможно, ты и прав, но лично я никакого профита от D не вижу... Даже от Go больше потенциальной пользы, как мне кажется. За счёт простоты. Хотя и от него я не в восторге. C++ гораздо "многословнее", а метапрограммирование заметно запутаннее. P.S. Вот кстати статейка на хабре в тему - http://habrahabr.ru/post/183488/ |
| Автор: D_KEY 30.03.14, 23:42 |
Так на Питоне задачи ещё быстрее решаются вопрос в том, какие возможности ты имеешь, сколько готовых(своих и сторонних) решений можешь применить, скольким людям это будет понятно и результат какого качества ты получишь. |
| Автор: OpenGL 31.03.14, 07:37 |
| Кстати, а он действительно "14" будет? Или они опять слишком оптимистичны? |
| Автор: korvin 31.03.14, 08:49 |
| Ну может как раз до C++0xF дотянут. =) |
| Автор: applegame 31.03.14, 09:25 |
| Да, но Питон все-таки язык с динамической типизацией, со всеми вытекающими. D же с одной стороны язык с полноценной статической типизацией, с другой позволяет легко обходится во многих случаях без обозначения типов. Любители вон даже накропали препроцессор для конвертации некоего питонообразного языка Delight в D и наоборот D в Delight. |
| Автор: Qraizer 31.03.14, 12:58 |
| applegame, я не знаю, что там такого особенного с D по этому вопросу. Тамошний пример вполне попадает под частный Плюсовый случай. |
| Автор: D_KEY 31.03.14, 13:36 |
| Qraizer, таким образом auto использоваться вроде только в C++14 можно будет, а сейчас(C++11) вроде формально требуется decltype там, который в этом случае написать проблематично. |
| Автор: Qraizer 31.03.14, 14:13 |
| Ну да. Там и варнинг есть. Сейчас единственным таким частным случаем является лямбда. Добавлено Ну так а велика разница? |
| Автор: applegame 31.03.14, 14:37 |
| Да, велика. Функция может быть шаблоном, а лямбда нет. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto g = generator!MersenneTwister(5); |
| Автор: Qraizer 31.03.14, 17:43 |
| Когда это дополнительный уровень косвенности был проблемой? Да и временно это. |
| Автор: applegame 28.04.14, 21:19 |
| Скотт Майерс участвует в DConf 2014 Еще один известный плюсовик в лагере D P.S. Правда он дружбан Александреску, который его, видимо, и сбил с пути истинного. |
| Автор: D_KEY 28.04.14, 21:22 |
| Цитата applegame @ Скотт Майерс участвует в DConf 2014 Еще один известный плюсовик в лагере D P.S. Правда он дружбан Александреску, который его, видимо, и сбил с пути истинного. ![]() Почему сбил? От C++ вроде ни один ни другой не отказываются. Добавлено Вообще C++ сейчас развивается достаточно хорошо. Не знаю, как там будет дальше, но сейчас хороший сбалансированный темп, за которым успевают и компиляторы и разработчики. |
| Автор: applegame 28.04.14, 21:25 |
Это была шутка Добавлено Кстати, ИМХО, интересные конфы, даже не для программистов на D. Добавлено Вот, например, будет презентация об использовании рефлексии во время компиляции - http://dconf.org/2014/talks/neves.html |
| Автор: applegame 28.05.14, 14:50 |
| DConf 2014 завершилась. К сожалению видеозаписи выступлений только начинают выкладываться в общий доступ. Но уже есть keynote Скотта Майерса. Он там по большей части говорит о C++, так что, возможно, любителям C++ тоже будет весьма интересно посмотреть это выступление. The Last Thing D Needs - Scott Meyers |
| Автор: D_KEY 28.05.14, 16:24 |
| Цитата applegame @ Но уже есть keynote Скотта Майерса. Он там по большей части говорит о C++, так что, возможно, любителям C++ тоже будет весьма интересно посмотреть это выступление. Ну так. Мне кажется слабовато с точки зрения аргументации для данного холивара. |
| Автор: korvin 28.05.14, 17:14 |
| Если ты про фразу applegame (а не про видео, я его не смотрел), то она еще и двусмысленна, т.к. по ней непонятно — это «за» C++ или D. =) |
| Автор: applegame 28.05.14, 17:19 |
| Это вообще не аргументация с точки зрения холивара. Холивар, по-моему, уже никому не интересен. |
| Автор: D_KEY 28.05.14, 17:53 |
| Цитата applegame @ Это вообще не аргументация с точки зрения холивара. Холивар, по-моему, уже никому не интересен. Мне не интересен холивар только потому, что тут нет интересной аргументации Добавлено Цитата korvin @ Если ты про фразу applegame (а не про видео, я его не смотрел), то она еще и двусмысленна, т.к. по ней непонятно — это «за» C++ или D. =) Видео против (сложности) C++ |
| Автор: applegame 28.05.14, 18:13 |
Сомневаюсь, что в природе вообще существует интересная для тебя аргументация в холиворе D vs C++ ![]() На вас ничего не действует ни UDA, ни строковые миксины, ни шаблоны, ни CTFE. На все ответ только один - "ну и чо?" ![]() Только Qraizer признал, что в обобщенном программировании D бьет C++. Добавлено Ну не совсем против. Майерс говорит также о том, что для C++ эта сложность, фактически, вынужденная мера. |
| Автор: D_KEY 28.05.14, 18:49 |
| Цитата applegame @ На вас ничего не действует ни UDA, ни строковые миксины, ни шаблоны, ни CTFE. На все ответ только один - "ну и чо?" ![]() Надо заметить, что не только на меня это не действует. Вон у go даже, наверное, аудитория шире уже. Цитата Только Qraizer признал, что в обобщенном программировании D бьет C++. А чего тут признавать? Бьёт. Только насколько это существенно будет в реальной жизни? |
| Автор: applegame 28.05.14, 20:43 |
Ага, кроме тебя еще на полтора тролля не лействует ![]() Даже? За Go стоит Google, а D сумел развиться до текущего уровня без поддержки крупных корпораций. Популярность Go - не более, чем хорошая реклама. |
| Автор: korvin 29.05.14, 02:10 |
| Ну да, конечно. Сложно признать, что простой (если не сказать примитивный, по сравнению с D) язык оказался более полезен на практике, потому что вместо задрачивания мало кому нужных языковых фенечек, люди писали полезные библиотеки? =) Добавлено Собственно golang dlang… |
| Автор: D_KEY 29.05.14, 05:22 |
| Цитата applegame @ Даже? За Go стоит Google, а D сумел развиться до текущего уровня без поддержки крупных корпораций. Популярность Go - не более, чем хорошая реклама. С чего ты взял? |
| Автор: applegame 29.05.14, 05:34 |
| Цитата korvin @ Ага прямо как PHP.Ну да, конечно. Сложно признать, что простой (если не сказать примитивный, по сравнению с D) язык оказался более полезен на практике, потому что вместо задрачивания мало кому нужных языковых фенечек, люди писали полезные библиотеки? =) Кстати либы для D надо искать тут А вообще, если верить вот этому http://www.tiobe.com/index.php/content/pap...tpci/index.html, то Go все же отстает от D. Fail. |
| Автор: D_KEY 29.05.14, 05:40 |
| При чем тут PHP? Скорее как Python и Ruby. Добавлено Цитата applegame @ А вообще, если верить вот этому http://www.tiobe.com/index.php/content/pap...tpci/index.html, то Go все же отстает от D. Fail. Сколько лет D? Добавлено А вот на каком-нибудь github, вроде как D сильно отстает от Go. Если я правильно помню. |
| Автор: applegame 29.05.14, 05:47 |
| Фактически первая стабильная версия компилятора вышла в 2007 году, а Go в 2009. Огромная разница, да? А теперь сравни Google и Digital Mars. Добавлено |
| Автор: D_KEY 29.05.14, 05:49 |
| Кстати, на D уже пишут проекты в духе influxdb(на go написана, если что)? Добавлено Цитата applegame @ Фактически первая стабильная версия компилятора вышла в 2007 году, а Go в 2009. Огромная разница, да? То, что стабильная версия вышла так поздно для D - это тоже недостаток, а не повод сделать язык моложе, чем он есть. Цитата А теперь сравни Google и Digital Mars. Go занималась не очень большая команда. И особой помощи от google я не вижу(сравни, например, с продвижением C# от MS). |
| Автор: korvin 29.05.14, 05:52 |
![]() =)) А сипсок "production"-пользователей D где можно посмотреть? |
| Автор: applegame 29.05.14, 05:54 |
| korvin, попробуй Ctrl-F5, так как у меня никаких ошибок нет. Списка не знаю, но некоторых я перечислял в этой теме. |
| Автор: D_KEY 29.05.14, 05:54 |
| За что(отсутствия навязывания Go) гуглу большое спасибо, а то мне лично go не нравится. Но в отличие от D он хотя бы практичен. |
| Автор: korvin 29.05.14, 05:55 |
| Вообще-то в 2012-м. До Go 1 ни компилятор, ни язык не были стабильны. |
| Автор: applegame 29.05.14, 05:56 |
| Цитата D_KEY @ На самом деле возраст языка вообще ничего не значит, если уж на то пошло.Ты работаешь в Google? Или так, просто потрепаться? То, что стабильная версия вышла так поздно для D - это тоже недостаток, а не повод сделать язык моложе, чем он есть. |
| Автор: korvin 29.05.14, 05:57 |
| Жаль, была бы еще одна линейка. =) |
| Автор: D_KEY 29.05.14, 06:01 |
| Значит в контексте распространения. Цитата Ты работаешь в Google? Или так, просто потрепаться? Мы говорили о продвижении языка. Вот MS продвигала C#, ты видишь, что Google продвигает Go так же? А как развивался Go вроде не закрытая информация. |
| Автор: applegame 29.05.14, 06:01 |
| Но представлен был в 2009. Фактическое развитие D началось лет пять назад. Хотя он и появился он в 2001-году все это время он находился в замороженном состоянии. Добавлено На самом деле уже только то, что этот язык был представлен Google имеет огромное значение. О нем узнало очень много народу. А о D мало кто знает. |
| Автор: korvin 29.05.14, 06:03 |
| А какую помощь (в продвижении Go) оказывал Google? Пара выступлений Пайка? |
| Автор: D_KEY 29.05.14, 06:04 |
| Цитата applegame @ Хотя он и появился он в 2001-году все это время он находился в замороженном состоянии. Что тоже отрицательно сказалось на его восприятии. Сколько не читаю холиваров про него, всегда есть истории про "заинтересовался-загорелся-попробовал-плюнул" |
| Автор: korvin 29.05.14, 06:06 |
| Ты говорил про стабильные версии, определись уж. |
| Автор: D_KEY 29.05.14, 06:08 |
| Цитата applegame @ На самом деле уже только то, что этот язык был представлен Google имеет огромное значение. Dart'у что-то это не помогло. Цитата О нем узнало очень много народу. А о D мало кто знает. Как раз приведенный тобой индекс tiobe говорит об обратном. На фоне этого, более широкое использование Go в открытых проектах говорит о том, что Go практичнее и вызывает больше интереса в качестве языка реальной разработки. Добавлено Опять же, Rust, как мне кажется, уведет еще людей с D. Если, конечно, у них все пойдет хорошо. |
| Автор: applegame 29.05.14, 10:33 |
| Цитата D_KEY @ Ага. Я тоже долго был в этой категории, но в какой-то момент понял, что D достиг той точки, когда уже можно перейти на него. Сколько не читаю холиваров про него, всегда есть истории про "заинтересовался-загорелся-попробовал-плюнул" ![]() Добавлено Цитата D_KEY @ Может быть, а может и нет. ЕМНИП, в Rust нет полноценных шаблонов, вместо них дженерики. Опять же, Rust, как мне кажется, уведет еще людей с D. Если, конечно, у них все пойдет хорошо. Добавлено Ты хоть сам веришь-то в то что D более известен, чем Go? |
| Автор: D_KEY 29.05.14, 11:07 |
| Цитата applegame @ Цитата D_KEY @ Может быть, а может и нет. ЕМНИП, в Rust нет полноценных шаблонов, вместо них дженерики.Опять же, Rust, как мне кажется, уведет еще людей с D. Если, конечно, у них все пойдет хорошо. Там дженерики вроде тип не "забывают" в реализации(т.е. кодогенерация эффективна) плюс есть trait'ы, специализации(но только через реализацию trait'ов) и пр. И, самое главное, там есть полноценные макросы. Добавлено Нет, но tiobe вроде как раз на поисковые запросы и пр. вещи смотрит. Так что "если верить" tiobe, то... |
| Автор: applegame 29.05.14, 12:00 |
| Цитата D_KEY @ Полагаю, что известность и популярность, хоть и связанные вещи, но все же разные. Нет, но tiobe вроде как раз на поисковые запросы и пр. вещи смотрит. Так что "если верить" tiobe, то... ![]() |
| Автор: DarkEld3r 17.06.14, 13:06 |
| Как по мне, "duck typing" С++ шаблонов мощнее. В расте ведь если класс поддерживает нужную операцию, но не через требуемый трейт, то облом. Плюс перегрузки функций нет - из-за этого, по моему, обобщённый код писать менее удобно. Хотя остальной набор фич мне тоже больше Д-шного нравится. |
| Автор: D_KEY 17.06.14, 13:09 |
| Цитата DarkEld3r @ В расте ведь если класс поддерживает нужную операцию, но не через требуемый трейт, то облом. Так ты заведи Цитата Плюс перегрузки функций нет - из-за этого, по моему, обобщённый код писать менее удобно. Тут спорно. Есть мнение, что через трейты это делать не сложнее, при этом код будет более понятен и структурирован. Но сам я активно не писал на трейтах, потому утверждать это не берусь. Но похоже на правду. |
| Автор: DarkEld3r 17.06.14, 15:17 |
| А если класс или генерик не мои и менять нежелательно/невозможно? Я только за, если бы такие ограничения были опциональными (типа как разрабатываемые концепты). Или я чего-то не понимаю или не согласен. Скажем как реализовать подобие std::begin из С++? По моему, перегрузка - это удобно. |
| Автор: D_KEY 17.06.14, 15:20 |
| Так их и не надо менять. У нас есть чей-то trait и есть чей-то тип, а мы можем написать для этого типа нужный impl этого trait'а. Добавлено Ну там все-таки другой подход к обходу коллекций. У них есть метод iter, который возвращает объект, соответствующий trait'у Iterator. Есть trait'ы для видов итераторов(произвольного доступа, последовательные и т.д.). У итератора есть метод next, который двигает итератор и возвращает опциональное значение. Если двигаться некуда, то он вернет None. Добавлено Но я плохо знаю Rust и они частенько меняют фичи. Посмотрим, что выйдет, когда они его доделают. |
| Автор: applegame 21.06.14, 04:50 |
А чем, скажем, тебе лично, D_KEY, не нравится D? |
| Автор: D_KEY 21.06.14, 06:13 |
| Наверное он мне просто неинтересен. Не вижу, где и зачем его применять. |
| Автор: applegame 21.06.14, 09:45 |
| Понятно. |
| Автор: DarkEld3r 26.06.14, 11:56 |
| Это был просто пример. В куче случаев мне кажется удобным наличие перегрузки. Да хотя бы to_string или min/max. И если вещи типа то_стр на имплах делаются "вполне нормально", то если аргументов несколько, то уже получается более бредово. Ещё что-то читал, что макросы у них не попадают в неймспейсы, что тоже не очень здорово. Впрочем, я раст знаю ещё хуже и очень может быть, что просто слишком привык к тому как эти вещи делаются в С++. Возможно, кто-то, кто знает язык лучше, сумеет разубедить (пока они его не "зарелизят" за изучение браться лень). |
| Автор: D_KEY 26.06.14, 12:00 |
| аналогично |
| Автор: Мяут-Настоящий 26.06.14, 12:09 |
| Цитата не пора ли C++ потихоньку готовиться к пенсии? Вот вам: Почему Ваза утонул, а С++ всё ещё на плаву http://habrahabr.ru/company/infopulse/blog/227529/ |
| Автор: DarkEld3r 26.06.14, 13:50 |
| А можно я Сразу говорю - глубоко язык не изучал и ничего хоть немного обьёмного писать не пробовал. Тем не менее, в итоге сложилось не самое лучшее впечатление. Вроде, много улучшений, но в итоге получается так себе. Взять хотя бы строки. В С++ "raw string literals" появились не так давно. В D они есть, но в виде кучи разных вариантов со своими (местами не очень прозрачными) правилами. Например: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto a1 = "just a string"; auto a2 = r"raw string\n\r"; auto a3 = `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. Почему бы не удалили, в таком случае. Или хотя бы депрекейтед обьявили. Плюс строки с задаваемыми разделителями. Правда в качестве "разделителя" может быть только один символ и только из этого списка: "[(<{" (так на сайте написано, на самом деле такое тоже работает (q"|raw string\n\r|"), а вот такое уже нет (q"!raw string\n\r!"). Разделители допускают вложение (если честно, то не понял зачем это надо): <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto а5 = q"/test/eee/"; // Error. auto a6 = q"[]]"; // Error. auto a7 = q"[[]]"; // OK, a7 = "[]". Можно задавать разделители из более чем одного символа, но при этом надо разбивать такой литерал на несколько строк (разделители должны быть на разных строках): <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto a1 = q"EOS Test string EOS"; Вот так написать нельзя, ну и отступ попал бы в строку: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto a1 = q"EOS Test string EOS"; На мой взгляд, это не очень удoбно. Дофига правил и исключений для одной сущности. И это при том, что язык обьявляют более простым, чем С++. При этом в С++ как раз сделали нормально без необходимости строки разрывать и ломать форматирование: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> R"delimiter(The String Data \ Stuff " )delimiter" Опять же, если на их сайте бегло всякие сравнения посмотреть, то местами лучше (пусть даже гораздо лучше), местами примерно так же, а есть и такое, что повторить не получится. Может оно и "не надо" или на D оно иначе делается, но в табличке хватает простых "No" со стороны D. Ну и ГЦ, конечно. В этом плане подход раста намного лучше. При этом сторонники языка утверждают, что "если надо", то можно без него. Но при этом приходится отказываться от кучи вещей, которыми в С++ жертвовать не обязательно. Причём библиотеки, где отказались от классов, чтобы ГЦ не трогать и сделали всё на структурах, ещё и пользователя ограничивают. Да и мне вообще подход С++ ближе, где программист сам решает где и что размещать, а не язык за него. Тем более дурацким показалось, что в D есть (было) ключевое слово scope для размещения классов на стеке, но его объявили устаревшим с идиотским обьяснением - "а вдруг такой обьект передадут за пределы функции и получат грабли". Ведь это компилятор может и проверить. В общем, есть плюсы, но и минусов хватает. В итоге С++ выигрывает так как: 1. Грабли уже известны. 2. Инфраструктура лучше. Да и со скоростью развития теперь вопрос. В С++ много всякого обещают. За D правда не слежу, но там даже не все заявленые фичи работают (да хотя бы multiple alias this), потом всё обещаются стандартную библиотеку допилить и компилятор языка на D перевести. А с развитием что? |
| Автор: MyNameIsIgor 26.06.14, 14:08 |
| Угу, и самый популярный комментарий Цитата потому, что С++ не тонет |
| Автор: JoeUser 22.08.14, 18:13 |
| Всю переписку ниасилил, но скажу одно - "вы все дураки, я одна стою в белом пальто, красивая" © Если скрестить как-то нетипизированность (ну или допущение) и Цэ++ ... это была бы бомба! Скажу более, не юзавши boost, но слышавши про его тип ::any - тлеет надежда, что строгую типизацию вынесут в разряд "must haVe", вместо обязалова. А пока ... Perl - the best of the best. Даже не думайте спорить! |
| Автор: D_KEY 22.08.14, 19:23 |
| Что это? Неявная типизация? Или динамическая типизация? Или что? Добавлено По контексту больше похоже на динамическую. Но что тогда оставить в "смеси" от C++? Там все полезное так или иначе связано со статической типизацией. |
| Автор: korvin 24.08.14, 05:10 |
| Ты смог определить контекст в этом потоке сознания? =) |
| Автор: Axis 30.10.14, 09:43 |
| Да что-то сколько уже Александреску пиарит D, а воз и ныне там. |
| Автор: applegame 04.11.14, 07:01 |
| Это не так. Набирает популярность. Медленно так как нет мощной финансовой поддержки. |
| Автор: Kray74 04.11.14, 08:11 |
| Ага, и facebook совсем не причем, правда? |
| Автор: applegame 04.11.14, 09:02 |
| Ага, Facebook действительно не причем. Они не спносируют D. Иногда, усилиями того же Александреску, фейсбук дает вознаграждение за фикс некоторых критических для них багов. Но тоже самое делают и другие пользователи D. Вот что пишет сам Александреску: Цитата Просто мощнейшая финансовая поддержка, правда? И фейсбук в ней участвует незначительно. A $150 monthly contribution would cover our hosting costs. $1000 per month would cover the yearly basic costs for DConf. $500 more per month would add A/V for the conference. We've had DConf partially sponsored, but it's good to have autonomy. Some more couple thousands would buy us things like a web designer. $2000 or more per month would possibly get us a person to put on things that are urgent and important. We're very much limited by the lack of funds. Andrei |
| Автор: D_KEY 04.11.14, 12:36 |
| Ну у C++ с финансовой поддержкой тоже не густо было. Да и сейчас особо нет. У питона, насколько я знаю, ситуация не лучше. Где же комьюнити D? |
| Автор: applegame 04.11.14, 12:48 |
| Нет? А как же Apple со своим clang, Microsoft со своим Visual Studio, Intel со своим ICC? Очевидно там кодят добровольцы совершенно бесплатно. А уж кто в комитете заседает, наверняка волонтеры. Герб Саттер (руль комитета), в Microsoft только числится, а так все за свой счет, бедняга. |
| Автор: MyNameIsIgor 04.11.14, 13:20 |
| Цитата applegame @ Нет? А как же Apple со своим clang, Microsoft со своим Visual Studio, Intel со своим ICC? Они поддерживают то, что уже популярно, и на чём написано огромное количество кода. Цитата applegame @ Герб Саттер (руль комитета), в Microsoft только числится, а так все за свой счет, бедняга. Такие же намёки на мордокнигу были отвергнуты. Саттеру теперь что, на пожертвования жить? Компании участвуют в стандартизации не для того, чтобы продвигать язык, а потому что являются его пользователями. А вообще C++ (как и многие другие языки) стал популярным не из-за вложенных в него денег, а просто потому что c'est la vie. |
| Автор: Мяут-Настоящий 04.11.14, 13:47 |
| applegame, D_KEY говорит "было", то есть наверное про времена когда C++ был отходом от постороннего проекта Страуструпа. Который внезапно заинтересовал бизнес в те времена. Хотя какая-то поддержка от Bell Labs была наверное, надо бы перечитать Эволюцию. |
| Автор: applegame 04.11.14, 14:09 |
| Реально C++ не было альтернативы, да и не нужна она была. Бизнесу просто больше нечем было заинтересоваться. C++ популярен не потому что он так хорош, а потому что он был первым в своей нише, да и то что он совместим с C тоже очень сыграло на руку. |
| Автор: MyNameIsIgor 04.11.14, 14:47 |
| Цитата applegame @ Реально C++ не было альтернативы, да и не нужна она была. Бизнесу просто больше нечем было заинтересоваться. C++ популярен не потому что он так хорош, а потому что он был первым в своей нише, да и то что он совместим с C тоже очень сыграло на руку. Как минимум были Эйфель и Objective-C |
| Автор: D_KEY 02.12.14, 14:30 |
А D тут при чем? |
| Автор: Flex Ferrum 02.12.14, 14:31 |
| Да, ближайшая в топе тема из серии C++ vs XXX Добавлено D_KEY, впрочем, нашёл более подходящую. |
| Автор: Мяут-Настоящий 02.12.14, 14:42 |
| Я хочу этот язык! |
| Автор: korvin 05.12.14, 15:18 |
| Чтобы писать порно-пасьянсы? =)) А вообще, как там D, еще не сдох? Добавлено В отличие от C++ они ж вроде проприетарны. Plan 9 тоже как бы был как альтернатива монструозному Unix, до Linux, но из-за закрытости (тогда) никто их идеями не воспользовался. |
| Автор: applegame 05.12.14, 16:33 |
| Нормалек. Обрастает либами, биндингами к сишным либам и IDEшками. |
| Автор: D_KEY 05.12.14, 17:10 |
| Ну совсем он вряд ли сдохнет. Кстати, был ли у нас холивар Go и D? После выхода Rust можно будет попробовать устроить Rust vs D. Мне Rust кажется более перспективным. |
| Автор: DarkEld3r 08.12.14, 13:56 |
| Например? Мне тоже, но начал "изучать" язык и постоянно какие-то мелочи "расстраивают". Про отсутствие перегрузки уже говорил, вроде, не смертельно, но местами получается уродливо. Например, вот "конструкторы" хеш таблицы: 1. HashMap::new() 2. HashMap::with_capacity() 3. HashMap::with_hasher() 4. HashMap::with_capacity_and_hasher() А если ещё параметр добавить захочется?.. Кстати, создавать этот контейнер из списка, вроде, невозможно. Дефолтных значений у параметров тоже "пока" нет. Или то, что буквы для методов "экономят" - "len" вместо length или size. Карго, опять же, заточен под определённые вещи и шаг в сторону уже оборачивается неудобствами. Хаскелевский кабал, к примеру, вообще никаких вопросов не вызвал. |
| Автор: D_KEY 08.12.14, 15:48 |
Я бы подождал релиза Rust |
| Автор: applegame 08.12.14, 21:29 |
| VisualD DDT Mono-D Лично я сижу в Sublime Text 3 Для совсем уж красноглазых есть плагины для vim и какой-то там официальный режим emacs. Либы тут - http://code.dlang.org/ |
| Автор: DarkEld3r 09.12.14, 13:57 |
| Просто подумал, что я что-то пропустил и появились "чисто-Д" IDE. Про плагины к другим IDE в курсе. Это принципиально ничего не изменит, насколько я знаю. До версии 1.0 они хотят только всякие "мелочи" подрихтовать. При этом многое не успевают и оно перенесено "на потом". После релиза активная разработка продолжится, планируется по "стабильному релизу" каждые шесть недель. |
| Автор: applegame 09.12.14, 16:12 |
| А это что значит? Недавно появилась некая альфа IDE - https://github.com/BBasile/Coedit не знаю подходит ли она под определение "чисто-Д" IDE. |
| Автор: DarkEld3r 10.12.14, 08:54 |
| Я понимаю, что это не принципиально, но было бы интересно посмотреть на новую IDE созданную именно для D. Ещё лучше, если бы она была сама написана на D. Это было бы своего рода индикатором наличия заинтересованного сообщества вокруг языка. Вон для хаскеля (и на хаскеле) написали Leksah, для Racket тоже. Ну или если бы в существующих IDE "официально" добавили поддержку, то тоже было бы интересно. Ещё раз - я понимаю, что это не обязательно. У раста ситуация такая же и тоже вряд ли кто-то кинется писать новую ИДЕ. Но на результат я бы посмотрел. |
| Автор: Kray74 10.12.14, 15:27 |
| Современные IDE, как правило, - комбайны, работающие с несколькими языками через плагины, так что смысла писать новую IDE под один язык не особо много. |
| Автор: reinterpret_alexey 25.12.14, 16:43 |
Хороший С++ класс - это такой, глядя на который появляется чувство скуки. |
| Автор: korvin 26.12.14, 21:25 |
| Перенастрой подсветку кода, чтоб было нескучно, спроси у Попова как. |
| Автор: Qraizer 26.12.14, 21:58 |
| Я тебя, надеюсь, правильно понял, korvin? |
| Автор: korvin 28.12.14, 11:34 |
| Э-м. Ну я даже не представляю, какие есть варианты понимания моего сообщения, поэтому не знаю, что ответить. |
| Автор: JoeUser 15.05.15, 18:19 |
| Цитата Kray74 @ Современные IDE, как правило, - комбайны, работающие с несколькими языками через плагины, так что смысла писать новую IDE под один язык не особо много. Бегло глянул в сети - есть в разработке Qt Creator plugin for D language support, не пробовал пока. На гите указано, что два релиза уже вышло. |
| Автор: applegame 22.10.15, 16:37 |
Давненько я тут не писал. ![]() Случилась перемога: JSON-парсер написанный на D стал самым быстрым JSON-парсером среди всех языков, обогнав более чем в два раза (!) предыдущего чемпиона RapidJSON написанного на C++. Бенчмарки Обсуждение на реддите Одна из причин такой шустрости, а заодно преимущество D перед C++: Благодаря использованию opDispatch обращения к полям JSON-объекта возможно как к свойствам D-шной структуры. Например: json.coordinates будет скомпилировано в json.singleKey!("coordinates") - вызов функции с одним компайл-тайм аргументом и без ран-тайм аргументов вообще. В итоге парсер уже на стадии компиляции "знает" какие поля ему нужно парсить и валидировать, а какие можно пропустить. |
| Автор: korvin 22.10.15, 21:01 |
| Цитата applegame @ обогнав более чем в два раза (!) предыдущего чемпиона RapidJSON написанного на C++. Ага, 226 MB vs 1 MB. P.S. И да, баян, на LOR'е уже обсудили. =) https://www.linux.org.ru/news/opensource/12...omment-12028092 https://www.linux.org.ru/news/opensource/12...00?cid=12028749 https://www.linux.org.ru/news/opensource/12...00?cid=12028855 https://www.linux.org.ru/news/opensource/12...00?cid=12028984 |
| Автор: applegame 22.10.15, 21:41 |
| Это вырвиглазная SAX-версия, которой без слез нельзя пользоваться, тем более, что по скорости все равно проигрывает. А юзабельный DOM-вариант - 243 Мб против D-шного 226. P.S. Это не баян - неделя всего прошла. А приведенные тобой ссылки - жалкий лепет. Никто не мешает включать в парсер на C++ такие же куски асма, SIMD и прочие оптимизации, но пока как-то слабо. ![]() Кроме того я выше описал чисто D-шную фичу. Добавлено korvin, но вообще обсуждение доставляющее, спасибо за ссылку |
| Автор: korvin 22.10.15, 22:23 |
| Цитата applegame @ Это вырвиглазная SAX-версия, которой без слез нельзя пользоваться, тем более, что по скорости все равно проигрывает. А юзабельный DOM-вариант - 243 Мб против D-шного 226. Чего? Какой SAX/DOM у JSON? Цитата applegame @ P.S. Это не баян - неделя всего прошла. А приведенные тобой ссылки - жалкий лепет. Никто не мешает включать в парсер на C++ такие же куски асма, SIMD и прочие оптимизации, но пока как-то слабо. ![]() Не слабо, а нафиг никому не упало в современном мире. D'шники просто живут в прошлом веке. =) Ещё Эрик Реймонд в "Философии Unix" писал, насколько незначительны затраты на парсинг текста (причём там речь шла о разборе произвольного текста, а не какого-то строгого формата) по сравнению с преимуществами использования текста вместо бинарных форматов. Ну и опять же, если уж нужен минимальный оверхед на сериализацию/десериализацию, таки используют бинарные форматы (gob, bson и т.п. Erlang, например использует бинарный формат для своих структур) либо более специализированный текстовый формат, который разобрать на любом языке будет не проблема. Впрочем, людей даже разбор xml (который в этом плане сложнее, чем json) не напрягает... Зато компилятор Go установить на винду (и, возможно, на осх) значительно проще, чем любой из трёх D'шных. =) И это сильно решает, на самом деле. Всегда пожалуйста. |
| Автор: MyNameIsIgor 22.10.15, 23:04 |
| Перемога имеет привычку превращаться в зраду. Цитата applegame @ JSON-парсер написанный на D стал самым быстрым JSON-парсером среди всех языков, обогнав более чем в два раза (!) предыдущего чемпиона RapidJSON написанного на C++. Трудно без профилирования сказать, где самое слабое место SAX варианта. Но сама идея некую схему JSON интегрировать в парсер мне понравилась. Если дело действительно в лишних вызовах обработчика в SAX, то есть есть мнение, что встраивание схемы даже во время исполнения даст тот же результат. Во время компиляции в C++ можно использовать для этого constexpr. В любом случае я над этим поразмышляю - здесь ещё может быть чёткое/нечёткое соответствие схеме, опциональные поля, действия для неуказанных в схеме полях... Интересно, короче. Цитата applegame @ Никто не мешает включать в парсер на C++ такие же куски асма, SIMD и прочие оптимизации, но пока как-то слабо. Это серьёзно аргумент за D? ![]() Цитата applegame @ Это вырвиглазная SAX-версия, которой без слез нельзя пользоваться, тем более, что по скорости все равно проигрывает. А юзабельный DOM-вариант - 243 Мб против D-шного 226. Стоп-стоп. Чемпион никакой DOM не даёт, а фактически массив десериализованных структур. Здесь, кстати, используется рефлексия, которая для C++ пока только в виде предложений. А вот DOM версия на D даёт результат 12.42 секунд и 1417.1 Mb против C++ DOM 0.94 секунды и 243.6 Mb. Это многое говорит о кодогенерации и потреблении памяти D. И именно эти два примера эквивалентны по функционалу, ибо мы вовсе не всегда знаем структуру JSON. Ну, просто такие выражения. Имеется в виду способ парсинга. |
| Автор: applegame 23.10.15, 05:29 |
| Условное название способа парсинга. Можно сказать pull/push парсер, если тебе так больше нравится. Цитата korvin @ Если не можем обогнать, скажем, что это просто не нужно Не слабо, а нафиг никому не упало в современном мире. D'шники просто живут в прошлом веке. =) бла-бла-бла... ![]() На самом деле другим еще как упало, народ возбудился и начал реагировать, например тот самый С++ RapidJSON SAX бенчмарк пояаился буквально вчера. Цитата korvin @ Ну это явная ложь. DMD ставится на линупс, макось и винду не сложнее чем Go. Качается бинарный пакет и устанавливается стандартными средствами OS. Для винды это обычный exe-установщик. GDC и LDC - это да на винду поставить еще тот гемор.Зато компилятор Go установить на винду (и, возможно, на осх) значительно проще, чем любой из трёх D'шных. =) И это сильно решает, на самом деле. Ага, именно поэтому это перемога, а не победа. ![]() Цитата MyNameIsIgor @ По показателям потребления памяти RapidJSON SAX бенчмарк не эквивалентен, потому что не запоминает результаты парсинга. Если еще заполнять массив, а потом в цикле считать сумму как сделано в D-шном бенче, то результаты потребления памяти и скорости ухудшатся.Стоп-стоп. Чемпион никакой DOM не даёт, а фактически массив десериализованных структур. Здесь, кстати, используется рефлексия, которая для C++ пока только в виде предложений. А вот DOM версия на D даёт результат 12.42 секунд и 1417.1 Mb против C++ DOM 0.94 секунды и 243.6 Mb. Это многое говорит о кодогенерации и потреблении памяти D. И именно эти два примера эквивалентны по функционалу, ибо мы вовсе не всегда знаем структуру JSON. Что же касается "честного" DOM-парсера, то то что приведено в бенчмарке - это встроенный в стандартную либу достаточно убогий JSON-парсер, который устарел и планируется к замене. Самый быстрый на данный момент "честный" DOM-парсер на D - это кандидат в стандартную либу - std.data.json. Его в бенче нет, надо сделать соответствующий pull-request. Память он кушает также в районе 200Мб (фктически массив для хранения результатов парсинга), но по скорости уступает раза в три RapidJSON. Тут да, таки зрада. |
| Автор: applegame 23.10.15, 05:40 |
| Цитата MyNameIsIgor @ Обработчики - это очень неудобно. В vibe.d сериализаторе аналогичная функциональность реализована через мета-атрибуты, в частности изменение имени поля, опциональность и игнорирование:В любом случае я над этим поразмышляю - здесь ещё может быть чёткое/нечёткое соответствие схеме, опциональные поля, действия для неуказанных в схеме полях... Интересно, короче. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> struct Data { @optional int a = 10; string b; @name("field") int[] c; @ignore List list; } |
| Автор: MyNameIsIgor 23.10.15, 07:43 |
| Это не вопрос удобства, это вопрос необходимости, о чём нам говорит потребление памяти при SAX. |
| Автор: applegame 23.10.15, 07:55 |
| Цитата MyNameIsIgor @ Это не вопрос удобства, это вопрос необходимости, о чём нам говорит потребление памяти при SAX. Низкое потребление памяти - следствие потокового парсинга с обработкой данных на лету, без запоминания результатов парсинга. Обработчики не имеют к этому прямого отношения. Аналогичное поведение можно сделать с помощью ленивых итераторов или ренджей. Я могу написать бенч для std.data.json с таким же мизерным потреблением памяти, правда не такой быстрый как рапид, но зато без обработчиков. Те 200+ мб кушают не сами парсеры, а распарсенные данные в массиве. |
| Автор: MyNameIsIgor 23.10.15, 08:02 |
| Цитата applegame @ Низкое потребление памяти - следствие потокового парсинга с обработкой данных на лету, без запоминания результатов парсинга. Обработчики не имеют к этому прямого отношения. Аналогичное поведение можно сделать с помощью ленивых итераторов или ренджей. Они будут на самом верхнем уровне. А теперь представляем, что у нас там дерево. |
| Автор: applegame 23.10.15, 08:59 |
| Цитата MyNameIsIgor @ Цитата applegame @ Низкое потребление памяти - следствие потокового парсинга с обработкой данных на лету, без запоминания результатов парсинга. Обработчики не имеют к этому прямого отношения. Аналогичное поведение можно сделать с помощью ленивых итераторов или ренджей. Они будут на самом верхнем уровне. А теперь представляем, что у нас там дерево. Если дерево, то обработчики в том или ином виде будут присутствовать, это да. Но деревья как правило парсятся целиком, а в этом случае проще создать структуру с нужными полями и метаданными задать особые случаи (опциональность и т.п.), чем городить обработчики токенов. |
| Автор: MyNameIsIgor 23.10.15, 10:23 |
| Цитата applegame @ Если дерево, то обработчики в том или ином виде будут присутствовать, это да. Но деревья как правило парсятся целиком Как правило вообще всё парсят целиком и не имеют проблем. Я говорю о тех случаях, когда проблемы возникнуть могут. Я и не хочу обрабатывать токены. Я хочу реагировать на свойства так же, как внутри себя реагирует этот парсер на D, только делать это по событийной модели с обратными вызовами. |
| Автор: applegame 23.10.15, 10:55 |
| Цитата MyNameIsIgor @ Я и не хочу обрабатывать токены. Я хочу реагировать на свойства так же, как внутри себя реагирует этот парсер на D, только делать это по событийной модели с обратными вызовами. А зачем событийная модель? Просто нравится такой подход, и/или потому что на плюсах иначе не сделаешь? |
| Автор: MyNameIsIgor 23.10.15, 12:26 |
| Говорю же - из-за потребления памяти. Если уж мы в сотых долях секунды соревнуемся, то сотнями мегабайт раскидываться некрасиво. На C++ не сделать просто так рефлексию. А так ничего не мешает сделать, например, так <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto coords = json["coordinates"].read<Coord[]>({"x", &Coord::x}, {"y", &Coord::y}, {"z", &Coord::z}); |
| Автор: korvin 23.10.15, 17:33 |
| "Если не можем привлечь чем-то полезным, будем кричать о размере." ![]() Цитата applegame @ На самом деле другим еще как упало, народ возбудился и начал реагировать, например тот самый С++ RapidJSON SAX бенчмарк пояаился буквально вчера. Да-да, мужики любят меряться, а толку? Никто не станет из-за этого менять язык, парсинг JSON далеко не самое узкое место в вебсервисе. Цитата applegame @ Ну это явная ложь. DMD ставится на линупс, макось и винду не сложнее чем Go. Качается бинарный пакет и устанавливается стандартными средствами OS. Для винды это обычный exe-установщик. GDC и LDC - это да на винду поставить еще тот гемор. Вот только в этом супер-пупер бенчмарке победил GDC, а DMD выдаёт обычный тормозной код. Ты ж читал тему на ЛОРе. |
| Автор: applegame 24.10.15, 08:59 |
Полезность вопрос спорный, кому полезно, кому нет, а вот размер - вопрос бесспорный. ![]() Цитата korvin @ Да-да толку нет, поэтому бенчмарки по любому поводу встречаются на каждом углу. Факт, по существу тебе сказать-то и нечего.Да-да, мужики любят меряться, а толку? Никто не станет из-за этого менять язык, парсинг JSON далеко не самое узкое место в вебсервисе. Кроме того, писькомерство часто заставляет мужиков совершенствоваться. Вон глядишь MyNameIsIgor напишет свой парсер JSON, который переможет всех, попутно исследовав интересные технологии программирования. Цитата korvin @ Дык и бенч победил в линупсе, а не в винде. В бубунте gdc - один из стандартных пакетов и устанавливается не сложнее g++. Но какое это имеет отношение к этомуВот только в этом супер-пупер бенчмарке победил GDC, а DMD выдаёт обычный тормозной код. Ты ж читал тему на ЛОРе. Цитата korvin @ Зато компилятор Go установить на винду (и, возможно, на осх) значительно проще, чем любой из трёх D'шных. =) ошибочному высказыванию? Или ты один из тех, у кого не хватает смелости признаться в своей ошибке? Кстати, моя инфа тоже устарела, на данный момент GDC на базе mingw работает и под Win, также как и LDC на базе MSVC. Бинарные уже скомпилированные пакеты доступны к загрузке на соответствующих сайтах. У DMD кодеген говно, но зато он быстро компилирует. Самое смешное, что у Go, который ты тут привел в качестве примера, ситуация ровно такая же. Родной компилятор Go от гугла сильно уступает по качеству сгенеренного кода компилятору gccgo, который, на винду ставится еще геморнее, чем gdc. Но при этом также как и DMD является референсным компилятором и компилирует гораздо быстрее, чем мощные оптимизирующие собратья. Не, korvin, троллинг у тебя явно на этот раз не удался, слишком толстый. Брось ты это дело. |
| Автор: D_KEY 24.10.15, 09:35 |
| Там перемога за счёт языковых фич или за счёт каких-то особенностей реализации парсера? Если последнее, то хз при чем тут язык и холивар. |
| Автор: applegame 24.10.15, 12:19 |
| Цитата D_KEY @ И то и другое.Там перемога за счёт языковых фич или за счёт каких-то особенностей реализации парсера? Если последнее, то хз при чем тут язык и холивар. Но сам твой вопрос несовсем корректен, поэтому мой ответ неточен. Вот что автор сам немного пишет об особенностях реализации - https://github.com/kostya/benchmarks/pull/4...mment-147932489 Читай и сам решай. |
| Автор: D_KEY 24.10.15, 16:48 |
| applegame, а ты прочёл? На C++ можно реализовать так же? |
| Автор: applegame 24.10.15, 21:53 |
| Там используется рефлексия и CTFE, первое в C++ отсутствует, а второе сильно ограничено. Кроме того там используются некоторые возможности шаблонов, отсутствующие в C++, для реализации удобного API. Поэтому так же не получится, но похожим образом, полагаю, можно. Ассемблерные вставки, на которые тыкают некоторые на лоре, на самом деле всего лишь работа с SSE. Причем они завернуты в условную компиляцию, поэтому на платформах не поддерживающих SSE, парсер работать будет, но не так быстро. |
| Автор: D_KEY 24.10.15, 22:29 |
| Т.е. похоливарить-то не о чем? |
| Автор: MyNameIsIgor 24.10.15, 22:54 |
| Цитата applegame @ CTFE, первое в C++ отсутствует, а второе сильно ограничено. Кроме того там используются некоторые возможности шаблонов, отсутствующие в C++, для реализации удобного API Подробнее - что такого дало CTFE, и что за отсутствующие возможности шаблонов? |
| Автор: applegame 25.10.15, 07:53 |
| Ну а как ты хотел? Все что угодно реализованное на языке X можно похожим образом сделать на языке Y. Но, похоливарить действительно особо не о чем. Просто для информации, как можно с пользой применить некоторые особенности D. Цитата MyNameIsIgor @ Например передача строки в качестве параметра шаблона (название поля) или уже упомянутый форвардинг функций через opDispatch. Насчет CTFE, я похоже погорячился, buildRemapTable, которая по сути и занимается рефлексией (разбором структуры), все же не обычная функция (хотя и могла бы быть таковой), а шаблон, но тем не менее она возвращает CT-константу - список строк, что опять же невозможно в C++. Или возможно? Подробнее - что такого дало CTFE, и что за отсутствующие возможности шаблонов? |
| Автор: MyNameIsIgor 25.10.15, 13:41 |
| И почему её надо передавать именно параметром шаблона? Цитата applegame @ Насчет CTFE, я похоже погорячился, buildRemapTable, которая по сути и занимается рефлексией (разбором структуры), все же не обычная функция (хотя и могла бы быть таковой), а шаблон, но тем не менее она возвращает CT-константу - список строк, что опять же невозможно в C++. Или возможно? Ну, с constexpr функция есть такая сложность, что динамическое выделение памяти невозможно, потому нельзя приемлемым способом вернуть список, который по длине и хранимым значениям будет зависеть от переданного в функцию аргумента. Но это можно сделать в зависимости от шаблонного аргумента constexpr функции. Потому камнем преткновения остаётся рефлексия. Если пофантазировать, что предложение комитету уже где-то реализовано, то там такое возможно. Ценность это фичи вообще не могу оценить. В чём смысл, если компилятор всё равно ничего проверить не в состоянии? И что делать, если мне надо обратиться по имени свойства, полученному во время исполнения? |
| Автор: applegame 25.10.15, 16:33 |
| Чтобы не обрабатывать названия полей run-time для тех полей, для которых название известно compile-time, что бывает чуть менее, чем всегда. Цитата MyNameIsIgor @ А что нужно проверять компилятору? Он просто инстанцирует шаблон и генерит функцию для парсинга соответствующего поля json-объекта. Естественно это можно сделать только если имя поля известно уже на стадии компиляции:Ценность это фичи вообще не могу оценить. В чём смысл, если компилятор всё равно ничего проверить не в состоянии? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> json.myJsonField -> json.opDispatch!"myJsonField" Цитата MyNameIsIgor @ К такому свойству обратиться как свойству структуры не получится. Тогда используется какой-нибудь opIndex (аналог operator[]), где название поля передаётся уже run-time. Но насколько я знаю в обсуждаемом парсере это не реализовано. И что делать, если мне надо обратиться по имени свойства, полученному во время исполнения? |
| Автор: MyNameIsIgor 25.10.15, 20:25 |
| Цитата applegame @ Чтобы не обрабатывать названия полей run-time для тех полей, для которых название известно compile-time, что бывает чуть менее, чем всегда. А что входит в понятие "обрабатывать"? Я о том и говорю - он ничего не может. Потому это возможность никак не влияет на возможности языка, просто синтаксическая фишка, ценность которой лично для меня сомнительна. |
| Автор: amk 25.10.15, 21:40 |
| Похоже, если строку обрабатывает код, написанный программистом, это называется рунтайм, а если точно такой же, но подставленный компилятором, то это уже рунтаймом не называется. |
| Автор: applegame 26.10.15, 08:04 |
| Посмотрел код парсера, там действительно выгода не очень большая, но таки есть, а именно, длина имени поля известна compile-time, а значит не нужно ее вычислять в run-time, что слегка ускоряет сравнение строк. Цитата MyNameIsIgor @ Ну я бы так не сказал. Обычно оно применяется для различного рода врапперов, что-то вроде operator-> на стероидах. А так да, синтаксическая фишка, так же как и operator->.Потому это возможность никак не влияет на возможности языка, просто синтаксическая фишка, ценность которой лично для меня сомнительна. Цитата amk @ Нет, compile-time - это если код выполняется на стадии компиляции. И совершенно без разницы написан ли код программистом или сгенерен компилятором.Похоже, если строку обрабатывает код, написанный программистом, это называется рунтайм, а если точно такой же, но подставленный компилятором, то это уже рунтаймом не называется. Что касается возможности передавать строки compile-time вообще, то это сильно помогает в работе с рефлексией. Я в свое время написал автоматические генераторы классов, для RPC (remote proсedure call) через сеть. Грубо говоря мы описываем интерфейс с функциями с параметрами и возвращаемымми значениями, а либа генерит классы для RPC-клиента и RPC-сервера унаследованные от этого интерфейса и реализующие его функции. Заняло примерно 150 строк не считая сериализатора и либы для работы с сетью. Возможность работы со строками в compile-time - это однозначный вин, не понимаю, как можно не понимать этого. |
| Автор: Qraizer 26.10.15, 09:07 |
| Помню, писал утилитку, собирающую из трёх Word-овых, одного Excel-ного документов, содержащий требования, шаблоны для итогов и выявленные несоответствия, и результатов запуска тестов с пасс/фэйлами и покрытием, два других Word-овых документа с итогами, требующимися для сертификационных органов. Писал через ActiveX-интерфейсы к MS Office, для лицензионной чистоты на MS Studio Express, поэтому на чистом IDispatch, без библиотек и TLB. Танунафик эту динамическую типизацию с run-time рефлексией. |
| Автор: applegame 26.10.15, 09:49 |
| Дык в D статическая типизация со статической же рефлексией. |
| Автор: jack128 26.10.15, 13:12 |
|
| Автор: MyNameIsIgor 26.10.15, 13:19 |
| Цитата applegame @ Посмотрел код парсера, там действительно выгода не очень большая, но таки есть, а именно, длина имени поля известна compile-time, а значит не нужно ее вычислять в run-time, что слегка ускоряет сравнение строк. Хех, я надеялся, что во время компиляции меняется машина состояний парсера для обработки указанных свойств ![]() Не буду точно утверждать, но пока не вижу препятствий делать это же на constexpr функциях. Цитата applegame @ Что касается возможности передавать строки compile-time вообще, то это сильно помогает в работе с рефлексией. Что мне не понравилось в D - так это засилье строк. А правильно работать с AST как в Lisp или Nemerle. |
| Автор: Qraizer 26.10.15, 14:48 |
| Я знаю, applegame. Зато бесплатно, jack128. У меня все внутренние продукты написаны на Стандартных Плюсах, чтобы компилилось и работало и на WinAPI, и на POSIX, ежели вдруг придётся переползти исключительно в unix-way. Фирма не тратит деньги на лицензии, если этого можно не делать, т.к. всякие там RTRT и LDRA и так стоят дофига, ещё Студий не хватало. |
| Автор: Shaggy 26.10.15, 16:19 |
hotdem_ru_553347561914549879450.jpg (, : 826)
|
| Автор: Qraizer 26.10.15, 16:34 |
| Троллить пытаешься, Shaggy? Напрасно, у нас практически все target execution environment построены на POSIX. |
| Автор: Flex Ferrum 26.10.15, 19:41 |
| Эммм... Народ, чёт я не догоняю. Когда я пишу в C++: someStruct.field = node["field"].asString(); (ну или как-то так) я тоже знаю имя поля в compile-time. В чём профит то? |
| Автор: applegame 27.10.15, 06:53 |
| Цитата MyNameIsIgor @ Да, я тоже надеялся. Он (парсер) достаточно примитивен, хз как ему удалось обогнать RapidJSON.Хех, я надеялся, что во время компиляции меняется машина состояний парсера для обработки указанных свойств ![]() Цитата MyNameIsIgor @ Это да, строковые миксины невероятно уродливы, но таки лучше чем ничего. Есть драфт с претензией на приличные макросы и даже ключевое слово macro зарезервировано, но так как это далеко не самое ужасное в D, то запил его отложен на неведомые времена.Что мне не понравилось в D - так это засилье строк. А правильно работать с AST как в Lisp или Nemerle. Цитата Flex Ferrum @ Эммм... Народ, чёт я не догоняю. Когда я пишу в C++: someStruct.field = node["field"].asString(); (ну или как-то так) я тоже знаю имя поля в compile-time. В чём профит то? В теории ничем, в реальности отличается тем, что ты передаешь указатель на строку через стек или регистр, параметр шаблона не передается никак. Кроме того при поиске поля приходится выполнять сравнивание переданного имени поля и названий полей считанных из JSON-файла. В обсуждаемом парсере сначала сравниваются длины названий полей, у считанного названия длина вычисляется в процессе парсинга, а у строки-параметра шаблона длина известна compile-time и просто компилируется в константу. |
| Автор: Flex Ferrum 27.10.15, 08:19 |
| Цитата applegame @ В теории ничем, в реальности отличается тем, что ты передаешь указатель на строку через стек или регистр, параметр шаблона не передается никак. Кроме того при поиске поля приходится выполнять сравнивание переданного имени поля и названий полей считанных из JSON-файла. В обсуждаемом парсере сначала сравниваются длины названий полей, у считанного названия длина вычисляется в процессе парсинга, а у строки-параметра шаблона длина известна compile-time и просто компилируется в константу. Ну ты же понимаешь, что при желании всё это можно сделать и на C++. |
| Автор: applegame 27.10.15, 15:19 |
| Интересно как можно compile-time посчитать длину строки передаваемой как параметр функции, которая парсит соответствующий json-объект? |
| Автор: MyNameIsIgor 27.10.15, 15:23 |
| Цитата applegame @ Интересно как можно compile-time посчитать длину строки передаваемой как параметр функции, которая парсит соответствующий json-объект? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<size_t N> json_value operator[](const char (&ch)[N]); |
| Автор: applegame 27.10.15, 18:20 |
| Цитата MyNameIsIgor @ <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<size_t N> json_value operator[](const char (&ch)[N]); Круто, подзабыл я плюсы. А есть возможность из этой функции передать эту строку дальше? Исправьте, если не затруднит: http://ideone.com/MuFqEk |
| Автор: MyNameIsIgor 27.10.15, 19:21 |
| Я вот об этом уже говорил <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> calc<sum<N>(ch)> Не получится аргумент функции запихнуть в шаблон. |
| Автор: applegame 27.10.15, 20:44 |
| В том то и дело, даже несмотря на то что этот аргумент по идее известен compile-time. В D параметром шаблона может быть не только строка, но и любой символ включая переменную или функцию: http://dpaste.dzfl.pl/f3c84b792ae3 <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import std.stdio; void calc(alias something)(int a) { writeln(something + a); } void calc2(alias something1, alias something2)() { writeln(something1 + something2); } int fun() { return 10; } void main() { int var = 10; calc!var(20); calc!fun(20); calc2!(var, fun); } |
| Автор: MyNameIsIgor 27.10.15, 21:05 |
| Цитата applegame @ В том то и дело, даже несмотря на то что этот аргумент по идее известен compile-time Даже constexpr функции должны работать во время исполнения. Потому, например, задача <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> constexpr type foo(bool b) { /* implementation */ } сделать так, чтобы type менялся в зависимости от истинности b, не решаема - это сделает типизацию динамической, т.к. эта же функция должна работать и во время исполнения. Цитата applegame @ В D параметром шаблона может быть не только строка, но и любой символ включая переменную или функцию Угу, читал. Как я уже говорил, метапрограммирование в новом языке (тем более исполняющем код во время компиляции) надо было делать совсем не так, как в D. Потому подобные факты не только не агитируют меня в пользу D, а вызывают отвращение. К сожалению, Александреску не смог осилить ничего, кроме шаблонов. |
| Автор: applegame 28.10.15, 13:13 |
| Цитата MyNameIsIgor @ А как надо было? Угу, читал. Как я уже говорил, метапрограммирование в новом языке (тем более исполняющем код во время компиляции) надо было делать совсем не так, как в D |
| Автор: MyNameIsIgor 28.10.15, 13:16 |
| Цитата applegame @ Цитата MyNameIsIgor @ А как?Угу, читал. Как я уже говорил, метапрограммирование в новом языке (тем более исполняющем код во время компиляции) надо было делать совсем не так, как в D Дать доступ к AST, возможность его обходить, конструировать. Как во время компиляции, так и во время исполнения. Как в Nemerle. В том же C# (.NET) есть такая возможность, но только во время исполнения. Во многом на этом работает LINQ. |
| Автор: applegame 28.10.15, 13:23 |
| Цитата MyNameIsIgor @ А как это связано с шаблонами и прочей уже реализованной метапрограммируемой фигней в D? Доступ к AST и гигиеничные макросы могут добавить, и что, после этого отвращение исчезнет? Дать доступ к AST, возможность его обходить, конструировать. Как во время компиляции, так и во время исполнения. Как в Nemerle. В том же C# (.NET) есть такая возможность, но только во время исполнения. Во многом на этом работает LINQ. |
| Автор: MyNameIsIgor 28.10.15, 13:27 |
| Цитата applegame @ А как это связано с шаблонами и прочей уже реализованной метапрограммируемой фигней в D? Доступ к AST и гигиеничные макросы могут добавить, и что, после этого отвращение исчезнет? Это связано, потому что пропагандируется метапрограммирование на шаблонах и строках вместо того, чтобы изначально в новом языке сделать цивилизованный способ. Это ахтунг. Это наследие останется навсегда. |
| Автор: applegame 28.10.15, 14:27 |
| Цитата MyNameIsIgor @ Ага, теперь мне понятна ваша точка зрения. Со своей стороны могу сказать следующее:Это связано, потому что пропагандируется метапрограммирование на шаблонах и строках вместо того, чтобы изначально в новом языке сделать цивилизованный способ. Это ахтунг. Это наследие останется навсегда. Макросы заметно сложнее, чем шаблоны, поэтому (со слов знакомых) используются редко в небиблиотечном коде. D-ешные же шаблоны настолько просты и читабельны (в отличие от шаблонов C++), что их используют постоянно, практически в любом коде. Пожтому я не считаю отсутствие макросов каким-то очень уж серьезным недостатком. Кроме того слишком гибкие макросы - прямой путь к WAT WAT. LINQ можно успешно реализовать и без макросов. Нечто похожее - http://code.dlang.org/packages/dquery. Что касается Nemerle, то там действительно много интересных фич (после изучения Haskell это стало особо ясно), но у меня вызывает отвращение .NET/Mono. Поэтому Nemerle сразу был исключен мною из кандидатов на следующий проект. В целом после реального опыта использования D в коммерческом продакшн проекте, могу сказать следующее: - D полон крайне раздражающих косяков (в том числе и в дизайне языка) и недоделок. Настолько, что иногда хочется его бросить. - Сборщик мусора сильно упрощает написание кода, но работает он не лучшим образом, из-за чего многие библиотеки избегают его, некоторые совсем не используют. - Возвращаться на C++ не получается. C++ после D кажется очень неуклюжим и уродливым. - Недурно показал себя в разработке web-сервисов, пишется легко, как на каком-нибудь Python или Ruby, но многие ошибки отсекаются compile-time. - Писать на D легко и приятно, пока не столкнешься с неведомой грёбаной фигнёй и не потратишь на ее решение полдня. - Быстро развивается, отзывчивое и активное коммьюниьти. Буду ли я дальше писать на D? Не уверен если честно. Скорее всего буду писать пока не найду приемлемую для меня альтернативу. Язык должен быть компилируемым, без использования виртуальных машин (кроме LLVM, которая не совсем виртуальная машина) и с автоматическим выведением типов. Пока погладываю на Rust, Crystal и Nim. Crystal кажется очень интересным, но пока не напишешь чего-нибудь не поймешь. |
| Автор: MyNameIsIgor 28.10.15, 14:50 |
| Цитата applegame @ Макросы заметно сложнее, чем шаблоны, поэтому (со слов знакомых) используются редко в небиблиотечном коде. ![]() Он и реализован без макросов ![]() Цитата applegame @ Что касается Nemerle, то там действительно много интересных фич (после изучения Haskell это стало особо ясно), но у меня вызывает отвращение .NET/Mono. Поэтому Nemerle сразу был исключен мною из кандидатов на следующий проект. Я и не рекомендовал Nemerle. Но его основные достоинства вовсе не функциональщина, а метапрограммирование. Цитата applegame @ В целом после реального опыта использования D в коммерческом продакшн проекте, могу сказать следующее А я вот не стал его использовать. Когда-то возлагал на него надежды, но он разочаровал. Язык пытается объять необъятное, противоречив. В качестве конкурента C/C++ себя не оправдал, т.к. не следует принципу нулевой стоимости. В этом смысле пока что лучше всех выглядит Rust, Go слишком примитивен, остальные просто маргинальные. |
| Автор: applegame 28.10.15, 15:15 |
| Верно подмечено, так и есть. Отпугивает отсутствие исключений и обилие unwrap(). Добавлено Цитата MyNameIsIgor @ Это о "принцип абстракции с нулевой стоимостью"? Сборщик мусора нарушает этот принцип? В качестве конкурента C/C++ себя не оправдал, т.к. не следует принципу нулевой стоимости. |
| Автор: MyNameIsIgor 28.10.15, 15:20 |
| Цитата applegame @ Это о "принцип абстракции с нулевой стоимостью"? Сборщик мусора нарушает этот принцип? Это "не плачу за то, чего не использую". Как я понимаю, на практике полностью отключить сборку мусора в D нереально. |
| Автор: DarkEld3r 28.10.15, 15:27 |
| Это очень спорный тезис. Причём противники буквально чего угодно (перегруженных функций и операторов, шаблонов и т.д.), применяют его. Как правило оказывается, что пишут эти люди на языке(ах), где обсуждаемой фичи нет. Тут впору вспомнить о "парадоксе блаба", хотя я и не очень люблю этот аргумент. Можно зайти с другой стороны - плюсовые шаблоны применяются для метапрограммирования как раз потому что специализированного инструмента в языке не имеется. Результат зачастую не сильно читаемым получается. Нормальные макросы как раз могут сделать ситуацию лучше, ну а "неправильно" и неуместно можно применять что угодно. К сожалению, я не знаю перспективных языков, претендующих на нишу С++, с действительно хорошим метапрограммированием (уровня Nemerle). Rast хоть и нравится в целом, но имеет в этом отношении немало проблем. Обилие unwrap - это фича. А вот с исключениями и правда досадно, тем более, что их "нет" исключительно из-за упрямства. В том смысле, что в языке имеется всё необходимое кроме сахара для удобной обработки. |
| Автор: applegame 28.10.15, 15:44 |
| Реально. Но придется отказаться от многих встроенных приятных вещей и от половины стандартной библиотеки. Тем не менее есть либы совсем не использующие GC. Развитие D похоже на тыкания слепого котенка в разные углы. Не прошло и 10 лет, как создатели языка таки убедились, что этот ваш GC далеко не всегда кошерен, а чаще всего нафик не нужен. И что именно GC - главный аспект, из-за которого плюсовики не желают перелезать на D. Сейчас основное развитие языка идет в направлении отключения GC везде, где это возможно. Ввели очередной атрибут @nogc, помеченный им код гарантированно не используют GC (проверятся компилятором). Александреску написал целую либу самых разных аллокаторов выстроенных в иерархию и способных строится в цепочки и собирается писать либу контейнеров с использованием этих самых аллокаторов. Также разработали концепцию опциональной поддержку RC (на уровне языка) для классов и планируют ее запилить. Короче сейчас писать @nogc код можно, хоть и не так легко как хотелось бы. Но есть устойчивая тенденция к облегчению этого дела. P.S. Александреску может и дурно повлиял на развитие языка, но надо отдать ему должное - он открыт для диалога (так же как и Брайт) и не страдает бессмысленным упрямством. Добавлено Цитата DarkEld3r @ Ну D-шные шаблоны вполне читаемы. Макросы мне представляются тяжелой артиллерией для каких-то особо сложных случаев. Можно ли вообще отказаться от шаблонов/дженериков в пользу макросов?Можно зайти с другой стороны - плюсовые шаблоны применяются для метапрограммирования как раз потому что специализированного инструмента в языке не имеется. Результат зачастую не сильно читаемым получается. Нормальные макросы как раз могут сделать ситуацию лучше, ну а "неправильно" и неуместно можно применять что угодно. Цитата DarkEld3r @ Странная какая-то фича, и, насколько я понял, это обилие unwrap() как раз и есть следствие отсутствия исключений, нет? Обилие unwrap - это фича. А вот с исключениями и правда досадно, тем более, что их "нет" исключительно из-за упрямства. В том смысле, что в языке имеется всё необходимое кроме сахара для удобной обработки. |
| Автор: MyNameIsIgor 28.10.15, 16:00 |
| Цитата applegame @ Реально. Но придется отказаться от многих встроенных приятных вещей и от половины стандартной библиотеки. Разве это реальная практическая альтернатива? Нагромождение фич какое-то... Нет. Потому что они решают разные задачи. |
| Автор: DarkEld3r 28.10.15, 16:11 |
| Цитата applegame @ Но ведь найдутся случаи когда даже D-шные шаблоны окажутся недостаточно мощными?.. Ну D-шные шаблоны вполне читаемы. Макросы мне представляются тяжелой артиллерией для каких-то особо сложных случаев. Ведь и плюсовые шаблоны для ряда применений отлично подходят, а часто и без них жить можно, но иногда требуется большее. Это в контексте раста/плюсов или в каком-нибудь абстрактном языке? Имхо, это разные инструменты и хорошо иметь и то и другое. Цитата applegame @ Ну фича (спорная) в том, что обработка ошибок происходит явно.Странная какая-то фича, и, насколько я понял, это обилие unwrap() как раз и есть следствие отсутствия исключений, нет? Относительно отсутствия исключений - есть паника, которая точно так же раскручивает стек, вызывает деструкторы и т.д. Есть возможности её перехватить/обработать. Нет "только" удобного способа проверить к какому типу исключение относится. Может когда-то дойдут до того, что это тоже нужно, ведь изначально панику можно было обработать только на границе потоков. |
| Автор: applegame 28.10.15, 16:17 |
| Да, реальная. И становится все реальней. Фобос (стандартная либа) все больше и больше "ренджифицируется", что делает ненужными аллокации памяти вообще. Лямбды далеко не всегда требуют аллокаций, а там где требуют можно заменить на аналог std::function. Получаются эдакие плюсы на стероидах. Посмотрим что будет через полгода. Да, атрибутов нагородили мама не горюй. Добавлено Бывает такое но редко. Строковые миксины D успешно заменяют практическое любое применение макросов. Но выглядит это как помойка. Я не люблю строковые миксины именно за их уродство. |
| Автор: MyNameIsIgor 28.10.15, 16:24 |
| Цитата applegame @ Да, реальная. И становится все реальней. Фобос (стандартная либа) все больше и больше "ренджифицируется", что делает ненужными аллокации памяти вообще. Лямбды далеко не всегда требуют аллокаций, а там где требуют можно заменить на аналог std::function. Получаются эдакие плюсы на стероидах. Скорее это получается два языка в одном. По мне, так уже либо сборщик мусора есть, либо его нет. Не надо метаться - это всё то же стаскивание всего, что блестит. |
| Автор: applegame 28.10.15, 16:31 |
| Цитата MyNameIsIgor @ Это главная беда D - постоянное метание. С академической точки зрения - D отвратное говно, напичканое всем, чем ни попадя, работающее странным образом и т.д. и т.п. Но с практической точки зрения - садишься и пишешь, причем гораздо быстрее и безопаснее, чем на плюсах. GC в тех задачах, для которых я использую D (web-cервисы) практически не влияет на производительность. Скорее это получается два языка в одном. По мне, так уже либо сборщик мусора есть, либо его нет. Не надо метаться - это всё то же стаскивание всего, что блестит. Добавлено Я бы попробовал Rust, но блин, такого любителя синтаксического сахара как я эти unwrap() раздражают просто нереально. |
| Автор: Qraizer 28.10.15, 16:44 |
| Цитата DarkEld3r @ "Зачем вводить новое, если старое и так справляется." Примерно так думали в Комитете, наверное, предполагая, что всё это нечитабельное в конечном итоге будет внесено в библиотеку и красивенько там сверху оттуда смотреться. Получилось ли, это другой вопрос. Можно зайти с другой стороны - плюсовые шаблоны применяются для метапрограммирования как раз потому что специализированного инструмента в языке не имеется. Результат зачастую не сильно читаемым получается. |
| Автор: DarkEld3r 28.10.15, 17:03 |
| Цитата Qraizer @ Ну всё-всё предусмотреть и спрятать в библиотеку точно не получится, если мы о стандартной. Если о сторонних, то сейчас "кишки метапрограммирования" зачастую наружу торчат. Как минимум, в виде ошибок компиляции. Нормальные макросы сгладили бы обе проблемы. предполагая, что всё это нечитабельное в конечном итоге будет внесено в библиотеку и красивенько там сверху оттуда смотреться. |
| Автор: Qraizer 29.10.15, 00:09 |
| Ну, boost::mpl, конечно, не на варганили, но кое-что-таки внесли. Всякие там std::is_XXX(), std::enable_if(), std::make_-, add_-, remove_XXX()... Мало, что ли? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> В принципе, выглядит читабельно и, будучи Стандартным, избавляет от разгребания велосипедов C++03, а что ещё надо-то?template <typename T> class A: private T { struct Null: T {}; static Null NullPtr; public: A( typename std::enable_if<std::is_default_constructible<T>::value, T>::type* = &NullPtr); A(const typename std::enable_if<std::is_copy_constructible<T>::value, T>::type& ); A( typename std::enable_if<std::is_move_constructible<T>::value, T>::type&& ); /* ... */ }; Вот только я себя никак не приучу их юзать, и потому не знаю, насколько этого хватает. Вон, для A<>::A() чуток не хватило. |
| Автор: D_KEY 29.10.15, 08:48 |
Это читабельно для тех, кто хорошо разбирается с шаблонами и знает паттерны метапрограммирования с их использованием. А так у меня ещё есть надежды хотя бы на concepts lite в 17... |
| Автор: Flex Ferrum 29.10.15, 16:45 |
| По-моему ты только что изобрёл фичу C++11 под названием Inheriting constructor. Добавлено Да вроде должны быть. |
| Автор: Qraizer 29.10.15, 18:53 |
| Цитата Flex Ferrum @ Ага. Ничего проще в качестве примера не придумалось. По-моему ты только что изобрёл фичу C++11 под названием Inheriting constructor. |
| Автор: korvin 29.10.15, 19:18 |
| Какие макросы слишком гибки на твой взгляд? Добавлено Цитата applegame @ Странная какая-то фича, и, насколько я понял, это обилие unwrap() как раз и есть следствие отсутствия исключений, нет? Скорее это следствие отсутствия do-нотации. Впрочем, если не ошибаюсь, макрос try! там как-то помогает. |
| Автор: applegame 29.10.15, 20:00 |
| Макросы того же Nemerle. Насколько я понял они позволяют сделать так, что любая последовательность любых допустимых символов может оказаться вполне синтаксически корректной, если для этого будет сделан соответствующий макрос. Прямо как случай с Ruby в указанном ролике. Впрочем, может быть в Nemerle, в отличие от Ruby это не создаст много проблем. По крайней мере если я накосячу в одном из этих слов, то в Nemerle я получу ошибку еще на стадии компиляции, я правильно понимаю? |
| Автор: korvin 30.10.15, 17:59 |
| Цитата applegame @ Макросы того же Nemerle. Насколько я понял они позволяют сделать так, что любая последовательность любых допустимых символов может оказаться вполне синтаксически корректной, если для этого будет сделан соответствующий макрос. Прямо как случай с Ruby в указанном ролике. Впрочем, может быть в Nemerle, в отличие от Ruby это не создаст много проблем. По крайней мере если я накосячу в одном из этих слов, то в Nemerle я получу ошибку еще на стадии компиляции, я правильно понимаю? Конечно на этапе компиляции, Nemerle же статически типизированный. Впрочем, даже в динамически типизированных Scheme и CL получишь ошибку компиляции. Просто Ruby --- это поделие для хипстеров-студентов. =) |
| Автор: applegame 30.10.15, 19:17 |
| Как, если тип становится известным только в run-time? Просто Ruby - некомпилируемый язык, что впрочем никак не противоречит твоему утверждению Добавлено P.S. Только что прочитал, что в Go даже дженериков нет. Ужоснах. |
| Автор: korvin 30.10.15, 22:27 |
| Макроэкспанд происходит во время компиляции и макросы с типизацией никак не связаны. Ну ты и слоупок. Тем не менее Go уже в "продакшене" (из общеизвестных проектов --- Docker), а D'шники всё еще меряются скоростью парсинга JSON. =) |
| Автор: applegame 31.10.15, 06:32 |
| Цитата korvin @ Ну ты и слоупок. Тем не менее Go уже в "продакшене" (из общеизвестных проектов --- Docker), а D'шники всё еще меряются скоростью парсинга JSON. =) Это ни разу не показатель качества языка. На похапе мульёны общеизвестных проектов. |
| Автор: Бобёр 01.11.15, 07:22 |
| Цитата Это ни разу не показатель качества языка. Вероятно, это показатель качества всей инфраструктуры. Мне, например, D не нужен. Если надо написать такое "супер быстрое" - это это C/C++, а если надо быстро написать - то C# или python. В зависимости от обстоятельств. Зачем учить ещё один язык, если в моей любимой платной IDE его нету. |
| Автор: applegame 01.11.15, 08:43 |
| Скорее это показатель легкости изучения и истоических факторов. Цитата Бобёр @ Ну смотря что-ты пишешь. Допустим если нужен супер быстрый веб-сервис. C/C++ плохо подходят для этого, питон тормозной. Кто-то выберет Java, кто-то Go, ну а я выбрал D.Мне, например, D не нужен. Если надо написать такое "супер быстрое" - это это C/C++, а если надо быстро написать - то C# или python. В зависимости от обстоятельств. Зачем учить ещё один язык, если в моей любимой платной IDE его нету. А любимая платная IDE это какая? |
| Автор: Бобёр 01.11.15, 10:22 |
| Visual Studio вестимо. Цитата Допустим если нужен супер быстрый веб-сервис. C/C++ плохо подходят для этого, питон тормозной. Почему же плохо подходит. есть boost::asio. Оно реально вполне такое себе. Правда, на golang это вообще превращается в детскую забаву, это правда. Не знаю как на D, на golang сделать http сервер можно минуты за 3 примерно. |
| Автор: applegame 01.11.15, 10:57 |
| Ну тогда на самом деле поддерживает, не из коробки конечно, но без особого геморроя - VisualD Да, это отличая либа, когда-то я активно ей пользовался. Простой веб-сервис на ней написать не сложно, а вот для более сложного придется ваять много обвязки. Цитата Бобёр @ На чистом D + стандартные либы писать http-сервер не намного проще чем на голом C++ + стандартные либы. Но использовав D-шный библиотечный менеджер DUB можно поднять http-сервер за те же считанные минуты. С применением vibe.d простецкий http-сервер на D пишется примерно так:Правда, на golang это вообще превращается в детскую забаву, это правда. Не знаю как на D, на golang сделать http сервер можно минуты за 3 примерно. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> import vibe.d; void main() { auto settings = new HTTPServerSettings; settings.port = 8080; listenHTTP(settings, (request, response) { response.writeBody("Hello, World!", "text/plain"); }); runEventLoop(); } Естественно, есть роутинг, валидация параметров, поддержка сессий, шаблонов и т.д. Так же есть поддержка "сырых" TCP и UDP. Все это построено на аналоге горутин Go. Можно воспользоваться генератором web-интерфейсов. В этом случае просто создается класс где за определенные URL отвечают соответствующие методы и фреймворк автоматически в зависимости от имен методов и атрибутов привязанных к ним сгенерит соответствующий роутинг, распарсит параметры запроса и засунет их как параметры метода, а возвращаемое методом значение вернет как ответ на запрос. Web interface generator REST interface generator Нет, для веб-сервисов D определенно намного удобнее C++, а по скорости практически идентичен. |
| Автор: MyNameIsIgor 01.11.15, 11:31 |
| Это чем-то подкреплено? |
| Автор: applegame 01.11.15, 12:57 |
| Да, подкреплено. Первое: эмпирически выводится, что для идентичного кода D и C++ gdc и g++ генерят идентичный же машкод. Второе: измерения. Например уже упоминавшийся FastJSON, или вот эта статья - https://atilanevesoncode.wordpress.com/tag/boostasio/ или вот эта - https://togototo.wordpress.com/2013/08/23/b...ala-and-nimrod/ |
| Автор: Qraizer 01.11.15, 14:25 |
| А почему ссылки открываются только в Vivaldi? Добавлено А, ещё в Firefox-е из-под tor-а. |
| Автор: applegame 01.11.15, 19:29 |
Qraizer'а взломали? |
| Автор: Qraizer 01.11.15, 19:55 |
| Кого? Оперу с Хромом? Вивальди на том же движке, кстати. |
| Автор: korvin 01.11.15, 20:03 |
| Цитата applegame @ Нет, для веб-сервисов D определенно намного удобнее C++, а по скорости практически идентичен. Почему же спустя столько (ну пусть пять, с поблажками) лет так никто этими, несомненно весомыми, аргументами не впечатлился и все продолжили юзать тормозные PHP/Python/RoR/etc? |
| Автор: applegame 01.11.15, 20:52 |
| Цитата korvin @ Кто это такие "все"? Не все, многие впечатлились.Почему же спустя столько (ну пусть пять, с поблажками) лет так никто этими, несомненно весомыми, аргументами не впечатлился и все продолжили юзать тормозные PHP/Python/RoR/etc? Ну и пять лет - это вообще не срок. Похапе - 20 лет, Ruby - 20 лет, Python - 24 года, C++ - 32 года. D - 14 лет (D2 - 8 лет). Korvin, прекращай уже ехидствовать. Спрашивай по существу, без риторических бессмысленных вопросов. Добавлено Цитата Qraizer @ А почему ссылки открываются только в Vivaldi? Добавлено Сегодня, 17:33 А, ещё в Firefox-е из-под tor-а. Вообще не понимаю, о чем ты. |
| Автор: korvin 01.11.15, 21:51 |
| Цитата applegame @ Ну и пять лет - это вообще не срок. Похапе - 20 лет, Ruby - 20 лет, Python - 24 года, C++ - 32 года. D - 14 лет (D2 - 8 лет). Korvin, прекращай уже ехидствовать. Спрашивай по существу, без риторических бессмысленных вопросов. Похапе уже не менее десяти лет уверенно в продакшне, а п факту, почти с рождения; пистон практически основной скрипто-(и не только) язык в никсах (Дишники хотят эту нишу?), после шелла. Про C++ смешно, уже пару десятков лет в продакшне. Да что там. Go уже в продакшне. По существу я уже спрашивал: на какую нишу претендует Ди. Вроде, это уже обсуждали, похоже, ничего не изменилось: Дишники продолжают пытаться мерятся прибором в мире, где больше ценится результат, а не размер инструмента. Всё равно, что доказывать, что Хаммер круче лишь потому, что шире. |
| Автор: applegame 01.11.15, 22:33 |
| Цитата korvin @ И что дальше? То что быдлокодеры очень любят PHP не делает его удобным языком. Жабаскрипт - ну очень популярный язык, что не мешает ему быть говном. XML, один из худших языков разметки - весьма активно используется в продакшене. Популярность и качество практически не коррелируют друг с другом. Неужели тебе это непонятно? Вот ты например, насколько я помню, весьма одобряешь Plan 9. По твоей же логике оно полное говно, потому что никто его не использует, а все сидят на Win/Mac/Linux/BSD.Похапе уже не менее десяти лет уверенно в продакшне, а п факту, почти с рождения; пистон практически основной скрипто-(и не только) язык в никсах (Дишники хотят эту нишу?), после шелла. Про C++ смешно, уже пару десятков лет в продакшне. Да что там. Go уже в продакшне. А D тоже есть в продакшене, я приводил пример и не один. Я сам работаю с D в продакшне. Переписал проект с Ruby на D, потому что тормозило безбожно. Цитата korvin @ Ерунда. Я приводил ссылки с результатами из реальной жизни, а не с голым писькомерством. В вопросе же абстрактного меряния прибором дишники ничем не отличаются от сишников, плюсовиков, хаскелистов и всех прочих языкистов. Все одинаковы. Как бы тебе не хотелось обратного. По существу я уже спрашивал: на какую нишу претендует Ди. Вроде, это уже обсуждали, похоже, ничего не изменилось: Дишники продолжают пытаться мерятся прибором в мире, где больше ценится результат, а не размер инструмента. Всё равно, что доказывать, что Хаммер круче лишь потому, что шире. |
| Автор: Qraizer 02.11.15, 03:12 |
____________________.PNG (, : 701)
___________________________________________.PNG (, : 622)
|
| Автор: applegame 02.11.15, 05:09 |
| Это что-то у тебя. У меня открывается любым браузером. |
| Автор: OpenGL 02.11.15, 05:35 |
Может вирус в компе блокирует доступ к некоторым сайтам некоторым приложениям? О том, что вивальди является браузером вирусописатели просто не были в курсе? ![]() А с турбо-режимом в опере работает? |
| Автор: Qraizer 02.11.15, 12:58 |
У меня? Вирус? Добавлено Кстати, Престо-Опера тоже не робит. А Вивальди тоже на вебките. |
| Автор: D_KEY 02.11.15, 14:48 |
| Цитата applegame @ И что дальше? То что быдлокодеры очень любят PHP не делает его удобным языком. Жабаскрипт - ну очень популярный язык, что не мешает ему быть говном. XML, один из худших языков разметки - весьма активно используется в продакшене. Популярность и качество практически не коррелируют друг с другом. А что ты называешь качеством применительно к языкам программирования? Разве не для решения задач нужны языки? Разве они имеют самостоятельную ценность? |
| Автор: applegame 02.11.15, 17:13 |
| Например, количество и критичность ошибок дизайна, скорость написания кода, читаемость, уровень сложности поддержки и т.д. Мне непонятно, что ты этим хотел сказать. Очевидно, что ценность языка выявляется в удобстве использования его для решения задач. Добавлено Я бы на твоем месте не стал бы так легкомысленно относиться к этой угрозе. И на старуху бывает проруха. |
| Автор: D_KEY 02.11.15, 17:45 |
| А что за ошибки дизайна? Можно пример? И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны? Цитата скорость написания кода, читаемость, уровень сложности поддержки и т.д. Достаточно субъективные вещи. Т.е. опираться объективно мы тут можем только на статистику, в данном случае - на всю ту же популярность. Цитата Очевидно, что ценность языка выявляется в удобстве использования его для решения задач. Но если мы убираем популярность, то как же объективно оценить "удобство"? Если D такой удобный, то почему им так мало пользуются? Добавлено Приведу пример. Мне не нравится Go, но я не могу отрицать, что он зацепил многих и на нем уже пишут серьёзные проекты, которые используются в реальных системах. Это значит, что go полезен, что он смог привлечь внимание существенной части разработчиков и оказался удобен(чтобы я сам не думал по этому поводу и каким бы убогим не считал этот язык). |
| Автор: applegame 02.11.15, 18:50 |
| Не задавай глупых вопросов. Если ты действительно не в состоянии найти в интернетах ошибки дизайна, например PHP, то собственно разговор с тобой можно считать оконченым. Цитата D_KEY @ Есть объективные критерии, а опираться на популярность - весьма глупая затея.Достаточно субъективные вещи. Т.е. опираться объективно мы тут можем только на статистику, в данном случае - на всю ту же популярность. Чтобы оценить съедобность говна, тебе нужно собрать статистику о его популярности в народных массах? Я точно не знаю. Мое личное мнение - недостаток корпоративной поддержки, а также огромный выбор других языков, которого не было 20 лет назад. В наше время маргинальным языкам очень трудно набрать популярность, если никто не трезвонит о них. Цитата D_KEY @ Причина проста - Google. И то, что Go даже при такой поддержке очень тухло набирает популярность - лишний раз доказывает, что он убог.Приведу пример. Мне не нравится Go, но я не могу отрицать, что он зацепил многих и на нем уже пишут серьёзные проекты, которые используются в реальных системах. Это значит, что go полезен, что он смог привлечь внимание существенной части разработчиков и оказался удобен(чтобы я сам не думал по этому поводу и каким бы убогим не считал этот язык). Закономерно, что с появлением korvin и тебя, разговор опять смещается в совершенно левую плоскость. При выборе языка мне не интересна популярность, от слова совсем. Мне важны конкретные аргументы за и против. MyNameIsIgor четко и ясно сказал, что ему не нравится в D, мне тоже дохрена чего не нравится в D и я тоже об этом сказал. Я также четко и ясно сказал, что мне не нравится в Rust и Go. А ты и korvin, вместо беседы по существу, аппелируете к избитому, глупому аргументу - миллионы не могут ошибаться. Не надоело? |
| Автор: D_KEY 02.11.15, 19:01 |
Я сейчас даже не высказал свою позицию, не говоря уже об аргументах Я просто пытаюсь уточнить твою точку зрения. Добавлено Какие? Добавлено Цитата applegame @ Чтобы оценить съедобность говна, тебе нужно собрать статистику о его популярности в народных массах? Если ты хочешь обънктивности, то да. А то получится вкусовщина Добавлено Цитата applegame @ Причина проста - Google. И то, что Go даже при такой поддержке очень тухло набирает популярность - лишний раз доказывает, что он убог. Какой такой? Я вот не вижу, чтобы они его особо продвигали. Исходя из разговоров с адептами, могу сказать, что go, например, удачно подошёл тем, кто время от времени испытывает потребность в быстром создании относительно производительных сервисов, а опыт имеет при этом несколько другой - php/python. Такие специалисты не будут брать C/C++ и вряд ли полезут в Java-мир. Им просто и быстро даётся go, а ещё он позволяет решить их задачи. И Google тут ни при чем. D бы у них не пошёл, как бы и кто бы его не продвигал. Добавлено Цитата applegame @ А ты и korvin, вместо беседы по существу, аппелируете к избитому, глупому аргументу - миллионы не могут ошибаться. Не надоело? Я к этому аргументу не аппелирую, я лишь пытался понять твою логику отрицания фактора популярности. |
| Автор: applegame 02.11.15, 19:59 |
Все. Нет никаких объективных критериев. Только популярность решает. Тебе Go не нравится, но ты неправ, так как он популярен.Имя Google само по себе очень мощный двигатель. Каждый чих Гугла мгновенно разносится по новостным сайтам и прочим реддитам без всяких усилий с его стороны. Цитата D_KEY @ Я в свое время очень много писал на PHP и мне он очень нравился, я даже пытался его защищать от нападок. Наверное мне тогда очень понравился бы Go, если бы он тогда был. Исходя из разговоров с адептами, могу сказать, что go, например, удачно подошёл тем, кто время от времени испытывает потребность в быстром создании относительно производительных сервисов, а опыт имеет при этом несколько другой - php/python. Такие специалисты не будут брать C/C++ и вряд ли полезут в Java-мир. Им просто и быстро даётся go, а ещё он позволяет решить их задачи. И Google тут ни при чем. D бы у них не пошёл, как бы и кто бы его не продвигал. ![]() А насчет пошел бы D или не пошел, вопрос спорный. В одном я уверен, если бы например, Microsoft вдруг начал поставлять по умолчанию плагин VisualD вместе со своим VS, то популярность D выросла бы на порядки без каких-либо дополнительных телодвижений со стороны Microsoft. О кривизне PHP написано множество статей. Мне в свое время понравилась вот эта - PHP: Фрактал плохого дизайна (перевод). Там, на мой взгляд, очень точные и в тоже время забавные метафоры. И заодно есть ответы на твои вопросы. |
| Автор: DarkEld3r 02.11.15, 20:33 |
| Цитата D_KEY @ Нет, это только говорит, что (по сумме параметров) ничего лучше не нашлось. При этом на выбор влияет, в том числе, наличие инструментов, библиотек, готовых специалистов и т.д. Так что новым языкам взлететь действительно нелегко, особенно если это языки "общего назначения" не дающие сильного преимущества в чём-то конкретном.И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны? Ну и я поддержу applegame в том, что это повторение банальностей и не интересно. В конце концов, я уверен, что тут это каждый понимает, а значит можно пофлеймить не отвлекаясь на эти "скучные вещи". |
| Автор: D_KEY 02.11.15, 20:36 |
| Цитата applegame @ О кривизне PHP написано множество статей. Мне в свое время понравилась вот эта - PHP: Фрактал плохого дизайна (перевод). Там, на мой взгляд, очень точные и в тоже время забавные метафоры. И заодно есть ответы на твои вопросы. это оно? Цитата D_KEY @ Цитата Мяут-Настоящий @ Проблема состоит в том, что пых только из них и состоит ;-D http://me.veekun.com/blog/2012/04/09/php-a...-of-bad-design/ Прочел. Мда Может быть у участников темы есть какие-то возражения? Добавлено Да меня твоё мнение интересует. Ты считаешь, что есть объективные критерии, а значит, вероятно, можешь их назвать. Цитата Тебе Go не нравится, но ты неправ, так как он популярен. Почему сразу неправ? Просто необъективен. Цитата А насчет пошел бы D или не пошел, вопрос спорный. Ну конкретно в приведенном мною случае точно не пошёл бы Слишком сложен.Цитата В одном я уверен, если бы например, Microsoft вдруг начал поставлять по умолчанию плагин VisualD вместе со своим VS А он бы и начал, если бы было выгодно C++ же поставляет. Хотя и по C++ видно, что к нему внимания меньше, чем когда-то...Цитата то популярность D выросла бы на порядки без каких-либо дополнительных телодвижений со стороны Microsoft. Хм. Популярность, скажем, F# оставляет желать лучшего. А это детище ms, его проповедуют их евангелисты, по нему пишут книги и т.д. и т.п. Не все определяется поддержкой. Людям проще взять C#. Вообще довольно интересно, почему взлетает тот или иной язык... Это что-то из области психологии/социологии, как мне кажется. Добавлено Цитата DarkEld3r @ Цитата D_KEY @ Нет, это только говорит, что (по сумме параметров) ничего лучше не нашлось.И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны? Ну так это и есть "не существенны" Т.е. задачу позволяют решить лучше, чем другие. Даже при наличии недостатков...Цитата Так что новым языкам взлететь действительно нелегко, особенно если это языки "общего назначения" не дающие сильного преимущества в чём-то конкретном. Так может такие языки и не нужны? Естественный отбор, ничего личного. Цитата а значит можно пофлеймить не отвлекаясь на эти "скучные вещи". ![]() Да я не против. Просто выходит не очень весело. |
| Автор: DarkEld3r 03.11.15, 10:05 |
| Цитата D_KEY @ Забавно, что я тоже F# в пример привести хотел, правда вывод сделал прямо противоположный. MS особо и не продвигает этот язык, особенно если с шарпом сравнить. Да чего там, мне кажется, что про С++ они и то больше говорят. Хм. Популярность, скажем, F# оставляет желать лучшего. А это детище ms, его проповедуют их евангелисты, по нему пишут книги и т.д. и т.п. Не все определяется поддержкой. Людям проще взять C#. Тем не менее, про F# "все", как минимум, знают. Скала на .net не взлетела, а F# худо-бедно живёт как раз потому что есть из коробки и сделан "хозяевами платформы". Цитата D_KEY @ Нет, не значит. Ну так это и есть "не существенны" Т.е. задачу позволяют решить лучше, чем другие. Даже при наличии недостатков...Ну и давай всё-таки отделять более-менее объективные достоинства/недостатки и зрелость языка/платформы. Смотря для чего. Мне они нужны, как минимум, чтобы мозг размять. Опять же, эксперименты отрасль двигают, что тоже хорошо. Ну да, особенно если постоянно повторять мантру "зачем нужен язык N, если язык M популярнее". |
| Автор: D_KEY 03.11.15, 16:53 |
| Цитата DarkEld3r @ Цитата D_KEY @ Нет, не значит. Ну так это и есть "не существенны" Т.е. задачу позволяют решить лучше, чем другие. Даже при наличии недостатков...Хм... Нет, значит Ну серьезно, если язык выбирают, значит даже с его недостатками он справляется с решением задач. И то, что существуют более "красивые" языки, которые проигрывают конкурентную борьбу, ничего не меняет. Это не значит, что не нужно создавать новые языки(это отдельная тема для разговора) или изучать их. Просто игнорировать популярность значит отрицать конкурентную борьбу и её плоды. Каким бы ни были c/c++/java/php/js/etc., они в этой самой борьбе победили, а, значит, обладают набором таких достоинств, которые в определённое время и в определённом месте были востребованы настолько, что никакие уродства не смогли помешать взлету этих языков. |
| Автор: korvin 03.11.15, 17:16 |
| Цитата DarkEld3r @ Мне они нужны, как минимум, чтобы мозг размять. Опять же, эксперименты отрасль двигают, что тоже хорошо. Как языки, не предоставляющие ничего нового, помогают мозги размять? Я-то думал для этого обычно берут языки, сильно отличающиеся от тех, что ты уже знаешь. Цитата DarkEld3r @ Ну да, особенно если постоянно повторять мантру "зачем нужен язык N, если язык M популярнее". Ну если на неё не отвечать, то её и будут повторять. Одно дело, когда такое спрашивают про новый язык. Про Go спрашивали, про много что спрашивали, наверняка. И спустя 14 лет существования и развития, услышать "на нём можно быстрый JSON-парсер написать" --- это как-то уныло и не отвечает на вопрос. У Ruby, например, есть (были) хотя бы Рельсы, предоставляющие удобное комплексное решение для разработки веб-приложений. Кто разрабатывает "приложения для парсинга JSON"? Есть же vibe.d (или как там его), ну и показали бы историю успеха, где, скажем, замена (полная или хотя бы частична) Ruby на D привела к значительному росту производительности при сопоставимых затратах на разработку и сопровождение. Или с другой стороны: историю успеха перехода с C++ на D, который привёл к значительному сокращению трудозатрат при сопоставимой производительности программы. Применительно к этой самой библиотеки для парсинга JSON: вот есть у нас большой проект на Java, ты предлагаешь его полностью перевести на D из-за этой библиотечки? Использовать эту библиотеку в проекте через JNI (D ведь умеет в SO?)? Что мне это даст, учитывая, что основная вычислительная нагрузка идёт не на сериализацию (при том, что её достаточно используется), а на "бизнес-логику"? Ну, допустим, можно использовать в проекте на D, вот таких примеров и хотелось бы увидеть, а не "смотрите, как красиво на Хаскелле пишется функция вычисления факториала". Docker же, мы, вероятней всего, будем использовать в ближайшем будущем, если не найдём ничего лучше. При этом, нам не важно на чём он там написан, если он решает нашу задачу достаточно удобным для нас способом. |
| Автор: applegame 03.11.15, 20:07 |
| Цитата korvin @ Это ты так поставил вопрос сам, а не я. Я уже приводил ссылку на реальный проект с применением vibe.d, но ты же видишь только то, что тебе хочется видеть. У меня есть реальная история успеха перевода проекта с Sinatra (ruby) на vibe.d, с многократным увеличением производительности при примерно таких же расходах на разработку.И спустя 14 лет существования и развития, услышать "на нём можно быстрый JSON-парсер написать" --- это как-то уныло и не отвечает на вопрос. Форум dlang.org - работает на D. Сайт vibe.d работает на D. Чем не реальные проекты? Парсер JSON на D - всего лишь один из примеров. Ты же извратил сказанное так, как тебе самому захотелось, а именно: "D годится только на написание быстрых парсеров JSON, а значит бесполезен". |
| Автор: D_KEY 04.11.15, 10:32 |
| applegame, проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать. И не надо путать. Популярность является не аргументом, а скорее критерием. У D было достаточно времени, чтобы показать себя. |
| Автор: DarkEld3r 04.11.15, 15:10 |
| Цитата D_KEY @ Да, но это не значит отсутствие и несущественность недостатков. А начали мы именно с этого.Ну серьезно, если язык выбирают, значит даже с его недостатками он справляется с решением задач. Что значит игнорировать? Я ж не отрицаю фактор популярность и что это, при выборе языка, довольно много значит. Просто предлагаю не подменять популярностью всё остальное. Если у языка есть объективные достоинства или недостатки, то их можно и нужно учитывать, а не сводить всё к "ну раз он популярнее, то лучше (во всём)". Тем более, что ты сам говоришь про "определённое время и место". Да, у текущего мейнстрима было, в своё время, были (а может и остались, не важно) преимущества. Вот только сейчас к ним добавилось большое количество библиотек, специалистов, книг, курсов и т.д. Плюс в раскрутку многих языков были вложены немалые ресурсы. И это всё очень сильно перевешивает чашу в их пользу. Я просто сомневаюсь, что сейчас возможны быстрые революции, а не постепенное наращивание популярности. Вон даже свифт - более продвинутый, продвигается владельцами платформы, активно развивается и всё такое. И то на обжектив-С продолжают и ещё долго будут продолжать писать. И это при том, что язык изначально делался для лёгкой интеграции с имеющейся инфраструктурой. Если что, я не считаю, что всем нужно бросать "старьё" и бегом браться за новомодные языки. Тем более, что не могу сказать, что хоть один из них меня прямо так "идеально устраивает". Кстати, в D реализуют понемногу возможность использовать "любые" плюсовые библиотеки. Это здорово может на популярность языка повлиять. Цитата korvin @ Речь о другом шла - не о наличии нового, а о ярко выраженной "практической пользе" и о том, что это помогает для "взлёта" языка. Вот у Go она есть похоже, хотя "принципиально нового" и нет. Ну если мы гороутины таким считать не будем. Как языки, не предоставляющие ничего нового, помогают мозги размять? Я-то думал для этого обычно берут языки, сильно отличающиеся от тех, что ты уже знаешь. И наоборот - в языке могут быть новаторские вещи, но сами по себе, не приносить (очевидной?) пользы. Скажем, лайфтамы в расте - вроде и полезно и ново (в курсе про Cyclone), но я не уверен, что этого будет достаточно. К счастью, у языке есть и другие приятные вещи. Или макросы в немерле - удобно и мощно, но похоже люди не ощущают явной необходимости в них. Да, мысль понятна и я, в общем-то более-менее согласен. Но тут есть нюансы. Скажем по расту есть специальный ресурс с новостями (кстати, у D такое есть?). То есть люди используют язык, пишут всякое разное и делятся опытом. Там и про низкоуровневый опыт пишут и про серво и игровые движки делать пробуют и т.д. То есть информации хватает, просто надо интересоваться, но ведь не будешь всё на форум тащить? Плюс хватает людей, которые язык (любой) более-менее изучили, но применять на практике не могут или "не хотят". Обсуждать на форуме проще чем тянуть проект. Впрочем, applegame писал же, что D применяет и доволен. Конечно, тут возникнет вопрос "а есть ли реальная польза", но это не всегда легко измерить. Кстати, как по мне, то даже новости типа обсуждаемой (про "самый быстрый парсер") полезны - напоминают об языке и всё такое. Добавлено Цитата D_KEY @ Просто из любопытства: уровень как меряется? Количеством кода, "качеством" или популярностью? проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать. |
| Автор: applegame 04.11.15, 18:49 |
| Цитата D_KEY @ Почему для Docker'а был выбран Go - интересный вопрос. Я нашел соответствующую презентацию - http://www.slideshare.net/jpetazzo/docker-...te-docker-in-go и похоже, что выбор был сделан чуть ли не из желания попробовать новый язык. На слайде 26 упоминается D applegame, проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать. , авторы даже не знали, что это такое. Потому что о Go кричат на каждом углу, а D никому не известен. А так, кто знает, что было бы если бы авторы при выборе языка посмотрели на бы на D. Цитата D_KEY @ Критерием чего? Успешного маркетинга? - полностью согласен И не надо путать. Популярность является не аргументом, а скорее критерием. У D было достаточно времени, чтобы показать себя. ![]() Добавлено Цитата DarkEld3r @ Да не я один. Есть несколько контор работающих с D. Даже пара вакансий есть где-то там далеко Впрочем, applegame писал же, что D применяет и доволен. Конечно, тут возникнет вопрос "а есть ли реальная польза", но это не всегда легко измерить. Цитата DarkEld3r @ Да, ведет один из активных участников коммьюнити. Даже называется аналогично Но тут есть нюансы. Скажем по расту есть специальный ресурс с новостями (кстати, у D такое есть?) - http://arsdnet.net/this-week-in-d/nov-01.htmlКоммьюнити D растет и становится более активными, релизы компилятора стали выходить чаще. Обсуждения стали активнее, разрабатывается еще один компилятор со своим фронтендом - SDC (у LDC, GDC и DMD один и тот же фронтенд, изначально написанный на C++, недавно портированный на D) |
| Автор: D_KEY 05.11.15, 21:37 |
| Цитата DarkEld3r @ Цитата D_KEY @ Да, но это не значит отсутствие и несущественность недостатков.Ну серьезно, если язык выбирают, значит даже с его недостатками он справляется с решением задач. На мой взгляд, существенный недостаток - это такой, который приводит к невозможности решить задачу или крайне затрудняет ее решение. А ты как считаешь? Добавлено Так я предлагаю их таки назвать Цитата Тем более, что ты сам говоришь про "определённое время и место". Да, у текущего мейнстрима было, в своё время, были (а может и остались, не важно) преимущества. Вот только сейчас к ним добавилось большое количество библиотек, специалистов, книг, курсов и т.д. Плюс в раскрутку многих языков были вложены немалые ресурсы. И какой из этого можно сделать вывод? Цитата Я просто сомневаюсь, что сейчас возможны быстрые революции, а не постепенное наращивание популярности. Пусть будет постепенное. Я что против? Но за 14 лет можно было себя показать... Цитата Вон даже свифт - более продвинутый, продвигается владельцами платформы, активно развивается и всё такое. И то на обжектив-С продолжают и ещё долго будут продолжать писать. Так это как раз пример того, что популярность далеко не во всем связан с продвижением. Мне, например, свифт не показался интересным языком. Возможно, разработчики просто не видят смысла в переходе. Цитата Кстати, в D реализуют понемногу возможность использовать "любые" плюсовые библиотеки. Это здорово может на популярность языка повлиять. Зависит от качества решения. Но так да. Вообще, им следовало подумать об этом на раннем этапе развития языка. Проблема с D еще в том, что многие уже "перегорели". Цитата Цитата D_KEY @ Просто из любопытства: уровень как меряется? Количеством кода, "качеством" или популярностью?проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать. Объемом решаемых задач, контрибьютерами, комьюнити, компаниями и проектами, которые используют данный проект и т.п. Добавлено Цитата applegame @ Цитата D_KEY @ Критерием чего? Успешного маркетинга? - полностью согласен И не надо путать. Популярность является не аргументом, а скорее критерием. У D было достаточно времени, чтобы показать себя. ![]() В данном случае, видимо, неуспешного Но вообще к D это неприменимо. Маркетинг маркетингом, но в определенный момент разработчик выделяет время и пробует новый язык/технологию. И тут уже маркетинг уходит на задний план, а конкретные недостатки и достоинства на первый. Я уже приводил пример с Go. Вот конкретные разработчики, которые таки стали использовать Go, D бы использовать не стали. Языку нужна ниша. Нужны те реальные задачи, которые он позволит решать "лучше"(в каком-то из востребованных смыслов). |
| Автор: DarkEld3r 06.11.15, 14:09 |
Ну я не собирался защищать именно D. Просто тоже "задела" эта апелляция к популярности. Ладно, этот спор всё равно зашёл в тупик. Относительно достоинств и недостатков. Думаю, что ты можешь назвать немало раздражающих "мелочей" в С++. Доказывать, что это "существенные недостатки" не собираюсь, тем более, что я сам пишу как раз этом языке, как минимум, "без отвращения". Да и ничего нового мы друг другу не скажем. D мне не нравится, да и знаю его недостаточно, чтобы говорить о (не очевидных) преимуществах или проблемах. Могу рассказать про раст. Впрочем, проще говорить мне будет как раз о недостатках, вернее, о тех вещах, которые раздражают.Цитата D_KEY @ Дык, делается это через Clang/llvm, на раннем этапе его не было. Зависит от качества решения. Но так да. Вообще, им следовало подумать об этом на раннем этапе развития языка. Цитата D_KEY @ Мне тоже. Но ты думаешь, что без продвижения ситуация не была бы намного хуже?Так это как раз пример того, что популярность далеко не во всем связан с продвижением. Мне, например, свифт не показался интересным языком Я уверен, что перебираться придётся - свифт будут развивать, а обжектив-С забросят. Но это как раз пример того как язык "искусственно" пропихивают. |
| Автор: DarkEld3r 10.11.15, 09:54 |
| Немного вброшу: Александреску спросили какой из языков (D/Go/Rust) имеет больше шансов заменить С. Он заодно и про С++ ответил. Ну и обсуждение на реддите, если кому интересно. |
| Автор: applegame 10.11.15, 10:33 |
DarkEld3r, почитываешь forum.dlang.org? ![]() И таки там не спрашивали Александреску. Там спрашивали вообще, а Алекандреску один из ответивших. Quora - это нечто вроде ответов.майл.сру. Интересно, чем руководствовались люди называя свой язык, например, "Коррозия Металла"? |
| Автор: korvin 10.11.15, 20:06 |
| Это только если сравнивать его с ЯП общего назначения (хотя Свифт формально тоже является таковым, но мы-то понимаем, что за пределами яблочных осей он никому не нужен, как и Обжектив-Си), но вот в качестве замены Обжектив-Си он более чем хорош. |
| Автор: DarkEld3r 11.11.15, 15:38 |
Не совсем, конкретно это нашёл на реддите (раз, два). Не так уж удивительно, что именно ответ Александреску тиражируют везде, тем более, что оно довольно взвешенным оказалось.Хотя и на forum.dlang.org иногда попадаю, например, недавно было интересно почитать мнение про "safe reference counting cannot be implemented as a library". Цитата applegame @ Вот тут есть сразу несколько объяснений, например: Интересно, чем руководствовались люди называя свой язык, например, "Коррозия Металла"? Цитата Rust is named after a fungus that is robust, distributed, and parallel. It is also a substring of "robust". Впрочем, учитывая разнообразие ответов, мне кажется, что объяснения появились позже самого названия. |
| Автор: applegame 11.11.15, 17:06 |
| Цитата DarkEld3r @ Цитата applegame @ Вот тут есть сразу несколько объяснений, например: Интересно, чем руководствовались люди называя свой язык, например, "Коррозия Металла"? Цитата Rust is named after a fungus that is robust, distributed, and parallel. It is also a substring of "robust". Впрочем, учитывая разнообразие ответов, мне кажется, что объяснения появились позже самого названия. Ага, то есть его на самом деле назвали не "Коррозия Металла", а "Ржавчинный гриб"? |
| Автор: applegame 11.11.15, 17:14 |
| Вот еще впечатление от Rust после С++/D - Rust impressions from a C++/D programmer |
| Автор: D_KEY 11.11.15, 19:11 |
| Лучше бы кто-нибудь рассказал, например, подробности ухода от gc в стандартной библиотеке D, да и несколько муторно отказываться от gc для классов и пр. |
| Автор: applegame 11.11.15, 21:29 |
| Цитата D_KEY @ Тебе это реально интересно? Эта тема постоянно перетирается на форуме dlang.orgЛучше бы кто-нибудь рассказал, например, подробности ухода от gc в стандартной библиотеке D, да и несколько муторно отказываться от gc для классов и пр. В стандартной либе стараются все максимально range'фицировать и lazy'фисировать. Отказываться от GC для классов сейчас достаточно просто: юзаем аллокаторы, которые в последней версии засунули в стандартную либу. Вместо new Foo(a, b, c) пишем allocator.make!Foo(a, b, c) / allocator.dispose(obj). Аллокаторов Александреска наделал несколько штук на разные случаи жизни. Причем сделаны они как конструктор: более простые можно собирать в более сложные - http://dlang.org/phobos/std_experimental_a...ing_blocks.html Из минусов: пока нет нормальных библиотечных аналогов shared_ptr и unique_ptr. Unique правда уже вроде как допилили. А так тот же RAII и scope(exit/success/failure) и вперед с песней. Но по сути в большинстве задач GC не мешает, а скорее наоборот помогает, ибо ничего не течет и не нужно париться с циклическими ссылками. Когда я использовал boost::asio, меня просто замучали эти weak_ptr/shared_ptr. Страх и ужас GC, по моему скромному, сильно преувеличен. Ну и нормальные иммутабельные классы, которые можно без синхронизации гонять между потоками, без GC непонятно как сделать. |
| Автор: D_KEY 11.11.15, 22:16 |
| Мне интересен потенциал опционального сборщика. Тут же заход немного с другой стороны. Цитата В стандартной либе стараются все максимально range'фицировать Это возможно для алгоритмов(которые и в C++ не связаны с памятью). А для контейнеров что? Аллокаторы? Т.е. умеют ли контейнеры работать с объектами в GC и не в GC? Цитата и lazy'фисировать. А это как с GC связано? Цитата Из минусов: пока нет нормальных библиотечных аналогов shared_ptr и unique_ptr. Unique правда уже вроде как допилили. А так тот же RAII и scope(exit/success/failure) и вперед с песней. Вот это грустно. Вроде же все средства для этого есть, просто не реализовали еще? Цитата Ну и нормальные иммутабельные классы, которые можно без синхронизации гонять между потоками, без GC непонятно как сделать. Не понял мысль. |
| Автор: applegame 12.11.15, 08:54 |
| Цитата D_KEY @ Эм, потенциал таков, что ты можешь отказаться от GC полностью.Мне интересен потенциал опционального сборщика. Тут же заход немного с другой стороны. Цитата D_KEY @ Не совсем понимаю, что значит работать с объектами в GC или не GC. Какая разница для контейнера откуда взялась память для объектов (если конечно эту память не выделяет сам контейнер)?А для контейнеров что? Аллокаторы? Т.е. умеют ли контейнеры работать с объектами в GC и не в GC? Что касается аллокаторов, то на данный момнет нет встроенных в стандартную либу контейнеров умеющих использовать аллокаторы. Александреска только собирается их писать. Есть сторонние либы с контейнерами и аллокаторами, также есть сторонние реализации аналогов shared_ptr и unique_ptr. Напрямую с GC не связано, но связано с аллокациями. Функции возвращающие ленивые ренджи никогда не делают аллокаций памяти. В стандартной либе вроде есть RefCounted и Unique но они почему-то не работают с классами (не в смысле глючат, а в смысле запрограмиированы не принимать классы). На форуме идут дискуссии. Александреску помешан на безопасности, а библиотечная реализация таких объектов действительно не может быть полностью безопасной. Ему отвечают: ну и что? Пусть будет небезопасно, живут же всякие shared_ptr/unique_ptr - все довольны. Конечно же все кому сильно надо написали свои велосипеды на эту тему. Ну а Александреска предлагает встроить поддержку RC-объектов непосредственно в язык шобы было ну ваще безопасно. По мне так это перебор. В крайнем случае достаточно изобрести очередной аттрибут, для пометки RC-объектов, чтобы компилятор знал, что это RC и пресекал попытки вынести из комнаты кишки такого объекта. Это относительно большая тема. В D кроме модификатора const есть еще модификатор immutable. По отношению к value-типам особой разницы между ними нет. А вот для ссылочных объектов разница существенна. Если функция получила в качестве параметра const-объект, то это значит, что она гарантирует неизменность этого объекта. При этом такой объект может быть изменен где-то в другом месте (например, в другом потоке). То есть наша функция сама дает гарантии неизменности, но не получает таковых. Если же функция получила в качастве параметра immutable-объект, то это значит что она получает гарантию, что никто (в том числе и она сама) не может изменить (в том числе и уничтожить) этот объект нигде и никогда. То есть immutable-объекты можно спокойно распространять по всей программе, в том числе мужду потоками без синхронизации и без счетчика ссылок. Я не представляю как сделать такое поведение объектов без GC. В моем проекте постоянно создаются и уничтожаются небольшие иммутабельные объекты. Эти объекты не менее постоянно курсируют между потоками в виде иммутабельных же массивов, слайсов на иммутабельные массивы или ленивых ренджей поверх иммутабельных массивов. Благодаря иммутабельности и GC я могу это делать безопасно и без утечек полностью забив на синхронизацию и головную боль с временем жизни этих объектов и массивов, в которых они лежат. В C++ пришлось бы использовать shared_ptr (без гарантий иммутабельности, а значит небезопасно), который при каждом копировании создает write barrier со всеми вытекающими, а так как такие копирования происходят постоянно и в больших количествах, то можно поспорить, что будет производительнее: весь такой zero-abstraction-cost shared_ptr или обычные указатели с якобы тормозным GC. |
| Автор: MyNameIsIgor 12.11.15, 09:26 |
| Зачем, если объект иммутабельный? Все его копии равнозначны. Отдайте в другой поток его копию. И тогда уже нельзя будет поспорить, что производительнее: стек или черепаха GC. Вы тут вообще мешаете понятия неизменяемости и умные указатели. Это вещи ортогональные. shared_ptr не привносит никакой небезопасности, кроме той, что уже есть в языке. |
| Автор: D_KEY 12.11.15, 09:39 |
| И страдать? Цитата Какая разница для контейнера откуда взялась память для объектов (если конечно эту память не выделяет сам контейнер)? Цитата Что касается аллокаторов, то на данный момнет нет встроенных в стандартную либу контейнеров умеющих использовать аллокаторы. Так а кто выделяет память? Память для элементов лежит в GC? Цитата Это относительно большая тема. В D кроме модификатора const есть еще модификатор immutable. По отношению к value-типам особой разницы между ними нет. А вот для ссылочных объектов разница существенна. Если функция получила в качестве параметра const-объект, то это значит, что она гарантирует неизменность этого объекта. При этом такой объект может быть изменен где-то в другом месте (например, в другом потоке). То есть наша функция сама дает гарантии неизменности, но не получает таковых. Если же функция получила в качастве параметра immutable-объект, то это значит что она получает гарантию, что никто (в том числе и она сама) не может изменить (в том числе и уничтожить) этот объект нигде и никогда. Это понятно и знакомо. Цитата То есть immutable-объекты можно спокойно распространять по всей программе, в том числе мужду потоками без синхронизации и без счетчика ссылок. Я не представляю как сделать такое поведение объектов без GC. По мне так управление памятью ортогонально иммутабельности. Так а почему без счетчика ссылок-то? Как он мешает immutable? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> struct A { const int a; const int b; }; // если являемся одним из владельцев void thread_fun(std::shared_ptr<A> obj) { // читаем сколько влезет из obj без синхронизации } // если не являемся владельцем void thread_fun(const A & obj) { // читаем сколько влезет из obj без синхронизации } Цитата В моем проекте постоянно создаются и уничтожаются небольшие иммутабельные объекты. Эти объекты не менее постоянно курсируют между потоками в виде иммутабельных же массивов, слайсов на иммутабельные массивы или ленивых ренджей поверх иммутабельных массивов. Ну это вполне может жить или на подсчете ссылок или с удалением объектов при завершающей обработке(если таковая имеется) или каким-то сочетанием этого. GC тут, конечно, упрощает жизнь, но иммутабельность тут ни при чем, ИМХО. Цитата В C++ пришлось бы использовать shared_ptr (без гарантий иммутабельности, а значит небезопасно) Почему без гарантий иммутабельности? Цитата который при каждом копировании создает write barrier со всеми вытекающими, а так как такие копирования происходят постоянно и в больших количествах Почему постоянно? Почему в больших количествах? Очень часто тебе вообще достаточно unique_ptr и каких-то очередей/каналов между воркерами. Нет? Цитата то можно поспорить, что будет производительнее: весь такой zero-abstraction-cost shared_ptr или обычные указатели с якобы тормозным GC. Ну в такой постановке да. Сейчас речь не о холиваре "GC против всех", а о том, насколько хорошо в языке может жить опциональный сборщик. |
| Автор: applegame 12.11.15, 10:34 |
| Цитата MyNameIsIgor @ Копирование массивов или глубокое копирование объектов содержащих другие объекты - не очень-то производительное решение. Речь идет об указателях на immutable-данные.Зачем, если объект иммутабельный? Все его копии равнозначны. Отдайте в другой поток его копию. И тогда уже нельзя будет поспорить, что производительнее: стек или черепаха GC. Цитата MyNameIsIgor @ Не совсем ортогональные. Умный указатель не может быть "честно" иммутабельным по определению. А значит не может содержаться в другом иммутабельном объекте.Вы тут вообще мешаете понятия неизменяемости и умные указатели. Это вещи ортогональные. Страдать? Не более, чем в C++. Если сначала жил с GC, а тут, опа, и нужно от него отказаться, тогда да, будешь страдать. ![]() Эту уже от самого контейнера зависит. Пока все встроенные в стандартную либу контейнеры берут память исключительно у GC. Контейнеры построенные на базе аллокаторов берут память собственно у аллокатора, в качестве которого может выступать также и GC. То есть это уже будут универсальные контейнеры. По умолчанию память хапается у GCAllocator, а там можно переключиться на Mallocator или какой-нибудь FreeListAllocator с бэкендом на том же GCAllocator/Mallocator. Цитата D_KEY @ Я так не считаю. ИМХО, честную иммутабельность принципиально нельзя сделать без GC. Возможно я ошибаюсь, эта тема весьма интересна мне, посему - Цитата По мне так управление памятью ортогонально иммутабельности.То есть immutable-объекты можно спокойно распространять по всей программе, в том числе мужду потоками без синхронизации и без счетчика ссылок. Я не представляю как сделать такое поведение объектов без GC. ![]() Цитата D_KEY @ Дык, объект-то нифига не иммутабельный, то бишь владелец объекта может его легально изменить (например по ошибке программиста) без сопротивления со стороны компилятора, и второй поток прочитает половину объекта со старыми данными, а половину с новыми, нарушив какой-нибудь инвариант. Так а почему без счетчика ссылок-то? Как он мешает immutable? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> struct A { const int a; const int b; }; // если являемся одним из владельцев void thread_fun(std::shared_ptr<A> obj) { // читаем сколько влезет из obj без синхронизации } // если не являемся владельцем void thread_fun(const A & obj) { // читаем сколько влезет из obj без синхронизации } Цитата D_KEY @ Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов. Причем несколько потоков могут одновременно работать с одними и теми же объектами. Объекты регулярно уничтожаются и создаются новые. Можно было действительно просто копировать все целиком и отправлять копии другим потокам, но это я посчитал очень неэффективным в плане производительности, да и зачем, если все иммутабельное, и я могу спокойно слать потокам только указатели на эта данные.Цитата который при каждом копировании создает write barrier со всеми вытекающими, а так как такие копирования происходят постоянно и в больших количествах Почему постоянно? Почему в больших количествах? Очень часто тебе вообще достаточно unique_ptr и каких-то очередей/каналов между воркерами. Нет? Цитата D_KEY @ Хз, по мне "опциональный" не совсем корректное выражение. Сам язык не требует GC, кроме считанных фич. И тут не стоит впрос использовать эти фичи с GC или без. Либо с фичами и с GC, либо без GC и без фич. Лишение этих фич доставляет страдания только тем, кто ими раньше активно пользовался. Скажем плюсовики и раньше не могли взять и склеить два массива специальной конструкцией языка, так что лишение такой возможности в D они даже не заметят. Сейчас речь не о холиваре "GC против всех", а о том, насколько хорошо в языке может жить опциональный сборщик. |
| Автор: MyNameIsIgor 12.11.15, 10:40 |
| |
| Автор: applegame 12.11.15, 10:52 |
| "Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет. |
| Автор: D_KEY 12.11.15, 10:56 |
| Почему не может? И зачем ему быть иммутабельным, если нужен иммутабельный объект, а указатель можно копировать. Или тебя смущают изменяемые счетчики? Но это внутренние потроха, потокобезопасность же тебе гарантируется. Цитата Страдать? Не более, чем в C++. Ну как не более, если даже контейнеры без GC не работают в D? Цитата ИМХО, честную иммутабельность принципиально нельзя сделать без GC. А почему? Цитата Дык, объект-то нифига не иммутабельный, то бишь владелец объекта может его легально изменить (например по ошибке программиста) без сопротивления со стороны компилятора Там же константные поля. Так что с сопротивлением Покажи код(лучше на C++, чтобы не было недоразумений). Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов. Причем несколько потоков могут одновременно работать с одними и теми же объектами. Объекты регулярно уничтожаются и создаются новые. Можно было действительно просто копировать все целиком и отправлять копии другим потокам, но это я посчитал очень неэффективным в плане производительности, да и зачем, если все иммутабельное, и я могу спокойно слать потокам только указатели на эта данные. Цитата Сам язык не требует GC, кроме считанных фич. И контейнеров, например |
| Автор: MyNameIsIgor 12.11.15, 10:58 |
| Цитата applegame @ "Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет. Что такое "действительно не меняет своё внутреннее состояние"? У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи? |
| Автор: D_KEY 12.11.15, 11:02 |
| Цитата applegame @ "Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет. Так какая разница, если тебе предоставляют гарантии корректной работы счетчиков RC в многопоточной среде? |
| Автор: applegame 12.11.15, 11:30 |
| Контейнеры - это не D, это библиотеки. В сторонних библиотеках (которые можно поставить дешным пакетным менеджером dub) есть контейнеры с аллокаторами, RC и прочая. То что нет в стандартной - это да печаль и говно. А что будет если владелец уничтожит объект? Например первый поток закончит работу раньше второго? Цитата MyNameIsIgor @ Это гарантия того, что в любой момент времени можно прочитать это состояние и оно всегда будет одним и тем же. Допустим некий компилятор увидев, что данный объект иммутабельный, и со спокойной совестью берет и помещает его в область памяти с защитой от записи. И если Вася вас обманул, то в какой-то момент ваше приложение упадет. Что такое "действительно не меняет своё внутреннее состояние"? У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи? |
| Автор: MyNameIsIgor 12.11.15, 11:37 |
| Цитата applegame @ Это гарантия того, что в любой момент времени можно прочитать это состояние и оно всегда будет одним и тем же. Допустим некий компилятор увидев, что данный объект иммутабельный, и со спокойной совестью берет и помещает его в область памяти с защитой от записи. Не понимаю, как из гарантии того, что я прочитаю одно и то же состояние, следует, что объект может быть в области с защитой от записи? |
| Автор: applegame 12.11.15, 11:42 |
| Цитата D_KEY @ Тут дело в безопасности. Зачем, например, нужен модификатор const, если тебе предоставляют гарантии, что эта вот функция, мамой клянус, не изменяет состояние этого вот объекта? То есть то что касается именно shared_ptr, то тут никаких сомнений нет. Я знаю, что он меняет cвое состояние (счетчик), и его константные функции не совсем константные (так как опять же меняют счетчик), но на это можно закрыть глаза, так как это работает. Но если вот этот тип T для меня сделал Вася, то я бы очень хотел, чтобы его const функции были бы на самом деле const. А то я создам immutable глобальную переменную типа T, компилятор запихнет ее в data-сегмент, а тут выяснится, что const-функция оказалась не const и все дело падает в ран-тайме. Нехорошо, Вася. Нехорошо. Так какая разница, если тебе предоставляют гарантии корректной работы счетчиков RC в многопоточной среде? Добавлено Цитата MyNameIsIgor @ не просто прочитаете одно и тоже состояние, а в любой момент времени прочитаете одно и тоже состояние, из чего следует, что никто и никогда не должен изменять эти данные.Не понимаю, как из гарантии того, что я прочитаю одно и то же состояние, следует, что объект может быть в области с защитой от записи? Почему бы параноидальному компилятору и не засунуть этот объект в область с защитой от записи? Более того, компиляторы в некоторых случаях так и делают. Например строковые литералы в C++/D "честно" иммутабельные. В линупсе попытка записи в такой литерал приведет к сегфолту. |
| Автор: MyNameIsIgor 12.11.15, 11:48 |
| Цитата applegame @ не просто прочитаете одно и тоже состояние, а в любой момент времени прочитаете одно и тоже состояние, из чего следует, что никто и никогда не должен изменять эти данные. Дададада. Цитата applegame @ Почему бы параноидальному компилятору и не засунут этот объект в область с защитой от записи? Более того компиляторы в некоторых случаях так и делают На каком основании? С чего вы вообще взяли, что всегда читать одно и то же состояние - это всё равно, что в объект никто не пишет? Добавлено Я, конечно, троллю. И знаю, что поскольку в D было слабо вставить зависимые типы, сделали тупо побитовую неизменность, назвали это безопасностью и вот теперь адепты этого недоязыка познают понятие неизменяемости через призму D. Печально, фигли... |
| Автор: applegame 12.11.15, 12:04 |
| Цитата MyNameIsIgor @ А кому было не слабо вставить зависимые типы? Idris? ATS? Такие чисто ситемные языки приближенные к hardware. И совсем не академические. Я, конечно, троллю. И знаю, что поскольку в D было слабо вставить зависимые типы, сделали тупо битовую неизменность, назвали это безопасностью и вот теперь адепты этого недоязыка познают понятие неизменяемости через призму D. Печально, фигли... ![]() И зря вы так об адептах D. Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше? |
| Автор: MyNameIsIgor 12.11.15, 12:06 |
| Цитата applegame @ Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше? Да любой функциональный язык может. Там все сущности иммутабельны, но почему-то не расположены в памяти с защитой от записи. Интересно, почему? Добавлено Проблема в том, что если хочется приблизиться к "железу", то чем-то надо жертвовать. Я не понимаю обеспечение безопасности с помощью изъятия у всех кухонных ножей. |
| Автор: D_KEY 12.11.15, 12:16 |
| Цитата applegame @ А что будет если владелец уничтожит объект? Например первый поток закончит работу раньше второго? Так там же shared_ptr. Добавлено Цитата applegame @ Но если вот этот тип T для меня сделал Вася, то я бы очень хотел, чтобы его const функции были бы на самом деле const. А то я создам immutable глобальную переменную типа T, компилятор запихнет ее в data-сегмент, а тут выяснится, что const-функция оказалась не const и все дело падает в ран-тайме. Нехорошо, Вася. Нехорошо. Это возможно неплохая соломка, но по сути своей гарантии корректной работы в данном случае ничем не отличается от других контрактов. Если Вася тебя обманул в этом вопросе, то где гарантии, что он в принципе корректно реализовал то, что ты используешь? |
| Автор: applegame 12.11.15, 12:23 |
| Цитата MyNameIsIgor @ Потому что у всех изъяли, как вы выразились, кухонные ножи. А в каком-нибудь Haskell изъяли также вилки, ложки и иголки.Да любой функциональный язык может. Там все сущности иммутабельны, но почему-то не расположены в памяти с защитой от записи. Интересно, почему? Цитата MyNameIsIgor @ Я тоже этого не понимаю. В итоге имеем монстра D, в который все пичкают и пичкают всякие ненужные хрени вроде якобы безопасного RC. Правильно ругался на Александреску один из адептов D: прежде чем думать о безопасном аж жуть RC, сделайте обычный не совсем безопасный RC а-ля шаред_птр, и не совсем безопасные контейнеры с аллокаторами. А они вместо этого дружно ломают голову над тем как впихнуть невпихуемое. Проблема в том, что если хочется приблизиться к "железу", то чем-то надо жертвовать. Я не понимаю обеспечение безопасности с помощью изъятия у всех кухонных ножей. Во второй поток ты передал ссылку на сам объект а не shared_ptr. Цитата D_KEY @ <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> struct A ... // если не являемся владельцем void thread_fun(const A & obj) { // читаем сколько влезет из obj без синхронизации } |
| Автор: D_KEY 12.11.15, 12:45 |
| Сорри, я неправильно объяснил. Это не второй поток. Или все потоки работают с shared_ptr или есть отдельные воркеры, которые не являются владельцами и просто читают объект по ссылке и есть какой-то агрегатор, который владеет объектом и ожидает завершения воркеров. |
| Автор: Qraizer 12.11.15, 12:55 |
| Цитата applegame @ Константные объекты вместо константных ссылок на них, не? А честная она там или нет, это никому не интересно. Если даже и есть внутри mutable-поля, это проблемы сугубо автора класса и компилятора. Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше? |
| Автор: applegame 12.11.15, 13:10 |
| Тоже предлагаешь копировать константный массив на сто элементов? Цитата Qraizer @ А если такой объект расположен в ПЗУ? Компилятор же не в состоянии распознать честная иммутабельность или нет? Написано immutable, значит immutable. А честная она там или нет, это никому не интересно. Если даже и есть внутри mutable-поля, это проблемы сугубо автора класса и компилятора. |
| Автор: Qraizer 12.11.15, 13:52 |
| Зачем копировать? Создал константный объект и радуешься. Хочешь – копируй, хочешь – ссылайся. Если объект расположен в ПЗУ, он по определению не может быть создан конструктором, потому что тот предполагает модификацию полей объекта для придания ему некоего состояния. В таком случае он должен быть туда помещён уже сконструированным, и для работы с ним достаточно ссылки. |
| Автор: MyNameIsIgor 12.11.15, 14:14 |
| Это же был пример, т.к. вы говорили про "маленькие иммутабельные объекты" ![]() Вариантов может быть много. Добавлено Во, кстати, а какой GC сейчас использует D? Если как и раньше BoehmGC, то это fail. |
| Автор: applegame 12.11.15, 14:22 |
| Цитата Qraizer @ Сосбственно об этом я и говорил.Зачем копировать? Создал константный объект и радуешься. Хочешь – копируй, хочешь – ссылайся. Цитата Qraizer @ Отлично. А теперь ты по этой ссылке вызываешь некий const-метод этого класса, а он оказывается не совсем const и пытается модифицировать свои поля, которые находятся в области недоступной для записи. Если объект расположен в ПЗУ, он по определению не может быть создан конструктором, потому что тот предполагает модификацию полей объекта для придания ему некоего состояния. В таком случае он должен быть туда помещён уже сконструированным, и для работы с ним достаточно ссылки. Добавлено Цитата MyNameIsIgor @ Ага, он самый, родной. В теории может течь, но на практике не течет. По крайней мере на 64-битном линупсе. Во, кстати, а какой GC сейчас использует D? Если как и раньше BoehmGC, то это fail. |
| Автор: MyNameIsIgor 12.11.15, 14:40 |
| Цитата applegame @ Ага, он самый, родной. В теории может течь, но на практике не течет. По крайней мере на 64-битном линупсе. Да он не должен течь. Просто консервативный, может что угодно за указатель посчитать и не почистить. С другой стороны он должен меньше ресурсов требовать, тегирование всякое ему не нужно. Но получается, что я и на C++ могу получить GC того же качества, что в D |
| Автор: applegame 12.11.15, 14:44 |
| Цитата MyNameIsIgor @ Поэтому и может течь. Теоретически. Точнее даже не течь, а просто зажимать память до некоторого момента.Да он не должен течь. Просто консервативный, может что угодно за указатель посчитать и не почистить. Конечно. Собственно, ЕМНИП, BoehmGC изначально и был придуман для C/C++. |
| Автор: MyNameIsIgor 12.11.15, 14:46 |
| Именно так. |
| Автор: DarkEld3r 12.11.15, 15:02 |
| Цитата applegame @ Читал, местами интересно. С чем-то согласен (например, Display/Debug), а что-то наоборот кажется преимуществом. Ну и кое-что "когда-то допилят/исправят". Вот еще впечатление от Rust после С++/D - Rust impressions from a C++/D programmer |
| Автор: Qraizer 12.11.15, 15:15 |
| Цитата applegame @ Хорошо, давай развёрнуто.Цитата Qraizer @ Отлично. А теперь ты по этой ссылке вызываешь некий const-метод этого класса, а он оказывается не совсем const и пытается модифицировать свои поля, которые находятся в области недоступной для записи.Если объект расположен в ПЗУ, он по определению не может быть создан конструктором, потому что тот предполагает модификацию полей объекта для придания ему некоего состояния. В таком случае он должен быть туда помещён уже сконструированным, и для работы с ним достаточно ссылки. Константный объект является константным. Константный метод не может в своём объекте что-либо изменить, компиляция не пройдёт. Но он может снять константность const_cast<> и менять что угодно. Прав ли он? Ответ двоякий. Стандарт языка описывает корректность сей конструкции для объектов, не создававшихся константными. Т.е. для тех, которые обычные, но константность им была придана дополнительными мерами. Например, посредством передачи по константной ссылке в функцию, или, как вот тут, добавлением const к this контрактом метода. Итп. Когда ты передаёшь обычный объект по константной ссылке или указателю, ты как раз получаешь вон то самое константное, которое не совсем константное. Однако если объект был создан уже константным, то в этом случае const_cast<>, снимающий с него константность, по Стандарту (точнее, не конкретно const_cast<>, а последующая модификация объекта) приводит к неопределённому поведению, откуда следует всё остальное нехорошее. Потому я и спросил, поможет ли тебе создание изначально константных объектов вместо искусственно навешанных на них ярлыков const. Прикол в том, что автор класса реально не знает, какой this ему пришёл в метод, константный искусственно или от рождения. Поэтому const_cast<> внутри const-методов – это линейкой по рукам и переквалификация в инженера-программиста без категории, кроме как автор гарантированно смог избежать UB. Совсем другое дело, если некие поля, типа тех же счётчиков в shared_ptr<>, не являются частью состояния объектов. Или как я люблю делать CRITICAL_SECTION в качестве полей объектов. В этом случае такие поля выносятся за пределы контрактов константности посредством mutable, и мало того, что автору класса уже по барабану, каким именно образом константен объект, так и обеспечение возможности модификации этих полей ложится на плечи компилятора. Ну ещё и и линкера в ряде случаев. Добавлено Опять же можно надавить на линкер и заставить его-таки сделать то, что он по-хорошему в упор делать отказывается. Но тогда модификация mutable-полей, вызывающая в итоге UB, не должна ИМХО никого удивлять, разве нет? |
| Автор: DarkEld3r 12.11.15, 15:49 |
| Цитата MyNameIsIgor @ По моему, это не сильно отличается, скажем, от гарантий в плане того, что функция openFile может делать совсем другое.У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи? Кстати, D вообще никак не позволяет нарушить иммутабельность? Даже через всякие хаки? |
| Автор: MyNameIsIgor 12.11.15, 15:52 |
| Цитата DarkEld3r @ По моему, это не сильно отличается, скажем, от гарантий в плане того, что функция openFile может делать совсем другое. Но это не означает, что мне нужна эта гарантия через побитовую неизменяемость. |
| Автор: DarkEld3r 12.11.15, 16:00 |
| Цитата MyNameIsIgor @ Возможно, но аргументация через то, что объект окажется в памяти с защитой от записи и всё упадёт - так себе. Ведь компилятор вполне может (и должен) реагировать на ситуации когда мы явно указываем (mutable), что нечто будет меняться. Но это не означает, что мне нужна эта гарантия через побитовую неизменяемость. |
| Автор: MyNameIsIgor 12.11.15, 16:16 |
| Цитата DarkEld3r @ Цитата MyNameIsIgor @ Возможно, но аргументация через то, что объект окажется в памяти с защитой от записи и всё упадёт - так себе. Ведь компилятор вполне может (и должен) реагировать на ситуации когда мы явно указываем (mutable), что нечто будет меняться. Но это не означает, что мне нужна эта гарантия через побитовую неизменяемость. Если мы допускаем mutable, то мы опять приходим к "чем это отличается от openFile".Дилемма ясна - либо такой вот кастрат, либо развитие системы типов для возможности через неё точнее выражать семантику кода. |
| Автор: applegame 12.11.15, 16:25 |
| Цитата DarkEld3r @ Конечно можно, как в плюсах - cast'ом, но если поставить @safe, то нельзя, но если сильно захотеть и поставить @trusted, то можно. D - такой D. Кстати, D вообще никак не позволяет нарушить иммутабельность? Даже через всякие хаки? ![]() Имутабельность в D скорее защита от случайной ошибки и самодокументироемости, чем реальная защита от Васи. Также как и pure. |
| Автор: korvin 12.11.15, 20:54 |
| Цитата applegame @ "Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет. Счётчик ссылок не внутренне состояние объекта, и shared_ptr --- не сам (иммутабельный) объект. Счётчик придётся изменять потокобезопасным способом, но операции над самим объектом не требуют синхронизации, в чём проблема? |
| Автор: applegame 12.11.15, 21:43 |
| Цитата korvin @ Это уже обсуждалось выше, не хочу повторять. И да, проблем нет. Счётчик ссылок не внутренне состояние объекта, и shared_ptr --- не сам (иммутабельный) объект. Счётчик придётся изменять потокобезопасным способом, но операции над самим объектом не требуют синхронизации, в чём проблема? |
| Автор: D_KEY 13.11.15, 09:54 |
| applegame, я вот тебе не до конца понимаю. Мешает отсутствие GC иммутабельности и работе с иммутабельными данными из разных потоков или нет? |
| Автор: applegame 13.11.15, 11:39 |
| Цитата D_KEY @ Да, мешает в некоторой степени.applegame, я вот тебе не до конца понимаю. Мешает отсутствие GC иммутабельности и работе с иммутабельными данными из разных потоков или нет? Проблема во времени жизни иммутабельных данных. В случае наличия GC собственником является GC, который и уничтожает эти данные, когда доступ к ним из кода теряется. В случае отсутствия GC приходится применять замены вроде shared_ptr, который сводит преимущества иммутабельности, а именно отсутствие необходимости в синхронизации, на нет. Кроме того shared_ptr сам по себе - еще то говнецо, хуже него только голый указатель. shared_ptr нужно избегать всеми силами и заменять везде, где только возможо на unique_ptr. Что в вышеупомянутом случае невозможно. Чем он так говнист? Это то, что я вспомнил из личного опыта использования boost::asio + shared_ptr. 1. shared_ptr не умеет обрабатывать циклические ссылки, а значит их обработка ложится на плечи программиста - weak_ptr. То есть даже применив shared_ptr все равно нужно контролировать время жизни объекта. 2. Так как shared_ptr не является частью языка, то при использовании сторонних библиотек не умеющих с ним работать, приходится вытаскивать из shared_ptr непосредственно сам объект, что небезопасно. 3. Сам shared_ptr нифига не потокобезопасен. Опасно обращаться из разных потоков к одному и тому же объекту shared_ptr без синхронизации. 4. Использование указателя на объект завернутого в shared_ptr становится небезопасным везде, в том числе внутри функций-мемберов этого объекта: Никому и нокогда нельзя отдавать голый this, даже если вам кажется, что объект должен жить к моменту использования этого указателя. Лучше перекреститесь и Плохо: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Карашо:struct Foo { int a; void foo() { bar([&]{ // опасносте!!! к моменту вызова лямбды объект может быть уже похерен cout << a; }); } }; <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> struct Foo : enable_shared_from_this<Foo> { int a; void foo() { auto self = shared_from_this(); bar([=]{ cout << self->a; }); } }; |
| Автор: D_KEY 13.11.15, 12:33 |
| Цитата applegame @ В случае отсутствия GC приходится применять замены вроде shared_ptr, который сводит преимущества иммутабельности, а именно отсутствие необходимости в синхронизации, на нет. Вот именно это я и не понимаю... Каким образом? Цитата shared_ptr нужно избегать всеми силами и заменять везде, где только возможо на unique_ptr. Скорее не нужно использовать shared_ptr там, где можно обойтись unique_ptr. Цитата Что в вышеупомянутом случае невозможно. Ну это вопрос спорный. Если организовывать пайпы между тредами, т.е. один объект в один момент времени обрабатывает только какой-то один воркер, то передачи владения вполне достаточно. Кроме того, этот способ, как правило, еще и наиболее эффективен в плане организации многопоточной обработки. Цитата shared_ptr не умеет обрабатывать циклические ссылки, а значит их обработка ложится на плечи программиста - weak_ptr. То есть даже применив shared_ptr все равно нужно контролировать время жизни объекта. Ну так если ты отказался от GC, естественно, нужно Цитата Так как shared_ptr не является частью языка, то при использовании сторонних библиотек не умеющих с ним работать, приходится вытаскивать из shared_ptr непосредственно сам объект, что небезопасно. Что в этом такого небезопасного? Цитата Сам shared_ptr нифига не потокобезопасен. Опасно обращаться из разных потоков к одному и тому же объекту shared_ptr без синхронизации. Ну для него есть атомики в C++. Хотя по мне так из разных потоков его дергать и не нужно. Цитата Использование указателя на объект завернутого в shared_ptr становится небезопасным везде, в том числе внутри функций-мемберов этого объекта: Никому и нокогда нельзя отдавать голый this, даже если вам кажется, что объект должен жить к моменту использования этого указателя. Лучше перекреститесь и Это все тот же вопрос о владении и контроле времени жизни. Да, об этом нужно думать. Только я так и не понял, при чем тут иммутабельность. Добавлено applegame, а если в C++ использовать boehm, то насколько это сильно страдабельнее, чем в D? |
| Автор: Qraizer 13.11.15, 12:54 |
| Автор: MyNameIsIgor 13.11.15, 13:07 |
| Потокобезопасен подсчёт ссылок. Сам объект shared_ptr таких гарантий не даёт, да они и не нужны. |
| Автор: applegame 13.11.15, 13:41 |
| Что именно ты не понимаешь? Указатель на иммутабельный объект можно просто передать, а при использовании shared_ptr будут атомики с барьерами памяти. Я уже писал об этом. К иммутабельности относился только первый абзац моего ответа. Остальное уже относится скорее к GC vs shared_ptr. Цитата D_KEY @ Если честно, для меня главные преимущества D перед C++: читабельные и мощные шаблоны, UFCS, полноценное CTFE, рефлексия может еще какие-нибудь мелочи забыл. GC просто приятная плюшка без которой можно жить, а местами очень хорошо жить.applegame, а если в C++ использовать boehm, то насколько это сильно страдабельнее, чем в D? Говорят D1 был таким, а потом пришел Александреску и все испортил ![]() Ну а что есть в C++ для каруселей? Да и все тобой сказанное известно. Все подводные камни shared_ptr хорошо изучены, описаны и придуманы методы их обхода. Но от этого они не перестают быть подводными камнями. Само наличие подобных комней - это минус. |
| Автор: D_KEY 13.11.15, 13:47 |
| Цитата applegame @ Указатель на иммутабельный объект можно просто передать, а при использовании shared_ptr будут атомики с барьерами памяти. Я уже писал об этом. Ну и что? Один раз при передачи в тред ты скопируешь shared_ptr. Я уверен, что для большинства задач это будет абсолютно незаметно. Цитата К иммутабельности относился только первый абзац моего ответа. А там были аргументы? Цитата Остальное уже относится скорее к GC vs shared_ptr. Ну это неинтересно |
| Автор: applegame 13.11.15, 17:26 |
| Цитата D_KEY @ Для большинства задач вообще не нужны треды и immutable как таковые. А в реальных сложных многопоточных приложениях, треды имеют свойство постоянно обмениваться друг с другом объектами. А в моем реальном приложении они это делают постоянно. Ну и в конце-концов это просто удобнее. Ну и что? Один раз при передачи в тред ты скопируешь shared_ptr. Я уверен, что для большинства задач это будет абсолютно незаметно. |
| Автор: D_KEY 13.11.15, 17:32 |
| Цитата applegame @ А в реальных сложных многопоточных приложениях, треды имеют свойство постоянно обмениваться друг с другом объектами. В реальных многопоточных приложениях будет так, как ты сделаешь. Для обмена объектами достаточно unique_ptr и передачи владения. Добавлено Возможно. Но это выходит за рамки холивара, т.к. не является объективным критерием. |
| Автор: applegame 13.11.15, 17:52 |
| К сожалению, зачастую недостаточно. Точнее, зачастую невозможно передать владение. |
| Автор: Qraizer 13.11.15, 18:08 |
| Твоя фантазия. Ну сам посуди, какая логика владения должна быть, скажем, у двусвязного списка? |
| Автор: applegame 13.11.15, 18:55 |
GC? Которого нет в C++, хотя вполне может быть. |
| Автор: D_KEY 13.11.15, 19:11 |
| У D же C/C++'ый GC |
| Автор: applegame 13.11.15, 19:27 |
| Именно, и вроде даже был пропосал на GC. |
| Автор: D_KEY 13.11.15, 19:46 |
| Цитата applegame @ К сожалению, зачастую недостаточно. Точнее, зачастую невозможно передать владение. А ты мог бы привести какой-нибудь интересный пример? Задачку может какую. |
| Автор: korvin 13.11.15, 20:44 |
| А почему бы вместо указателя на (большие)данные не передавать указатель на функцию обработки в обратном направлении? Т.е. построить протокол взаимодействия потоков таким образом, чтобы обмен происходил исключительно маленькими порциями сообщений, которые можно тупо копировать и не париться ни над счётчиком ссылок, ни над потокобезопасностью (данные же иимутабельны в нашем обсуждении). Да, чревато callback-hell, но ведь можно сделать это нормально. |
| Автор: applegame 14.11.15, 08:07 |
| Есть один большой массив иммутабельных данных, нужно обрабатывать его части параллельно множеством потоков. Если я передаю один и тот же элемент в несколько потоков, то тут либо голые указатели, либо shared_ptr. Цитата korvin @ Ну а указатель на иммутабельные данные разве не есть исключительно малая порция сообщений, которые можно тупо копировать и не париться ни над счётчиком ссылок, ни над потокобезопасностью? Кроме того у меня только несколько постоянно работающих потоков. Для обработки порций данных запускаются отдельные потоки. Они обрабатывают свой кусок и завершаются. Так как я использую D + vibe.d, то вместо потоков я применяю сущности очень похожие на goroutines.А почему бы вместо указателя на (большие)данные не передавать указатель на функцию обработки в обратном направлении? Т.е. построить протокол взаимодействия потоков таким образом, чтобы обмен происходил исключительно маленькими порциями сообщений, которые можно тупо копировать и не париться ни над счётчиком ссылок, ни над потокобезопасностью (данные же иимутабельны в нашем обсуждении). Первая версия была написана на Ruby + Celluloid, но из-за кривой архитектуры надо было все это переписать. От Ruby я отказался из-за динамической типизации. |
| Автор: D_KEY 14.11.15, 08:55 |
| Цитата applegame @ нужно обрабатывать его части параллельно множеством потоков. Если я передаю один и тот же элемент в несколько потоков А зачем ты передаешь один и тот же элемент в разные потоки? Цитата то тут либо голые указатели, либо shared_ptr. Вообще, в этом примере скорее всего есть тот, кто собирает результат обработчиков и/или ждет их завершения. Вот он и является владельцем. Т.е. сначала владельцем является тот, кто инициирует обработку, а потом он передает владение тому, кто эту обработку ожидает/объединяет результаты и пр. |
| Автор: applegame 14.11.15, 09:14 |
| Ну а как иначе, если у меня есть скажем сто внешних наблюдателей, которые через RPC-интерфейс желают в любой момент времени прочитать состояние каких-то элементов массива? Цитата D_KEY @ Владельцем является по сути массив данных. У никому передать владение он не может. Нет, unique_ptr тут явно не подходит. Вообще, в этом примере скорее всего есть тот, кто собирает результат обработчиков и/или ждет их завершения. Вот он и является владельцем. Т.е. сначала владельцем является тот, кто инициирует обработку, а потом он передает владение тому, кто эту обработку ожидает/объединяет результаты и пр. |
| Автор: D_KEY 14.11.15, 09:25 |
| Цитата applegame @ Ну а как иначе, если у меня есть скажем сто внешних наблюдателей, которые через RPC-интерфейс желают в любой момент времени прочитать состояние каких-то элементов массива? Но в таком случае и GC не должен собрать этот массив, ведь в любой момент кто-то может запросить его по RPC. |
| Автор: applegame 14.11.15, 10:49 |
| Цитата D_KEY @ Сам массив нет, а вот элементы да (точнее не сами элементы, а объекты на которые эти элементы ссылаются).Но в таком случае и GC не должен собрать этот массив, ведь в любой момент кто-то может запросить его по RPC. Массив меняется: какие-то элементы удаляются, новые добавляются. Скажем отдал я несколько элементов в поток обрабатывающий RPC-запрос. Пока запрос обрабатывается эти элементы были удалены из массива. Никаких сбоев не будет. Как только RPC-поток отработает ставшие ненужными элементы будут удалены GC. |
| Автор: D_KEY 14.11.15, 11:03 |
| Цитата applegame @ Сам массив нет, а вот элементы да (точнее не сами элементы, а объекты на которые эти элементы ссылаются). А я подумал, что данные прямо в массиве лежат. Ок. Цитата Массив меняется: какие-то элементы удаляются, новые добавляются. Кем? Цитата Скажем отдал я несколько элементов в поток обрабатывающий RPC-запрос. Пока запрос обрабатывается эти элементы были удалены из массива. Никаких сбоев не будет. Ну shared_ptr вполне справится Или ты думаешь, что затраты на копирование shared_ptr будут существенными? |
| Автор: applegame 14.11.15, 11:57 |
| Потоками-обработчиками. Операции чтения/записи в массив приходится синхронизировать мьютексом. Но они достаточно дешевые, так как копируются не сами объекты а только ссылки на них. И массив на самом деле не массив в смысле непрерывной области памяти. Там набор хэш-таблиц. Цитата D_KEY @ Зависит от нагрузки. Лично я в своем проекте ориентировался не на существенность оверхеда shared_ptr, даже если бы прибавилось скажем 10% я бы не переживал особо. Для меня было гораздо важнее удобство использования и безопасность. Хоть ты и сказал, что удобство - это субъективный параметр, но в данном случае он вполне объективный. Простое при прочих равных объективно удобнее сложного. Ну shared_ptr вполне справится Или ты думаешь, что затраты на копирование shared_ptr будут существенными? |
| Автор: D_KEY 14.11.15, 12:43 |
| Но при этом ты беспокоишься о копировании shared_ptr Цитата Для меня было гораздо важнее удобство использования и безопасность. Безопасность чего? Цитата Простое при прочих равных объективно удобнее сложного. Ты так говоришь, как будто "простое" и "сложное" - это объективные вещи Я вот не помню, чтобы shared_ptr мне когда-либо казался сложным. GC сам по себе гораздо сложнее, как и возможные случаи утечек при его использовании. |
| Автор: Qraizer 14.11.15, 15:00 |
| Мне кажется, applegame, ты смешал иммутабельность данных, подлежащих обработке, с иммутабельностью контейнера, их содержащего. |
| Автор: korvin 14.11.15, 20:13 |
| Цитата applegame @ Ну а указатель на иммутабельные данные разве не есть исключительно малая порция сообщений, которые можно тупо копировать и не париться ни над счётчиком ссылок, ни над потокобезопасностью? Нет, указатель может стать невалидным, если поток-владелец вызвал деструктор объекта, пока поток, получивший от него указатель на данные, ещё не завершился. Впрочем, с передачей функции может возникнуть та же фигня, если она создаёт отдельный поток. В общем, поток-владелец не должен возвращать "сырой" объект-срез, имеющий указатель на исходный массив, а лишь предоставлять небольшой, копируемый кусок по запросу. 1) При этом, поток-владелец, например, создаёт канал для взаимодействия с потребителем (передачи ему копируемого элемента массива) и, храня ссылку на канал, уведомляет его о своём уничтожении в своём деструкторе. 2) Владельцем же канала является поток-потребитель, который автоматически уничтожит канал при своей смерти. Канал, в свою очередь, в деструкторе, уведомляет поток-владелец, если тот не умер сам, (о чём канал знает из предыдущего пункта), который его (канал) создал, чтобы тот убрал его из списка живых каналов. При чём, уже сам канал может отдавать потребителю сырой указатель на объект, скопированный в его буфер, ведь канал (и соответственно этот объект) будут жить не больше, чем поток-потребитель. Ну, я не очень знаком с C++/потоками и всем таким прочем, поэтому, возможно, фигню написал, и, наверняка, тут есть проблемы, но как бы вот. Копирование только по мере необходимости и проблем с памятью, вроде, нет. BTW, на сколько я читал, в Erlang'е всё тупо копируется, например. Добавлено Вообще, развивая мысль: передавай между потоками не указатели на сами объекты, а unique_ptr на сообщения. Ведь отправителю сообщение нужно только до момента отправки, а получателю только с момента получения, т.е. в каждый промежуток времени у сообщения только один владелец, соответственно никакие shared_ptr и подсчёт ссылок не нужны совсем. Ты можешь спросить: это что мне, создавать кучу объектов-сообщений? Ну так с иммутабельными объектами тебе _придётся_ создавать кучу объектов в любом случае. Кроме того, если ты вдруг захочешь изменить интерфейс объекта-ресурса, поток-потребитель может этого не понять, а при использовании объектов-сообщений, их, скорее всего придётся менять меньше, т.к. сообщения во многих случаях смогут инкапсулировать работу с новым интерфейсом, не затрагивая потребителей. Плюс, сообщения будет проще сериализовать и разделить потребителей и владельца по разным процессорам/машинам. |
| Автор: applegame 15.11.15, 08:03 |
Во-первых на одну синхронизацию массива приходится сотня копирований shared_ptr. Во-вторых я тебе уже объяснял, о чем я на самом деле беспокоюсь. Сочинять-то зачем, тролль несчастный. ![]() Ну что ты такой бестолковый? Очевидно же чего - безопасность космических полетов. Цитата D_KEY @ Я так говорю, потому что сущность shared_ptr<T> объективно сложнее сущности T*. И причем здесь сложность GC? И о каких возможных случаях утечек ты говоришь?Ты так говоришь, как будто "простое" и "сложное" - это объективные вещи ![]() Я вот не помню, чтобы shared_ptr мне когда-либо казался сложным. GC сам по себе гораздо сложнее, как и возможные случаи утечек при его использовании. Цитата Qraizer @ Где именно?Мне кажется, applegame, ты смешал иммутабельность данных, подлежащих обработке, с иммутабельностью контейнера, их содержащего. Цитата korvin @ Такого не произойдет если есть GC, потока-владельца не существует. объектами владеет GC, который уничтожит их, как только перестанут существовать указатели на объекты во всех потоках приложения. Все потоки использующие объект отработали, этот же объект удален из массива - GC его удаляет.Весьма похоже на shared_ptr, только без всякого shared_ptr.Нет, указатель может стать невалидным, если поток-владелец вызвал деструктор объекта, пока поток, получивший от него указатель на данные, ещё не завершился. Цитата korvin @ Это ортогонально обсуждаемому вопросу. Я и так применяю сообщения там где это имеет смысл. Речь идет о совместном доступе нескольких потоков к одним и тем же данным. Вообще, развивая мысль: передавай между потоками не указатели на сами объекты, а unique_ptr на сообщения. Ведь отправителю сообщение нужно только до момента отправки, а получателю только с момента получения, т.е. в каждый промежуток времени у сообщения только один владелец, соответственно никакие shared_ptr и подсчёт ссылок не нужны совсем. |
| Автор: D_KEY 15.11.15, 09:44 |
| И вот снова появились новые условия в задаче Цитата Ну что ты такой бестолковый? Очевидно же чего - безопасность космических полетов. А если серьезно? У тебя "безопасность" какое-то магическое слово. Цитата Я так говорю, потому что сущность shared_ptr<T> объективно сложнее сущности T*. Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr. Цитата И причем здесь сложность GC? И о каких возможных случаях утечек ты говоришь? Все те, для которых предназначены SoftReference и WeakReference в той же Java. Даже с GC ты не можешь просто забить на работу с памятью и анализ времени жизни объектов. Пусть и в более редких случаях, но зато менее явных. Цитата Я и так применяю сообщения там где это имеет смысл. Речь идет о совместном доступе нескольких потоков к одним и тем же данным. Не знаю, по мне так ты хочешь странного. |
| Автор: applegame 15.11.15, 10:32 |
| Они не новые: Цитата applegame @ Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов. Разговор с тобой стал неприятным для меня. Ты как обычно скатился в жЫрноту: начал "забывать", то что говорилось раньше и придумывать то, чего не говорилось, делать вид, что не понимаешь о чем речь, спрашивать значение общеизвестных терминов, требовать формализовать неформализуемое, выводить диалог на обсуждение малозначительных сущностей и так далее. Я не хочу по-кругу повторять одно и тоже. Посему предлагаю поменяться ролями. ![]() Цитата D_KEY @ Что ты имеешь в виду? Почему это она сложнее? Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr. ![]() Цитата D_KEY @ А для чего предназначены в Java SoftReference и WeakReference? И ты так говоришь, как будто "явность" - объективный критерий. Все те, для которых предназначены SoftReference и WeakReference в той же Java. Даже с GC ты не можешь просто забить на работу с памятью и анализ времени жизни объектов. Пусть и в более редких случаях, но зато менее явных. ![]() А по мне ты просто не сталкивался со сколь-нибудь сложными многопоточными приложениями. |
| Автор: D_KEY 15.11.15, 10:50 |
| И где тут сказано, что лочишь мьютексом ты сразу для работы со многими элементами? Цитата Цитата D_KEY @ Что ты имеешь в виду? Почему это она сложнее? Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr. ![]() Я имею в виду, что shared_ptr - это подсчет ссылок на объект, его работа детерминирована и прозрачна. GC бывают очень разные, с разными стратегиями обхода, распределения памяти, работы с поколениями(и обработки ссылок между поколениями), гарантий времени остановки и пр. и пр. Цитата А для чего предназначены в Java SoftReference и WeakReference? Для того, чтобы с разной степенью свободы позволять GC удалять те объекты, на которые мы еще имеем ссылки. Цитата И ты так говоришь, как будто "явность" - объективный критерий. ![]() В случае ручного управления памятью утечки связаны с ошибками программиста, есть специальные тулзы, которые ищут утечки и пр. В случае RC есть детекторы циклов, которые покажут наличие циклических ссылок. Случаи "случайных" ссылок тяжелее выявлять и автоматических инструментов я не видел. Если есть - расскажи Цитата А по мне ты просто не сталкивался со сколь-нибудь сложными многопоточными приложениями. Добавлено И да, все хочу спросить, ты профайлером в том или ином виде пользуешься или на глаз оцениваешь, что медленно? |
| Автор: applegame 15.11.15, 11:31 |
| Цитата D_KEY @ Какое дело программисту до всей этой внутренней кухни? Убрал последнюю ссылку и забыл про объект и нет сюрпризов с неожиданным обращением к уже удаленному объекту. То же самое можно было бы сказать и о shared_ptr, если бы не несколько подводных камней и ограничений использования.Я имею в виду, что shared_ptr - это подсчет ссылок на объект, его работа детерминирована и прозрачна. GC бывают очень разные, с разными стратегиями обхода, распределения памяти, работы с поколениями(и обработки ссылок между поколениями), гарантий времени остановки и пр. и пр. Цитата D_KEY @ Для того, чтобы с разной степенью свободы позволять GC удалять те объекты, на которые мы еще имеем ссылки. Цитата D_KEY @ А случаи "случайных" ссылок можно подумать не связаны с ошибками программиста В случае ручного управления памятью утечки связаны с ошибками программиста, есть специальные тулзы, которые ищут утечки и пр. В случае RC есть детекторы циклов, которые покажут наличие циклических ссылок. Случаи "случайных" ссылок тяжелее выявлять и автоматических инструментов я не видел. Если есть - расскажи , Да и shared_ptr могут привести к ним с тем же успехом. А заявить, что WeakReference в Java предназначены для борьбы с утечками, это примерно как сказать, что delete в C++ предназначен для борьбы с утечками ![]() Инструмент для обнаружения причины таких "утечек" не нужен. Потому что твои пресловутые "случайные" зависшие ссылки - явление весьма специфичное и точки их возникновения легко находимы без каких-либо инструментов, кроме собственной головы. Как правило, это кеши, которые забыли периодически очищать. Тут я тебе без всякого valgrind найду утечку. Цитата D_KEY @ Да, давай оставим. Но так как ты первый перешел на личности, то последнее слово за мной: ты - некомпетентен в этой области. ![]() По мне так все наоборот... Вернее, ты не умеешь такие приложения проектировать. Но давай оставим в покое личности и попытаемся поговорить конструктивно. Вот теперь, да, не будем о личностях. |
| Автор: D_KEY 15.11.15, 11:59 |
| Нет ты Добавлено И ты еще рассуждаешь о компетентности? Добавлено Это не ошибки. Это доверие сборщику. Но вернемся к конструктивному обсуждению. Мне так и неясна связь иммутабельности с наличием/отсутсвием GC. По-моему, все что ты говоришь справедливо и для мутабельных данных, разве нет? Твой ответ про профайлинг так же интересен. |
| Автор: Qraizer 15.11.15, 12:11 |
| Цитата applegame @ Вот тут я могу присоединиться к D_KEY-ю. Разве не ты начал говорить о неком контейнере для ссылок на иммутабельные объекты, который то и дело, что меняет своё состояние? Объясни мне, плз, как можно рассуждать о тем или иным способом поумневшим ссылках на иммутабельные объекты, напрочь игнорируя содержащий их контейнер? При том что если бы контейнер был константным, мы могли бы обойтись тупо сырыми поинтерами и не париться. Пока я не вижу, зачем бы вообще могло понадобиться отдаваемые объекты оборачивать в смарты. Цитата Qraizer @ Где именно?Мне кажется, applegame, ты смешал иммутабельность данных, подлежащих обработке, с иммутабельностью контейнера, их содержащего. Добавлено Огласи уж полные условия, что ли. Без последующих отказов и дополнений. |
| Автор: applegame 15.11.15, 17:02 |
| Цитата Qraizer @ Ссылки из этого контейнера рассылаются другим потокам. Не весь контейнер, а его различные части.Объясни мне, плз, как можно рассуждать о тем или иным способом поумневшим ссылках на иммутабельные объекты, напрочь игнорируя содержащий их контейнер? И ты еще рассуждаешь о компетентности? Сборщик тут не причем. Такие же "утечки" можно получить и с shared_ptr и с голыми указателеми.Но давайте вернемся к Цитата D_KEY @ к конструктивному обсуждению. Мне так и неясна связь иммутабельности с наличием/отсутсвием GC. По-моему, все что ты говоришь справедливо и для мутабельных данных, разве нет? В общем случае ты видимо прав. Прямой связи нет. Скаэем так, сочетание иммутабельности и GC дает нам дополнительные гарантии. Если функция в D получает иммутабельный объект, то у нас есть гарантия не только в том, что никто и никогда не изменит этого объекта, но и то что никто и никогда не удалит этот объект пока мы его используем. То есть эта функция получается более генерализованной. Совершенно все равно откуда и в каком окружении она будет вызвана. То есть immutable в GC-окружении получается как бы более полным что-ли. К сожалению у меня не получается формализовать свою мысль более точно. Как в C++ определить был ли объект изначально константным или нет? Насколько я знаю никак. Фактически immutable в D обозначает изначальную константность. При этом immutable неявно может быть скастовано в const, но не наоборот. Теперь вопрос: нужен ли immutable в C++? Добавлено Накопал интересную статью в википедии об иммутабельности: Persistent data structures. Эти структуры иммутабельны и их реализация требует наличия GC. И как я понимаю именно они используются в чисто функциональных языках вроде Хаскеля. |
| Автор: D_KEY 15.11.15, 18:19 |
| Цитата applegame @ Ссылки из этого контейнера рассылаются другим потокам. Не весь контейнер, а его различные части. Т.е. мы имеем некоторый контейнер с данными, в который какие-то потоки кладут объекты, какие-то удаляют, а какие-то забирают элементы для того, чтобы их прочесть. Контейнер лочится мьютексом, а потоки работают сразу с группой объектов(иначе не имело бы смысл беспокоиться о копировании shared_ptr на фоне лока). Так? Цитата Такие же "утечки" можно получить и с shared_ptr и с голыми указателеми. В теории да, на практике вероятность ниже, поскольку и пользователи RC и пользователи ручного управления памятью сами обдумывают время жизни объектов, стратегию владения и пр. Цитата В общем случае ты видимо прав. Ок. А холивар GC vs не-GC не слишком интересная тема. ИМХО. Цитата Если функция в D получает иммутабельный объект, то у нас есть гарантия не только в том, что никто и никогда не изменит этого объекта, но и то что никто и никогда не удалит этот объект пока мы его используем. Гарантия того, что никто и никогда не удалит этот объект у нас есть в любом случае и никак с иммутабельностью не связана Цитата Эти структуры иммутабельны и их реализация требует наличия GC. Скажем так, они гораздо легче реализуются при наличии GC. |
| Автор: Qraizer 15.11.15, 19:46 |
| Цитата applegame @ И слава богу, что нет. Иначе от const не было бы никакого проку вообще, как сейчас от register. Или от C99-шного restrict. Зато есть (в какой-то мере) прямая противоположность: const volatile. И это ИМХО идеологически правильнее immutable. Как в C++ определить был ли объект изначально константным или нет? Насколько я знаю никак. Фактически immutable в D обозначает изначальную константность. При этом immutable неявно может быть скастовано в const, но не наоборот. Теперь вопрос: нужен ли immutable в C++? |
| Автор: applegame 15.11.15, 20:24 |
| Цитата D_KEY @ Да. Похоже на текущую архитектуру, сильно правда упрощенно, но примерно так. Т.е. мы имеем некоторый контейнер с данными, в который какие-то потоки кладут объекты, какие-то удаляют, а какие-то забирают элементы для того, чтобы их прочесть. Контейнер лочится мьютексом, а потоки работают сразу с группой объектов(иначе не имело бы смысл беспокоиться о копировании shared_ptr на фоне лока). Так? |
| Автор: korvin 16.11.15, 07:05 |
| Цитата applegame @ Такого не произойдет если есть GC, потока-владельца не существует. объектами владеет GC, который уничтожит их, как только перестанут существовать указатели на объекты во всех потоках приложения. Все потоки использующие объект отработали, этот же объект удален из массива - GC его удаляет.Весьма похоже на shared_ptr, только без всякого shared_ptr. Спасибо, Кэп. А я-то думал, GC в лиспах, хаскеллах, джавах и прочих сишарпах --- это что-то другое. Цитата applegame @ Это ортогонально обсуждаемому вопросу. Я и так применяю сообщения там где это имеет смысл. Речь идет о совместном доступе нескольких потоков к одним и тем же данным. Всё просто: совместный доступ не нужен. Каждым ресурсом владеет только один поток. |
| Автор: applegame 16.11.15, 11:07 |
| Цитата korvin @ Наверное думал, раз написал:Спасибо, Кэп. А я-то думал, GC в лиспах, хаскеллах, джавах и прочих сишарпах --- это что-то другое. Цитата korvin @ Нет, указатель может стать невалидным, если поток-владелец вызвал деструктор объекта, пока поток, получивший от него указатель на данные, ещё не завершился. Или решил, что речь идет о C++. Но тогда стоило бы написать, что ты говорил о другом языке, вместо благодарностей капитанам, нет? А какая связть между владением ресурсом и совместным доступом к ресурсу? |
| Автор: D_KEY 16.11.15, 12:22 |
| Цитата applegame @ Цитата D_KEY @ Да. Похоже на текущую архитектуру, сильно правда упрощенно, но примерно так.Т.е. мы имеем некоторый контейнер с данными, в который какие-то потоки кладут объекты, какие-то удаляют, а какие-то забирают элементы для того, чтобы их прочесть. Контейнер лочится мьютексом, а потоки работают сразу с группой объектов(иначе не имело бы смысл беспокоиться о копировании shared_ptr на фоне лока). Так? Можешь придумать похожую на твою, но более простую задачку, чтобы можно было поэкспериментировать? |
| Автор: applegame 16.11.15, 12:31 |
| Цитата D_KEY @ Поэкспериментировать на какую тему? Можешь придумать похожую на твою, но более простую задачку, чтобы можно было поэкспериментировать? |
| Автор: D_KEY 16.11.15, 12:38 |
| Цитата applegame @ Цитата D_KEY @ Поэкспериментировать на какую тему?Можешь придумать похожую на твою, но более простую задачку, чтобы можно было поэкспериментировать? Ну на тему иммутабельности, GC, RC, разделяемых ресурсов, очередей/каналов и пр. Там видно будет. |
| Автор: applegame 16.11.15, 12:41 |
| Цитата D_KEY @ Я не знаю. Я пытался как-то описать задачу более-менее полно, но все равно получается достаточно сложно. Ну на тему иммутабельности, GC, RC, разделяемых ресурсов, очередей/каналов и пр. Там видно будет. Добавлено Кроме того нас ограничивает внешнее 3rd party API. Если бы не оно мы могли бы вообще отказаться от совместного доступа к объектам, передавая только их уникальные идентификаторы. |
| Автор: D_KEY 16.11.15, 12:50 |
| Цитата applegame @ Цитата D_KEY @ Я не знаю. Я пытался как-то описать задачу более-менее полно, но все равно получается достаточно сложно.Ну на тему иммутабельности, GC, RC, разделяемых ресурсов, очередей/каналов и пр. Там видно будет. Да нужно что-то более конкретное. Т.е. обозначить, что за контейнер, как данные туда попадают, как удаляются, кто, как и когда их читает и что, собственно, с этими данными делает. Что-то надо придумать. Тогда можем поиграться(в том числе и на Go вариант может появиться). |
| Автор: applegame 16.11.15, 12:54 |
| Цитата D_KEY @ А смысл? Проверить что быдет быстрее GC или RC? Придумай сам что-нибудь с передачами групп объектов и типа их обработкой Да нужно что-то более конкретное. Т.е. обозначить, что за контейнер, как данные туда попадают, как удаляются, кто, как и когда их читает и что, собственно, с этими данными делает. Что-то надо придумать. Тогда можем поиграться(в том числе и на Go вариант может появиться). Я-то свою задачу решил и решение работает хорошо и, главное, поддерживается и расширяется тоже хорошо. Могут быть проблемы с масштабированием, но я полагаю, что мы вряд ли в обозримом будущем упремся в потолок текущей архитектуры. |
| Автор: D_KEY 16.11.15, 13:02 |
| Это можно. Но нам тут нужно, чтобы "обработка" была на одних и тех же данных много раз(и параллельно эти данные могут исключить из контейнера), причем данные должны быть достаточно большими, чтобы мы обеспокоились стоимостью копирования. Вот пока не придумывается ничего. |
| Автор: MyNameIsIgor 16.11.15, 13:06 |
| Цитата applegame @ я полагаю, что мы вряд ли в обозримом будущем упремся в потолок текущей архитектуры Так а какова сама задача, для которой была придумана такая архитектура? |
| Автор: applegame 16.11.15, 13:09 |
| То что мне приходит в голову не требует копирования или совместного доступа, достаточно обмениваться уникальными идентификаторами, что в общем-то не эффективней обмена сырыми указателями, но зато не требует GC. Разве что прописать в условиях задачи необходимость полного доступа к объекту в потоках. Добавлено Подробности разглашать не могу, так как оно коммерческое и проприетарное. |
| Автор: MyNameIsIgor 16.11.15, 13:12 |
| Цитата applegame @ То что мне приходит в голову не требует копирования или совместного доступа, достаточно обмениваться уникальными идентификаторами Это не то же самое, ибо тогда получившие идентификатор не будут владеть данными. Со сборщиком мусора или подсчётом ссылок они ими владеют, даже если данные удалены из контейнера. Добавлено Эммм... Ну, хз, конечно... Но что тайного, например, в такой формулировке "сервис должен получать такие-то запросы (примерная вероятность, периодичность) и отдавать такие-то ответы"? |
| Автор: applegame 16.11.15, 13:15 |
| Цитата MyNameIsIgor @ Я и не говорил, что это одно и тоже. Я имел в виду, что упрощенный пример задачи пришедший мне в голову не требует владения/совместного доступа, а достаточно идентификатора. Это не то же самое, ибо тогда получившие идентификатор не будут владеть данными. Со сборщиком мусора или подсчётом ссылок они ими владеют, даже если данные удалены из контейнера. Добавлено Цитата MyNameIsIgor @ Проблема в том, что в такой трактовке это будет слабо связано с реальной задачей. То есть если мы подберем наиболее удачный алгоритм, совершенно не факт, что он будет удачным в нашем реальном проекте. Но я попробую сформулировать нечто попроще. Будет эдакий многопоточный бенчмарк, пусть даже не похожий на реальный проект. Такое устроит? Но что тайного, например, в такой формулировке "сервис должен получать такие-то запросы (примерная вероятность, периодичность) и отдавать такие-то ответы"? |
| Автор: MyNameIsIgor 16.11.15, 13:24 |
| Цитата applegame @ Проблема в том, что в такой трактовке это будет слабо связано с реальной задачей. То есть если мы подберем наиболее удачный алгоритм, совершенно не факт, что он будет удачным в нашем реальном проекте. Ну, я имел в виду, что можно отделить то, что попадает под соглашение о неразглашении (форматы данных, область применения, алгоритмы и т.д.), от чисто технических подробностей - измеряемых параметров, которым должен удовлетворять сервис. Цитата applegame @ Но я попробую сформулировать нечто попроще. Будет эдакий многопоточный бенчмарк, пусть даже не похожий на реальный проект. Такое устроит? На мой взгляд, упрощать важно хотя бы потому, что не у всех будет время и желание не на работе писать много кода чисто для эксперимента. |
| Автор: korvin 17.11.15, 21:10 |
| Цитата applegame @ Наверное думал, раз написал: Цитата korvin @ Нет, указатель может стать невалидным, если поток-владелец вызвал деструктор объекта, пока поток, получивший от него указатель на данные, ещё не завершился. Или решил, что речь идет о C++. Но тогда стоило бы написать, что ты говорил о другом языке, вместо благодарностей капитанам, нет? Мы же обсуждали указатели и владение памятью при использовании иммутабельных объектов в многопоточной среде в языках без GC. Прямая: - с GC владельцем является GC и он же освобождает память. Т.е. имея ссылку на один и тот же ресурс оба потока будут иметь её до тех пор пока оба не завершаться. - Без GC программист сам выбирает политику владения памятью и организовывает совместный доступ таким образом, чтобы не было дыр, позволяющих привести систему к некорректному состоянию. Вот тебя не устраивает smart_ptr из-за каких-то там проблем, я тебе предлагаю [не использовать smart_ptr и не шарить сам ресурс напрямую (через какие бы то ни было указатели вообще)] и не иметь этих проблем. Добавлено Давай хоть для начала определимся, что это за ресурс. |
| Автор: applegame 17.11.15, 21:33 |
| Цитата korvin @ Я полагал, что мы обсуждаем замену иммутабельным объектам в языке с GC.Мы же обсуждали указатели и владение памятью при использовании иммутабельных объектов в многопоточной среде в языках без GC. Цитата korvin @ Как ты там говорил? Спасибо, кэп. Но владение ресурсом и совместный доступ - понятия ортогональные. Совместный доступ - проблема синхронизации, владение ресурсом - проблема времени жизни ресурса.Прямая: - с GC владельцем является GC и он же освобождает память. Т.е. имея ссылку на один и тот же ресурс оба потока будут иметь её до тех пор пока оба не завершаться. - Без GC программист сам выбирает политику владения памятью и организовывает совместный доступ таким образом, чтобы не было дыр, позволяющих привести систему к некорректному состоянию. Цитата korvin @ Я такого не говрил. Я говорил что по крайней мере в моем проекте immutable + GC удобнее, чем shared_ptr и может быть эффективней. А ты как-то странно заявил, что совместный доступ не нужен, если владелец всего один. Прямо вот совсем никогда не нужен? Создал объект в одном потоке раздал указатель на него еще десятерым, подождал пока они завершаться, уничтожил объект. Вот тебе схема с одним владельцем и совместным доступом.Вот тебя не устраивает smart_ptr из-за каких-то там проблем, я тебе предлагаю [не использовать smart_ptr и не шарить сам ресурс напрямую (через какие бы то ни было указатели вообще)] и не иметь этих проблем. В любом случае я тебя понял, такой вариант не всегда удобен и эффективен, но кое-где я его применяю. |
| Автор: korvin 17.11.15, 21:50 |
| Нет, если доступ требует владения, как в случае с shared_ptr. Добавлено Цитата applegame @ Создал объект в одном потоке раздал указатель на него еще десятерым, подождал пока они завершаться, уничтожил объект. Вот тебе схема с одним владельцем и совместным доступом. Э-э... Если ты ждешь пока потоки завершатся, то зачем тебе GC, если объект прекрасно и безопасно удалится создателем? Полезность GC проявляется как раз, когда ты не ждешь, пока потоки, обрабатывающие объект, завершатся, поэтому ты не можешь сам удалить объект там, где создал. |
| Автор: D_KEY 17.11.15, 22:07 |
| Цитата applegame @ Но владение ресурсом и совместный доступ - понятия ортогональные. Совместный доступ - проблема синхронизации, владение ресурсом - проблема времени жизни ресурса. Так вот именно. Потому наличие GC упрощает для тебя вопросы владения вне зависимости от иммутабельности(которая, в том числе, позволяет тебе не беспокоится о синхронизации). Добавлено Цитата applegame @ Но я попробую сформулировать нечто попроще. Будет эдакий многопоточный бенчмарк, пусть даже не похожий на реальный проект. Такое устроит? Меня бы устроило. Не факт, что как следует похоливарим, но подумать можно. А может и поиграться с реализацией будет интересно. |
| Автор: applegame 18.11.15, 08:51 |
| Доступ никогда не требует владения (по крайней мере в D/C++). Для получения доступа к объекту внутри shared_ptr/unique_ptr не обязательно передавать владение, можно просто вытащить указатель с помощью get(). Владения, в том числе и совместного, может требовать архитектура приложения, но не доступ сам по себе. Цитата korvin @ Это был просто пример. Я так не делаю.Э-э... Если ты ждешь пока потоки завершатся, то зачем тебе GC, если объект прекрасно и безопасно удалится создателем? Полезность GC проявляется как раз, когда ты не ждешь, пока потоки, обрабатывающие объект, завершатся, поэтому ты не можешь сам удалить объект там, где создал. Цитата D_KEY @ Скорее всего никак не похоливарим. Я пытался начать писать, все равно получается портянка. Но я попробую позже. Меня бы устроило. Не факт, что как следует похоливарим, но подумать можно. А может и поиграться с реализацией будет интересно. |
| Автор: Qraizer 18.11.15, 12:11 |
| Цитата applegame @ А ещё можно вытащить символьный массив из строки std::basic_string<>::c_str(). А ещё динамический массив из вектора &std::vector<>::front(). Вопрос только, зачем. Ответ известен: для передачи легаси-коду. Совет: для иных целей использовать не следует. Для получения доступа к объекту внутри shared_ptr/unique_ptr не обязательно передавать владение, можно просто вытащить указатель с помощью get(). |
| Автор: applegame 18.11.15, 14:11 |
| Цитата Qraizer @ Это не отменяет того факта, что доступ к объекту не требует владения этим объектом. Кроме того почему обязательно легаси? Любому коду не работающему с shared_ptr/unique_ptr, например разнообразного рода API операционых систем или библиотек. А ещё можно вытащить символьный массив из строки std::basic_string<>::c_str(). А ещё динамический массив из вектора &std::vector<>::front(). Вопрос только, зачем. Ответ известен: для передачи легаси-коду. Совет: для иных целей использовать не следует. |
| Автор: Qraizer 18.11.15, 14:33 |
| Это тоже легаси. |
| Автор: applegame 18.11.15, 18:23 |
Все, что не умные плюсовые указатели - легаси |
| Автор: Qraizer 18.11.15, 19:55 |
| И не только. |
| Автор: korvin 18.11.15, 20:39 |
| Цитата Qraizer @ А ещё можно вытащить символьный массив из строки std::basic_string<>::c_str(). А ещё динамический массив из вектора &std::vector<>::front(). О, кстати, а ещё вот что недавно узнал: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> public static void toUpperCase(String orig) { try { Field stringValue = String.class.getDeclaredField("value"); stringValue.setAccessible(true); stringValue.set(orig, orig.toUpperCase().toCharArray()); } catch (Exception ex){ } } Иммутабельность? Не, не слышал. |
| Автор: applegame 26.11.15, 18:29 |
| По поводу возможности писать на D без GC. Человек, написал полностью на D кроссплатформенный VST-плагин для наложения на голос эффектов в реальном времени с околонулевой латентностью. http://forum.dlang.org/thread/hbmbztydvyfw...forum.dlang.org |
| Автор: korvin 27.11.15, 20:22 |
| Ну вот, наконец-то нормальная success-story. =) Больше таких и D, может-таки, завоюет популярность у масс. =) Правда, неплохо бы показать преимущества реализации этой задачи на D вместо C++. |
| Автор: applegame 27.11.15, 21:27 |
| Цитата korvin @ success-stories есть немного тут - http://wiki.dlang.org/Current_D_UseНу вот, наконец-то нормальная success-story. =) Больше таких и D, может-таки, завоюет популярность у масс. =) Да какие тут преимущества? Любит человек писать на D вот и пишет. Преимущества по большей части субъективные - просто удобнее писать. Я приводил всякие куски кода в этой теме, но в ответ всегда заявлялось, что тоже самое можно сделать и на плюсах. Ну и что, что код в два раза длиннее и "мусорнее"? "Мусорность" ведь тоже понятие субъективное. Всегда найдется, тот кому вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; кажется ничем не лучше, а то и хуже, чем вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map<unsigned short, map<char, map<string, int>>> data; |
| Автор: D_KEY 27.11.15, 21:33 |
| Цитата applegame @ Всегда найдется, тот кому вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; кажется ничем не лучше, а то и хуже, чем вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map<unsigned short, map<char, map<string, int>>> data; Мне оба варианта кажутся отстоем. Я бы затайпдефил по частям. Иначе так и неясно кто на ком стоял и зачем. |
| Автор: korvin 27.11.15, 23:03 |
| Цитата applegame @ Всегда найдется, тот кому вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; кажется ничем не лучше, а то и хуже, чем вот это <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map<unsigned short, map<char, map<string, int>>> data; Тут я соглашусь с D_KEY'ем, но по другой причине: первый вариант напоминает объявление массива, вложенность типов как-то не отображается визуально, да и вообще определение типа как будто записано в обратном порядке. Всё же map проще и привычней воспринимать в виде keyT->valT, а не valT[keyT]. Т.е., если не принимать во внимание тайпдеф, то, ИМХО, логичней и понятней было бы что-то вроде <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ushort->(char->(string->int)) data; скобки при этом могут быть не обязательны. =) или <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ushort:char:string:int data; Может, я просто привык к объявлению типа справа от идентификатора: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> var data map[uint16]map[rune]map[string]int или Pascal-style: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> var data : map Word to map Char to map String to Integer; =) |
| Автор: D_KEY 27.11.15, 23:22 |
| Мне кажутся самими приемлемыми варианты: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map[ushort, map[char, map[string, int]]] ushort->char->string->int ushort to char to string to int |
| Автор: korvin 27.11.15, 23:47 |
| Цитата D_KEY @ Мне кажутся самими приемлемыми варианты: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map[ushort, map[char, map[string, int]]] ushort->char->string->int ushort to char to string to int Тоже норм. Первый мне особенно нравится, хоть он и длинней остальных, зато наглядно показывает вложенность. И при этом достаточно обобщённый, т.е. его можно применять для любых параметрических типов, например <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> keypath = Tuple[ushort, char, string]; |
| Автор: D_KEY 28.11.15, 00:06 |
| Его проблема в том, скорее всего, придётся отказаться от оператора [](как и пришлось в scala), а это тоже неудобно. |
| Автор: MyNameIsIgor 28.11.15, 01:36 |
| Цитата D_KEY @ Его проблема в том, скорее всего, придётся отказаться от оператора [](как и пришлось в scala), а это тоже неудобно. Не вижу особой перемоги в замене <> на []. Кстати, если в скалке стали использовать функций для массивов, в плюсах можно сделать так же <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map<int (unsigned short, char, std::string)> Реализация <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> namespace detail { template<class T> struct meta_map; template<class V, class K> struct meta_map<V (K)> { using type = std::map<K, V>; }; template<class V, class K, class... Keys> struct meta_map<V (K, Keys...)> { using type = std::map<K, typename meta_map<V (Keys...)>::type>; }; } template<class T> using map = typename detail::meta_map<T>::type; |
| Автор: applegame 28.11.15, 07:40 |
| В D все прозрачно: все что слева стоит на том что справа. Ну и при желании можно сделать так: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Map!(int, string, char, ushort) data; data[a, b, c] = 10; |
| Автор: D_KEY 28.11.15, 17:51 |
| Ну на мой взгляд [] читаются легче. Это же субъективно все. Цитата Кстати, если в скалке стали использовать функций для массивов, в плюсах можно сделать так же <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map<int (unsigned short, char, std::string)> Неплохо. Но тут все будет именно map'ом. А в общем случае можно хотеть мапу на деревьях, а можно на каком-то уровне захотеть хеш. |
| Автор: MyNameIsIgor 28.11.15, 18:14 |
| Цитата D_KEY @ Но тут все будет именно map'ом. А в общем случае можно хотеть мапу на деревьях, а можно на каком-то уровне захотеть хеш. Так делов то? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> namespace detail { template<class T, template<class...> class M> struct meta_map; template<class V, template<class...> class M> struct meta_map<V (), M> { using type = V; }; template<class V, class K, class... Keys, template<class...> class M> struct meta_map<V (K, Keys...), M> { using type = M<K, typename meta_map<V (Keys...), M>::type>; }; } template<template<class...> class M, class T> using map = typename detail::meta_map<T, M>::type; map<std::unordered_map, int (unsigned short, char, std::string)> m; |
| Автор: D_KEY 28.11.15, 18:43 |
| Не, я хочу на разных уровнях разные контейнеры. Добавлено А зачем он там стоит и какая логика за этим? Тайпдефы не только сокращают объявления, они ещё и позволяют уточнять смысл. |
| Автор: MyNameIsIgor 28.11.15, 18:55 |
| Ну, сам сделаешь? |
| Автор: applegame 28.11.15, 19:03 |
| Цитата D_KEY @ Он нужен если ты этот тип используешь много раз, а городить тайпдеф ради одного объявления - маразм. А зачем он там стоит и какая логика за этим? Тайпдефы не только сокращают объявления, они ещё и позволяют уточнять смысл. |
| Автор: D_KEY 28.11.15, 21:24 |
| Цитата applegame @ Цитата D_KEY @ Он нужен если ты этот тип используешь много раз, а городить тайпдеф ради одного объявления - маразм.А зачем он там стоит и какая логика за этим? Тайпдефы не только сокращают объявления, они ещё и позволяют уточнять смысл. А вот это вот в реальном коде не маразм? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; Добавлено Цитата MyNameIsIgor @ Ну вот чтоб синтаксис нормальным был не сделаю Мне вариант с вложенными типами нравится больше. И [] нравится больше <>. Вкусовщину обсуждаем, дожили. |
| Автор: Qraizer 28.11.15, 22:27 |
| Ну, отец-основатель рассказывал, что [] тоже рассматривались, но в конечном итоге были отвергнуты из-за высокой вероятности синтаксических коллизий. Поэтому был выбран новый тип скобок <> вместо придания новой роли []. К слову, с [] возникли бы сложности со специализациями, хотя когда рассматривался вопрос о виде скобок, о специализациях ещё не думали, до них было ещё далеко. Добавлено Или это был не отец-основатель, а кто-то из EDG?.. Что-то подзабыл уже. |
| Автор: applegame 28.11.15, 22:51 |
| Цитата D_KEY @ А вот это вот в реальном коде не маразм? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; Нет, а в чем проблема? Какой-нибудь int[][] тебе тоже кажется маразмом, или int[5][5]? В D можно и так <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[5][string][] data; И тут тоже все понятно. Массив ассоциативных массивов содержащих статические массивы по пять элементов типа int каждый. |
| Автор: D_KEY 28.11.15, 23:07 |
| Цитата applegame @ Цитата D_KEY @ А вот это вот в реальном коде не маразм? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int[string][char][ushort] data; Нет, а в чем проблема? Да не, все прекрасно, начиная от великолепного и понятного названия переменной, заканчивая говорящим описанием типа. Добавлено Ну все, перехожу на D. Цитата И тут тоже все понятно. Оно может и понятно, но смотрится и читается плохо. Сишные определения тоже понятны, если правила знаешь. Цитата Массив ассоциативных массивов содержащих статические массивы по пять элементов типа int каждый. Мне это очевидным не было. Добавлено Цитата applegame @ Массив ассоциативных массивов содержащих статические массивы по пять элементов типа int каждый. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> vector[map[string, array[int, 5]]] А если совсем пофантазировать, то это можно было бы как-то так записать: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> [string->[int:5]] |
| Автор: korvin 29.11.15, 09:48 |
| Цитата D_KEY @ Его проблема в том, скорее всего, придётся отказаться от оператора [](как и пришлось в scala), а это тоже неудобно. Я почти не знаком со Scala, поэтому не могу с ходу вообразить ситуацию, когда оператор [] будет конфликтовать с использованием [] для параметризации типа. Вот в D же параметры типа задаются в () и это не конфликтует с оператором () вызова процедуры. Да и в C++ же решили проблему >>? Т.е., ИМХО, это чисто скалопроблемы. Добавлено Цитата applegame @ И тут тоже все понятно. Массив ассоциативных массивов содержащих статические массивы по пять элементов типа int каждый. А смысловая нагрузка у этого массива? Ассоциаци там чего с чем? Рандомных строк с рандомными наборами из пяти рандомных чисел? Почему пяти, а не трёх, не восьми? |
| Автор: applegame 29.11.15, 10:28 |
| Цитата D_KEY @ Ой, давай еще к шрифту и цвету придерись. название переменной ему не понравилось... Давай еще поговорим о понятности наших ников. Тип вполне говорящий, описывается очень легко: V[K].Да не, все прекрасно, начиная от великолепного и понятного названия переменной, заканчивая говорящим описанием типа. Цитата D_KEY @ В D правил особых нет. Все следует одно из другого. Если тип значения тоже ассоциативный массив, то просто подставь его описание вместо V: V[K1][K2] - или просто двумерный ассоциативный массив.Оно может и понятно, но смотрится и читается плохо. Сишные определения тоже понятны, если правила знаешь. О да, тут все читабельно, сразу видно где тут типы ключей, а где типы значений. map[A, B] - двумерный массив? Неее, это ассоциативный массив, у которого ключ - это A, а B - значение. А если мне нужен ассоциативный массив по двум ключам, это будет map[A1, A2, B]? Нее, map[A1, map[A2, B]]. А обращаться к элементам, значит нужно вот так - var[A1[A2]]? Неее - var[A1][A2]. А почему при объявлении скобки вложены, а при обращении нет? Потому что гладиолус. array[int, 5] - двумерный массив? Неее, это одномерный массив фиксированного размера 5. А как будет двумерный массив, array[int, 5, 5]? Неее, вот так - array[array[int, 5], 5]. А обращаться к его элментам, значит нужно вот так - var[2[2]]? Неее - var[2][2]. А почему при объявлении скобки вложены, а при обращении нет? Потому что гладиолус. Тут вообще все сразу понятно: массив функций с одним параметром типа string и возвращаемым значением... эм... какого-то типа. Добавлено Цитата korvin @ ИМХО, не об этом речь.А смысловая нагрузка у этого массива? Ассоциаци там чего с чем? Рандомных строк с рандомными наборами из пяти рандомных чисел? Почему пяти, а не трёх, не восьми? Если хочется сделай так: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> alias Chapter = string; alias Part = uint; alias Line = ushort; struct Words { ... } Words[Line][Part][Chapter] content; auto w = content["Main"][2][10]; |
| Автор: D_KEY 29.11.15, 11:36 |
| Цитата applegame @ Цитата D_KEY @ Ой, давай еще к шрифту и цвету придерись.Да не, все прекрасно, начиная от великолепного и понятного названия переменной, заканчивая говорящим описанием типа. Каким боком тут шрифт и цвет? Я же специально уточнил про реальный код. Тут смысловую нагрузку не несут ни тип, ни переменная. Цитата Тип вполне говорящий, описывается очень легко: V[K]. Ну мапишь ты K на V. А зачем? Цитата Если тип значения тоже ассоциативный массив, то просто подставь его описание вместо V: V[K1][K2] - или просто двумерный ассоциативный массив. Ну а мне это не нравится. Я привык, чтобы сначала был ключ, а потом значение. Так удобнее читать. Цитата О да, тут все читабельно Да. Все прямо как ты сказал: Цитата Массив ассоциативных массивов со строковым ключем содержащих статические массивы по пять элементов типа int каждый. Ну дословно же. Цитата map[A, B] - двумерный массив? С какой стати это должен быть двумерный массив? Если ты не понял, то [] тут вместо плюсовых <>. Цитата А если мне нужен ассоциативный массив по двум ключам Что это такое? Я думаю, что ты понимаешь, что у тебя ассоциативный массив с K1 и значениями в виде других ассоциативных массивов с ключем K2 и значением V. Цитата это будет map[A1, A2, B]? Нее, map[A1, map[A2, B]]. Цитата А обращаться к элементам, значит нужно вот так - var[A1[A2]]? Неее - var[A1][A2]. Скорее всего var(A1)(A2). По крайней мере в Scala пришлось сделать так. Не уверен, что это лучший вариант. Но [] для дженериков мне нравятся больше <>. Цитата А почему при объявлении скобки вложены, а при обращении нет? Потому что гладиолус. Что? А почему тут вообще должна быть какая-то связь? Есть описание типов, а есть разные операторы. Цитата Если хочется сделай так: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> alias Chapter = string; alias Part = uint; alias Line = ushort; struct Words { ... } Words[Line][Part][Chapter] content; Ну мне вот не хочется Тем более, что на самом деле все наоборот. Мы же не на арабском пишем, почему я должен читать справа налево?Цитата <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto w = content["Main"][2][10]; А вот это вполне годно. |
| Автор: D_KEY 29.11.15, 11:41 |
| В сишных объявлениях и то больше логики, там по крайней мере как пишем, так и используем. А тут все наоборот: Объявляем <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Words[Line][Part][Chapter] content А используем: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> content[chapter_n][part_n][line_n] Все логично и понятно |
| Автор: applegame 29.11.15, 16:37 |
| Цитата D_KEY @ У сей свои ребусы еще похлеще:В сишных объявлениях и то больше логики, там по крайней мере как пишем, так и используем. А тут все наоборот: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void (*foo(int, void (*bar)(int)))(int); Расшифруй навскидку, что такое foo. И насколько оно визуально соответствует декларации. |
| Автор: amk 29.11.15, 16:53 |
| Давай я попробую: Скрытый текст Функция, принимающая в качестве параметров целое и указатель на функцию (принимающую целое и не возвращающую значение - void(int) ) и возвращающая указатель на такую же функцию void(int) ), как в параметре. |
| Автор: applegame 29.11.15, 16:56 |
Мододец. |
| Автор: D_KEY 29.11.15, 17:05 |
| Да. Но там объявление типа полностью соответствует использованию операторов, с помощью которых сложный тип дает доступ к своим компонентам. В D это не так. А заговорил о связи объявлений и использования ты Цитата <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void (*foo(int, void (*bar)(int)))(int); Расшифруй навскидку, что такое foo. Там довольно простые правила. Прекрасно описанные в K&R. Другое дело, что читать это неприятно. amk выше правильно написал Цитата И насколько оно визуально соответствует декларации. Плохо соответствует. Но вообще тут в любом случае нужны typedef'ы, каким бы прекрасным не был синтаксис. ИМХО. |
| Автор: applegame 29.11.15, 18:18 |
| Цитата D_KEY @ Связь должна быть визуальная, чтобы удобно было человеку, а не компилятору. Чтобы не надо было учить чтение объявлений по спирали и прочий brainfuck,Да. Но там объявление типа полностью соответствует использованию операторов, с помощью которых сложный тип дает доступ к своим компонентам. В D это не так. А заговорил о связи объявлений и использования ты Но мо собственно отклонились от первичного вопроса. Korvin спросил в чем преимущество D, я ответил, что в удобстве, которое кому-то может показаться наоборот неудобным. То есть преимущество выражается в конкретном человеке. Допустим я на D пишу гораздо быстрее и с меньшим числом ошибок, чем на C++, потому что многие конструкции и идиомы D мне проще и понятней для понимания, чем аналогичное в C++. А если взять, например Qraizer'а, то у него, возможно, все будет наоборот. Добавлено Цитата D_KEY @ Это да, typedef или дешный аналог - alias тут явно не помешал бы. Но вообще тут в любом случае нужны typedef'ы, каким бы прекрасным не был синтаксис. ИМХО. |
| Автор: D_KEY 29.11.15, 18:54 |
| Цитата applegame @ Korvin спросил в чем преимущество D, я ответил, что в удобстве, которое кому-то может показаться наоборот неудобным. То есть преимущество выражается в конкретном человеке. Допустим я на D пишу гораздо быстрее и с меньшим числом ошибок, чем на C++, потому что многие конструкции и идиомы D мне проще и понятней для понимания, чем аналогичное в C++. А если взять, например Qraizer'а, то у него, возможно, все будет наоборот. Т.е. объективных преимуществ ты назвать не можешь? |
| Автор: applegame 29.11.15, 19:02 |
| Ну для тебя лично нет, ты ведь вообще не считаешь какие-либо преимущества одного языка перед другим объективными. Сможешь ли ты назвать объективные преимущества C++ например, перед Visual Basic? Добавлено Если есть желание почитай статью Component programming with ranges Это не C++ vs D, и даже не преимущества D перед C++. Но любопытно, что для D это вполне идиоматичный код, а для C++ скорее экзотика. |
| Автор: amk 30.11.15, 14:07 |
| Я потратил на расшифровку столько времени, сколько понадобилось, чтобы написать пост. Даже меньше. Вообще-то это довольно простое объявление, бывают и позапутаннее. Но, объявить typedef для функций аргумента и результата было бы немного нагляднее. Добавлено А хорошее имя для этого typedef'а ещё и немного прояснило бы назначение кода. |
| Автор: D_KEY 30.11.15, 14:42 |
| В каком-то смысле синтаксис Си толкает людей на тайпдефы. А в других языках может возникнуть ложная иллюзия "итакпонятности". |
| Автор: amk 30.11.15, 14:51 |
| С другой стороны, возможность в C описать чуть ли не любую конструкию одним объявлением порождает иногда такие шедевры... Я один раз видел объявление длиной строк пять. Плотно заполненных, длиной символов 80. Это был пример для проверки утилиты расшифровки объявлений (забыл уже, как она называется). Как написал тот, кто его привёл: из небольших. |
| Автор: JoeUser 30.11.15, 21:27 |
| Давно все сделано в Perl'е <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> my %data; ${${$data{"зеленый"}}[6]}{"вес"} = [1,2,3,4,5]; #присваиваем хешу-массивов-хешей значение в виде массива |
| Автор: amk 02.12.15, 16:26 |
| Нифига непонятно. Что в результате получается-то? И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? Автор языка разве финансистом был? Я слышал, что он лингвист. |
| Автор: applegame 02.12.15, 16:27 |
| Цитата amk @ Чтобы легче парсилось, полагаю. И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? |
| Автор: negram 02.12.15, 18:45 |
| Цитата amk @ доллар обозначает, что значение -- скаляр, похож на букву "s" из соответствующего слова.И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? Автор языка разве финансистом был? Я слышал, что он лингвист. ps: код не промышленный, люди так не пишут Добавлено процент -- хеш-таблица, кружочки вокруг палочки (слеша) символизируют отображение одного значения на другое |
| Автор: korvin 02.12.15, 19:29 |
| Но хоть коммерческий? =) |
| Автор: Qraizer 02.12.15, 21:56 |
| Цитата Сообщить модератору о нарушении в этой теме Спам. |
| Автор: D_KEY 05.12.15, 23:01 |
| Цитата korvin @ Цитата D_KEY @ Его проблема в том, скорее всего, придётся отказаться от оператора [](как и пришлось в scala), а это тоже неудобно. Я почти не знаком со Scala, поэтому не могу с ходу вообразить ситуацию, когда оператор [] будет конфликтовать с использованием [] для параметризации типа Ну а как ты на уровне грамматики это сделаешь? Цитата Вот в D же параметры типа задаются в () и это не конфликтует с оператором () вызова процедуры. Так там же ! перед ними стоит. |
| Автор: korvin 08.12.15, 21:30 |
| Э-м... А как связаны грамматики типов и грамматика операторов? Ну например: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> type Array [T : Any] where { val make : T -> Int -> @This method get : Int -> T method set : Int -> T -> () #implementation } type Map [Key : Hashable, Value : Any] where { val make : () -> @This val make : Int -> @This method get : Key -> Value method put : Key -> Value -> () #implementation } typeclass Indexable Container where { type Index type Value operator _[_] : Container -> Index -> Value operator _[_] <- _ : Container -> Index -> Value -> () } instance Indexable Array [T] where { -- Array is a type, use "type grammar" type Index = Int type Value = T operator array[index] = array.get index -- array is a variable, use "operator grammar" operator array[index] <- value = array.set index value } instance Indexable Map [K, V] where { type Index = K type Value = V operator map[key] = map.get key operator map[key] <- value = map.put key value } let arr = Array.make 3 "" let map : Map[String, Array[String]] = -- Map is a type, use "type grammar" if random.nextBool () then make () else make 2 do { arr[1] <- "foo" -- arr and map are variables map["bar"] <- arr -- use "operator grammar" print arr[1] print arr print map["bar"] print map } => <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> "foo" ["", "foo", ""] ["", "foo", ""] #{"bar" => ["", "foo", ""]} Где тут конфликт? А разве ! не для этих их строковых "миксинов"? |
| Автор: MyNameIsIgor 08.12.15, 21:52 |
| Нет, он для шаблонов. Просто строка является аргументом шаблона. Вот как парсер здесь определит, что это оператор? Можно в парсере запоминать, какие идентификаторы являются именами переменных, а какие - типов. Но и это не всегда работает, поэтому в C++ используются приписки typename и template. Можно как у тебя - имена типов заглавной буквы, имена переменных - со строчной. Но конфликт то всё равно есть, и решается он какими-то дополнительными правилами или ограничениями грамматики. |
| Автор: JoeUser 08.12.15, 22:24 |
| Цитата amk @ И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? Выбор нужного контекста. На предыдущем примере: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> my %data; #просто объявляется локальная переменная-хэш # "парсим" пошагово выражение - ${${$data{"зеленый"}}[6]}{"вес"} = [1,2,3,4,5]; # # $data{"зеленый"} - по ключу "зеленый" выбираем значение хэша # ${$data{"зеленый"}}[6] - выбранное ранее значение - это массив, выбираем его 7-й элемент # ${${$data{"зеленый"}}[6]}{"вес"} - а этот 7-й элемент сам хэш, выбираем в нем значение по ключу "вес" # ... ну и присваиваем этому элементу массив [1,2,3,4,5] Вроде все просто и ясно, не? ЗЫ: В новой редакции Perl'a (6-я версия), будет немного по другому, вроде логичнее: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> %{@{%data{"зеленый"}}[6]}{"вес"} Потому, как элементы хэша уже не похожи на элементы массива, и предваряются неизменяемыми префиксами % и @. Но мне непривычно. Добавлено Именно. |
| Автор: korvin 09.12.15, 22:52 |
| Наверное, по тому, что токен перед ним --- переменная? Цитата MyNameIsIgor @ Можно в парсере запоминать, какие идентификаторы являются именами переменных, а какие - типов. Почему бы и нет? Цитата MyNameIsIgor @ Но и это не всегда работает, поэтому в C++ используются приписки typename и template. Само собой у каждого языка свой синтаксис, где-то это делается легко, где-то --- нет. Я и говорил лишь про конкретно проблему в синтаксисе Scala и конкретно возможность её решения при использовании чуть более другого синтаксиса, а не про возможность разрешить её в любом синтаксисе. Цитата MyNameIsIgor @ Можно как у тебя - имена типов заглавной буквы, имена переменных - со строчной. Э-м. В моём примере это решается не за счёт регистра символов, а за счёт однозначности семантики [] в, так скажем, двух не пересекающихся видах выражений --- "типовых" и "переменных": <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> type-decl ::= "type" <id> "[" <type> ["," <type>]* "]" "where" "{" ... "}" value-decl ::= "val" <id> ":" <type> method-decl ::= "method" <id> ":" <type> typeclass-type-variable-decl ::= "type" <id> instance-type-let ::= "type" <id> "=" <type> operator-decl ::= "operator" <syntax> ":" <type> let ::= "let" <id> ":" <type> let ::= "let" <id> "=" <expr> let ::= "let" <id> ":" <type> "=" <expr> --- упрощённо. Т.е. вполне себе легко определить, что в <type> [] --- параметры, а в <expr> --- оператор. Цитата MyNameIsIgor @ Но конфликт то всё равно есть, и решается он какими-то дополнительными правилами или ограничениями грамматики. Не вижу, в чём ограничение. Если строго разделить виды грамматик <type> и <expr>, то они никак не будут конфликтовать. В Хаскелле, например, нельзя объявить оператор ::, т.к. декларации типов можно использовать в тех же местах, что и выражения, например: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> x = y :: z -- это объявление x = y типа z или объявление x = результат применения оператора :: к переменным y и z? В ML по идее с этим лучше, но всё равно для декларации типа переменной используется : , а для операции cons списка --- :: т.к. есть как минимум одна неоднозначная ситуация: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> function (h : t) = ... -- это паттерн-матчинг аргумента-списка или декларация типа для аргумента? В моём примере никакой неоднозначности быть не может. А можно ли определить оператор : , чтобы он не конфликтовал с объявлением типа? --- Спросишь ты. А можно. И опять никаких неоднозначностей: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> let x : t : y -- syntax error let x : (t : class) -- ok, not an operator in <type> expression let x = y : z -- ok, it's operator : in <expr> expression let x : (t : class) = y : z -- ok, first two : --- <type>, third --- <expr> Как-то так. Добавлено Да собственно, что далеко ходить: в Java выражение дженерик-класса a<b> никогда не может быть спутано с использованием операторов сравнения А вот другие скобки уже используются в синтаксисе классов и только поэтому не могли быть использованы для параметров дженериков. Ну и плюс просто выбрали похожий на шаблоны C++ синтаксис. |
| Автор: MyNameIsIgor 10.12.15, 08:03 |
| Если ты запоминаешь идентификаторы или идентификаторы имеют разный вид для переменных и типов. А иначе ты получишь лишь идентификатор. Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже. Цитата korvin @ Я и говорил лишь про конкретно проблему в синтаксисе Scala и конкретно возможность её решения при использовании чуть более другого синтаксиса Не вижу такой возможности. Цитата korvin @ Т.е. вполне себе легко определить, что в <type> [] --- параметры, а в <expr> --- оператор. Это всё хорошо либо при теоретизировании, либо для синтаксически нищего языка. Например, что такое a[b]© в каком-то выражении? Это я из массива a беру по индексу b функцию и вызываю её с аргументом c? Или это я прямо в выражении без объявления переменной конструирую значение параметрического типа a с параметром b и отдаю в конструктор аргумент c? А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c? ![]() Цитата korvin @ Да собственно, что далеко ходить: в Java выражение дженерик-класса a<b> никогда не может быть спутано с использованием операторов сравнения Навскидку: в Java аргументами обобщений не могут быть значения, в C++ - могут. |
| Автор: D_KEY 10.12.15, 12:08 |
В общем, мало видов скобочек Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно. |
| Автор: korvin 10.12.15, 18:37 |
| Цитата MyNameIsIgor @ Это всё хорошо либо при теоретизировании, либо для синтаксически нищего языка. Например, что такое a[b]© в каком-то выражении? В каком "каком-то" выражении? Ты пишешь на языке произвольных абстрактных выражений? Perl что ли? =) И как разделение выражений на <type> и <expr> вдруг делают язык "синтаксически" нищим? Цитата MyNameIsIgor @ Это я из массива a беру по индексу b функцию и вызываю её с аргументом c? Или это я прямо в выражении без объявления переменной конструирую значение параметрического типа a с параметром b и отдаю в конструктор аргумент c? А где оператор new? Цитата MyNameIsIgor @ А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c? Вот это уже чуть интересней, но допустим у нас нет статических полей, у нас есть модули, где мы можем объявить статические переменные. Поэтому ответ: зависит от того, это <type> или <expr>, а это уже строго определено синтаксисом. Более того, зачем вообще явно указывать тип-параметр, если он выводится из контекста, как во всех нормальных языках? =) Я и не говорил, что Хаскелл --- образец для подражания в этом вопросе. Цитата MyNameIsIgor @ Навскидку: в Java аргументами обобщений не могут быть значения, в C++ - могут. Т.е. вместо a можно подставить 1? Будет 1<b>? И что тогда в C++ означает выражение 1<2>(3)? Создание объекта шаблонного класса 1 с шаблонным параметром 2 и параметром конструктора равным 3? =) Ну, допустим, про 1 я утрировал, но a<1>(2)? Пара-пара-пам? Добавлено Цитата MyNameIsIgor @ Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже. Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций. Кстати, в Хаскелле параметры же пишутся просто через пробел и ведь не путаются с применением функций-конструкторов, которые так же, как и типы, пишутся с заглавной буквы. Т.е. их идентификаторы неотличимы, да и вообще часто совпадают, если конструктор один. Добавлено Цитата D_KEY @ В общем, мало видов скобочек Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно. А может наплевать на всех, и заюзать символы вне ASCII диапазона? =) Но вообще, в Джаве можно бы было использовать круглые скобки, если бы в своё время авторы пару вещей сделали бы по-другому: 1) вместо оператора new использовать new как специальный статический метод, new и так ключевое слово и определить такой метод нельзя. Кроме того, такой синтаксис и так поддерживается в некоторых ситуациях. Т.е. вместо <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> new ArrayList<T>(); было бы <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ArrayList(T).new(); 2) при создании анонимного класса inplace передавать аргументы конструктора не после имени класса, а после фигурных скобок его тела, т.е. вместо <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> new Foo(1) { // ... } писать <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> new Foo { // ... }(1) Тогда после Foo в круглых скобках можно было бы указать типы. По-моему этому ничего особо не мешало, но, может, я что-то упускаю. |
| Автор: MyNameIsIgor 10.12.15, 19:15 |
| В любом. Цитата korvin @ И как разделение выражений на <type> и <expr> вдруг делают язык "синтаксически" нищим? Вводом ограничений. В синтаксически нищих языках ![]() Так что я так и не понял, как ты будешь определять, что это не вызов конструктора. Цитата korvin @ Вот это уже чуть интересней, но допустим у нас нет статических полей, у нас есть модули, где мы можем объявить статические переменные Т.е. я не смогу иметь отдельные переменные для каждого инстанса параметрического типа a? Это уже семантическое, а не синтаксическое, нищенство. Цитата korvin @ Более того, зачем вообще явно указывать тип-параметр, если он выводится из контекста, как во всех нормальных языках? =) Не знаю как там в нормальных, а в самом лучшем так <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<class T> struct a { static constexpr bool s = sizeof(T) == sizeof(char); }; int main() { return a<int>::s; } Как нормальные языки выведут, что я имел в виду именно int? Цитата korvin @ Т.е. вместо a можно подставить 1? Будет 1<b>? И что тогда в C++ означает выражение 1<2>(3)? Создание объекта шаблонного класса 1 с шаблонным параметром 2 и параметром конструктора равным 3? =) Нет. У тебя осталось две попытки ![]() Это боян. Например <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> a.func<A>(b); // что здесь написано? Но проблема раскрывается здесь <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<class T> void foo(T t) { t.func<1>(2); // а здесь что написано? } Добавлено Цитата korvin @ Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций. Усложнения парсера - требуется определить конец откладываемой части. И не всегда осуществимо - например, ты разбираешь обобщение (как у меня в примере выше), но при этом тебе его надо положить в байт-код. Ещё может возникнуть веселуха с циклически ссылающимися друг на друга кусками разбираемого кода. А набирать то их как? |
| Автор: D_KEY 10.12.15, 19:58 |
| korvin, а обобщённые функции как тогда выглядели в такой Java? |
| Автор: korvin 10.12.15, 20:43 |
| Как будто что-то плохое. Тебя же не смущает отсутствие возможности переопределения ключевых слов или использования их в качестве идентификаторов? А то в каком-то языке можно было легко получить код вроде <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> if if begin begin Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =) Типа C++? Цитата MyNameIsIgor @ Так что я так и не понял, как ты будешь определять, что это не вызов конструктора. Как угодно, я выше D_KEY'ю написал пример про Жабу. Или так же, как парсер Хаскелла отличает идентификатор типа от идентификатора конструктора. В нормальных языках нет нужды в подобном коде. =) Это пример того, как Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл []. Это смысл будет дальше определён вычислителем/компилятором. Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)? У Java сложный парсер? Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет? Вот, так и знал, что что-то упущу. Навскидку могу предложить foo(T)(x), выглядит не ок, но логично, т.е. вначале мы передаём конкретный тип и как бы создаём замыкание на его основе, а потом применяем замыкание к аргументу x. Вообще же, тут тип мог бы просто выводиться из типа аргумента, но из-за субтипирования, он может оказаться более общим, чем нужно. Добавлено Цитата MyNameIsIgor @ Т.е. я не смогу иметь отдельные переменные для каждого инстанса параметрического типа a? В нормальных языках параметрический тип ---- это параметрический тип, а не хрен пойми что, плодящая кучу кода. =) Добавлено Compose+( например. В нормальных же операционных системах есть поддержка клавиши Compose =) |
| Автор: MyNameIsIgor 10.12.15, 21:02 |
| Цитата korvin @ Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =) Т.е. обязательно new и отсутствие статических членов - это ненормальные ограничения ![]() Нет, типа Go и Java. Впрочем, они не только синтаксически, они и семантически нищие. Цитата korvin @ Это пример того, как духовносинтаксически богатый язык превозмогает обсуждаемую трудность. С чем ты споришь? =) Нет, не превозмогает. И я привёл тебе код почему не превозмогает. Цитата korvin @ Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл []. Эммм... Все твои рассуждения как раз и сводятся к тому, что мы при парсинге знаем смысл []. Цитата korvin @ Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)? Это не означает, что все неоднозначности можно разрулить без дополнительных приседаний. Что ты и доказал с теми же статическими членами. Цитата korvin @ Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет? Неоднозначности потому и неоднозначности, что без дополнительных телодвижений не разруливаются. Естественно грамматика C++ однозначна, но она контекстно-зависимая и потребовала подпорок typename/template. Добавлено На самом деле ответить тебе просто нечего. Ты всё обсуждение сводишь к "в нормальных языках". А на самом деле ты хочешь сказать "в никем не используемых, никому не нужных поделках". Добавлено В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue... |
| Автор: D_KEY 10.12.15, 22:43 |
| Цитата korvin @ Цитата D_KEY @ В общем, мало видов скобочек Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно. А может наплевать на всех, и заюзать символы вне ASCII диапазона? =) Это не слишком удобно Проще добавить в язык end. Мне не очень нравится, но {} освободит. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> def foo{T}(T x) ... end class A{T} ... end ... foo{int}(10); A{T} a; map{string, int} dict; Добавлено Еще таки есть вариант с дополнительным символом <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map!(string, vector!int) map@(string, vector@int) Или чуть изменим скобки: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> map(:string, vector(:int)) Ну или что-то в таком роде. Эх, в любом случае получается отстой. |
| Автор: applegame 11.12.15, 08:07 |
| Цитата MyNameIsIgor @ А что есть в нормальных ОС вместо epoll/kqueue? IOCP? В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue... |
| Автор: MyNameIsIgor 11.12.15, 08:54 |
| Цитата applegame @ Цитата MyNameIsIgor @ А что есть в нормальных ОС вместо epoll/kqueue? IOCP?В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue... Да, IOCP, /dev/poll |
| Автор: D_KEY 11.12.15, 09:46 |
Может лучше вернуться к обсуждению синтаксиса скобочек? |
| Автор: korvin 12.12.15, 09:21 |
| Ага, я уже запутался, о каких ОС речь. Я имел в виду *nix. Там поддержка клавиши Compose есть. В OS X вместо неё своя замутка с Alt(Option), но тоже пойдёт. В винде всё как всегда. Хотя есть сторонняя программа WinCompose, которая таки позволяет назначить Compose-клавишу, в семёрке она у меня работала нормально, а в восьмёрке почему-то начала периодически отваливаться. |
| Автор: applegame 24.07.16, 06:50 |
| Видео с DConf 2016. Как Remedy использовали D в игре Quantum Break: Quantum Break: AAA Gaming With Some D Code - Ethan Watson Господа из стартапа WEKA.IO пишут софт для облачной системы хранения данных на D без использования GC: Using D for Implementing a Large Scale Primary Storage System - Liran Zvibel Еще интересная тема - бит пакинг. Возможно будет интересно и плюсовикам: Bit Packing like a Madman - Amaury Sechet Ну и для эстетов Все видео с DConf 2016 |
| Автор: applegame 22.06.17, 05:14 |
| Компилятор D gdc утвержден для включения в состав GCC. |
| Автор: JoeUser 22.06.17, 14:29 |
| Лучче бы дэрантайм и фобос допилили, чтобы кросскомпилячился под mingw32. |
| Автор: applegame 23.06.17, 07:05 |
| Типа надо под линупсом компилять проги дл вянды или наоборот? |
| Автор: JoeUser 24.06.17, 13:22 |
| Ага. Автор LDC пиняет на "несовершенство" библиотек. Пошел уже 3-й год, как это было выявлено. |
| Автор: applegame 25.06.17, 04:09 |
| Задача достаточно экзотическая, поэтому, видимо, никто не возится с ней. Добавлено Возвращаясь к противостоянию с C++. Произвольную лямбду можно хранить в std::function. Если у лямбды есть замыкания, то std::function будет делать аллокацию памяти из кучи, верно? И при каждом копировании тоже хапает память из кучи? |
| Автор: JoeUser 26.06.17, 14:52 |
| Не экзотичнее из под линуха для мак оса - и это работает. |
| Автор: applegame 04.07.17, 13:38 |
| Цитата applegame @ Короче таки да, при каждом копировании std::function происходит аллокация, а значит плюсы сливают в этом плане дешке, так как дешные лямбды копируются без аллоцирования и состоят фактически из двух указателей. Возвращаясь к противостоянию с C++. Произвольную лямбду можно хранить в std::function. Если у лямбды есть замыкания, то std::function будет делать аллокацию памяти из кучи, верно? И при каждом копировании тоже хапает память из кучи? |
| Автор: JoeUser 04.07.17, 14:08 |
| Я вот задумался Рано или поздно "новый" GCC (с поддержкой DLang) перекочует в mingw32. Сейчас в библиотеках runtime и phobos есть ошибки, приводящие к невозможности кросс-компиляции. На сколько я правильно разобрался - ошибки из-за неверно расставленных условий компиляции (нет понятия "целевой платформы", есть понятие используемой платформы, т.е. где компилируем/собираем - та и цель). Вопрос ... ну и кто будет (и вообще будет ли) разбираться с этой проблемой? |
| Автор: D_KEY 04.07.17, 14:20 |
| Показывай тесты производительности и расхода памяти. Чего зря болтаешь? |
| Автор: OpenGL 04.07.17, 14:23 |
| Цитата applegame @ Короче таки да, при каждом копировании std::function происходит аллокация, а значит плюсы сливают в этом плане дешке, так как дешные лямбды копируются без аллоцирования и состоят фактически из двух указателей. Не понял. А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли? |
| Автор: negram 04.07.17, 15:17 |
Дык, как всегда в Open Source: разбираться будет тот, кого эта проблема больше |
| Автор: Qraizer 04.07.17, 20:06 |
| Цитата OpenGL @ У них же классы представлены ссылочной семантикой. Бред, конечно, но они привыкли. Пусть порадуются, чё. А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли? |
| Автор: applegame 05.07.17, 07:14 |
| Ну разве что синтетику какую-нибудь попробовать. Цитата OpenGL @ Скопируется при создании лямбды, а при копировании этой лямбды (например при передаче в функцию или сохранении в переменной) замыкания копироваться не будут. А разве должны?Не понял. А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли? Цитата JoeUser @ Вероятнее всего мейнтейнер GDC. Ты можешь попробовать спросить у него самого по поводу этой проблемы, а то и помочь с ней. Кстати, можно под линем компилять код для вянды через wine, говорят все работаэ. Я вот задумался Рано или поздно "новый" GCC (с поддержкой DLang) перекочует в mingw32. Сейчас в библиотеках runtime и phobos есть ошибки, приводящие к невозможности кросс-компиляции. На сколько я правильно разобрался - ошибки из-за неверно расставленных условий компиляции (нет понятия "целевой платформы", есть понятие используемой платформы, т.е. где компилируем/собираем - та и цель). Вопрос ... ну и кто будет (и вообще будет ли) разбираться с этой проблемой? Не забывай, что "у них" есть еще структуры, которые имеют семантику по значению. А в передаче классов по ссылке есть некий смысл. Не могу точно утверждать, но лично у меня создалось впечатление, что большая часть объектов в плюсах обычно передается при помощи указателей/ссылок или же сами являются обертками вокруг указателей. Но это немного не имеет отношения к обсуждаемой теме, так как лямбды в D это не класс, это встроенный в язык тип. Встроенность еще дает возможность компилятору проводить некоторые оптимизации, например в случае если время жизни переменных замыкания гарантированно больше, чем время жизни самой лямбды, то память не аллоцируется вообще, а просто передается указатель на стековый фрейм содержащий переменные замыкания. |
| Автор: Qraizer 05.07.17, 08:17 |
| Та не, речь не об этом. Речь о том, что переменная-объект всегда является ссылкой, так что любые присваивания просто копирую ссылку. При необходимости получить копию объекта это нужно заказать явно. Я не имею ничего против ссылочной семантики как таковой, но я категорически не приемлю смешанную семантику, когда в языке одни типы ссылочные, другие значения. |
| Автор: applegame 05.07.17, 08:23 |
| Цитата Qraizer @ Ну это тема отдельного холивора. Хотя как раз вот тут-то лично я склонен с тобой согласиться. Конечно не столь категорично, но таки мне не нравится эта особенность D. Но как показывает практика - не мешает. То есть раздражение чисто академическое. Я не имею ничего против ссылочной семантики как таковой, но я категорически не приемлю смешанную семантику, когда в языке одни типы ссылочные, другие значения. |
| Автор: Qraizer 05.07.17, 12:22 |
| Это мешает обобщённого коду, заставляя применять метакод с ветвлениями по свойствам типа. Кроме того, винегрет в Дельфи со строками заставляет серьёзно задуматься о том, чтобы категоричность-таки была, просто во избежание прецедентов. |
| Автор: applegame 05.07.17, 15:36 |
| Цитата Qraizer @ Как именно? Я не наблюдал никаких помех. Пример если можно.Это мешает обобщённого коду, заставляя применять метакод с ветвлениями по свойствам типа. Цитата Qraizer @ Не готов говорить о Дельфи. D - не Дельфи. Кроме того, винегрет в Дельфи со строками заставляет серьёзно задуматься о том, чтобы категоричность-таки была, просто во избежание прецедентов. |
| Автор: Qraizer 05.07.17, 17:55 |
| Та обсуждалось уже мульён раз. Типичный пример: тебе нужна локальная копия объекта, и толи = писать, то ли .clone() заранее ты знать не можешь. Для объектов классов = не сделает тебе копию, в результате модификации будут отражены на оригинале, для объектов неклассов .clone() просто провалится. Добавлено За D я тут и не говорю. Говорю за Дельфи. У них там хренова туча типов строк, какие-то объекты, какие-то не объекты, кто-то по сути POD, кто-то объект с состоянием, кто-то сам собой владеет и подсчитывает свои экземпляры, за кем-то надо следить самому, иначе утекут ресурсы, кому-то явно нужно командовать подсчитывать, кому-то если скомандуешь, расфигачишь пол-программы неопределённым поведением. Та ну их нахрен. |
| Автор: applegame 05.07.17, 20:15 |
| Цитата Qraizer @ Дак в плюсах тоже самое: для указателей нужно вызывать clone, а для неуказателей =. Можно представить, что класс D это что-то вроде shared_ptr. Та обсуждалось уже мульён раз. Типичный пример: тебе нужна локальная копия объекта, и толи = писать, то ли .clone() заранее ты знать не можешь. Для объектов классов = не сделает тебе копию, в результате модификации будут отражены на оригинале, для объектов неклассов .clone() просто провалится. |
| Автор: D_KEY 05.07.17, 20:19 |
| Цитата applegame @ Дак в плюсах тоже самое: для указателей нужно вызывать clone, а для неуказателей =. Зачем? <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<typename T> void foo(const T & x) { T a = x; } В случае указателей ты получишь копию указателя. Все одинаково, какой бы тип не был. Единственное, что не совсем логично в плюсах в плане типов - это ссылки. Добавлено Неужели в D нельзя написать аналог такого кода? |
| Автор: applegame 05.07.17, 20:24 |
| В твоем примере не указатель, а ссылка. Добавлено Для классов нет. Для структур можно. |
| Автор: D_KEY 05.07.17, 20:26 |
| Мой пример будет работать для любого T, даже если этот T будет указателем. |
| Автор: applegame 05.07.17, 20:30 |
| Код аналогичный твоему: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(T)(const ref T x) { T t = x; } В случае указатели или класса будет сделана копия указателя / указателя на класс, в остальных случаях копия самого объекта. Добавлено Неправильно он будет работать, читай пост Qraizerа, он хочет именно копию объекта, а не копию укпзателя на него. |
| Автор: D_KEY 05.07.17, 20:32 |
| Цитата applegame @ Код аналогичный твоему: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(T)(const ref T x) { T t = x; } В случае указатели или класса будет сделана копия указателя / указателя на класс, в остальных случаях копия самого объекта. Вот и появляются исключения на ровном месте. Для обобщенного кода куда проще, когда поведение одинаковое(концептуально). Добавлено Цитата applegame @ Непрпвильно он будет работать, читай пост Qraizerа, он хочет именно копию объекта, а не копию укпзателя на него. Указатель - самостоятельный тип. И его значение будет скопировано. Как и для любого другого типа. |
| Автор: applegame 05.07.17, 20:38 |
| Цитата D_KEY @ Какие исключения? Мой код делает ровно тоже самое, что и твой.Вот и появляются исключения на ровном месте. Для обобщенного кода куда проще, когда поведение одинаковое(концептуально). Цитата D_KEY @ И? Ты как-то влез в наш разговор не разобрпвшись о чем речь, Крайзер не хотел копию указателя, он хотел копию объекта, иначе зачем он clone() упомянул. И если ты хочешь некую обобщеную функцию придется метакодить, чтобы отличить указатель от значения. Указатель - самостоятельный тип. И его значение будет скопировано. Как и для любого другого типа. |
| Автор: D_KEY 05.07.17, 20:42 |
| Думаю, что это ты неверно понял оппонента. Цитата Крайзер не хотел копию указателя, он хотел копию объекта Ты C++ забыл? Указатель является самостоятельным типом и его объект содержит адрес. Добавлено В C++ у тебя везде семантика значений. В D одни типы обладают семантикой значений, а другие - ссылочные. Добавлено Цитата applegame @ Цитата D_KEY @ Какие исключения? Мой код делает ровно тоже самое, что и твой.Вот и появляются исключения на ровном месте. Для обобщенного кода куда проще, когда поведение одинаковое(концептуально). Мой код всегда создаёт копию значения типа T. Твой - нет. |
| Автор: Qraizer 05.07.17, 20:47 |
| Цитата applegame @ Нет. Как уже сказал D_KEY, = скопирует указатель и будет прав. Если мне нужно скопировать его содержимое, то я и напишу соответственно, сразу же указав параметром не T, а T*, и копировать буду источником разыменованный аргумент, а не его самого.Дак в плюсах тоже самое: для указателей нужно вызывать clone, а для неуказателей =. Единая семантика – либо значений, либо ссылок – тем и хороша, что я всегда знаю, с чем работаю, и если мне требуется разное поведение для значений/ссылок/указателей, я это легко сделаю либо перегрузкой, либо специализацией. В Плюсах принята семантика значений, но при этом я любой тип легко могу объявить ссылочным простым &. Не всегда это может быть удобно, но альтернатива хуже. Если бы была принята семантика ссылок, то и тут проблемы бы не было, наверняка был бы единый способ явно разыменовать ссылку, чтобы достучаться до хранилища объекта. В случае смешанной семантики у меня нет иного выбора, кроме как ветвиться метакодом, т.к. под T может скрываться и значение, и ссылка, и что конкретно придёт в мой обобщённый код в некой конкретной точке его инстанцирования, я заранее знать никак не могу. |
| Автор: applegame 05.07.17, 21:01 |
| Ну тогда объясни, что хотел оппонент и зачем он упомянул clone(). Тоже самое в D. Для более легкого понимания, представь, что класс в D - это просто особый тип указателя, например shared_ptr. Добавлено А clone() тогда зачем упомянул? То ли хотел сбить меня с толку, то ли решил мгновенно на другие рельсы перепрыгнуть. Цитата Qraizer @ Я тебя не понимаю. Зачем ветвиться? Просто делай присваивание, скопируется обычный указатель или указатель на класс или значение. Никаких ветвлений. В случае смешанной семантики у меня нет иного выбора, кроме как ветвиться метакодом, |
| Автор: D_KEY 05.07.17, 21:23 |
| Цитата applegame @ Тоже самое в D. Для более легкого понимания, представь, что класс в D - это просто особый тип указателя, например shared_ptr. Представить я могу все, что угодно. Но в системе типов D для классов сделано исключение |
| Автор: applegame 05.07.17, 21:30 |
Это не исключение, это ещё один самостоятельный тип. Ты же не называешь указатели исключением. ![]() Единственная претензия, пожалуй, это то, что выглядит оно как передача по значению, а передается указатель. |
| Автор: D_KEY 05.07.17, 21:32 |
| Есть тип T. В C++ не важно, какого этот тип "вида"(метатипа?). В приведенном выше коде будет создана копия значения этого типа. Если мы хотим сделать указатель на этот тип, мы делаем T* или там shared_ptr<T>. В D же, если это класс, то поведение будет отличаться от поведения для всех остальных "видов" типа. В частности, не будет иметь смысл T*. |
| Автор: amk 05.07.17, 21:33 |
| Qraizer, ну не понимает он, что ссылка на объект и сам объект это не одно и то же. applegame, к примеру, иногда в функции, чтобы получить результат, необходимо "поиграться" с состоянием объекта. Например, объект у тебя притворяется числом (представляет дробь или является числом высокой точности, или ещё что-нибудь в этом роде). К при меру число это представляет собой угол (в градусах), и тебе необходимо загнать его в интервал ±180°. Простейший способ — прибавлять/вычитать 360, но чтобы не испортить состояние исходного объекта, ссылку на который ты передал, тебе лучше бы работать с копией. Если ты передаёшь целое или вещественное (встроенный тип), то простое = создаёт тебе копию, с которой ты можешь спокойно манипулировать. Если ты передаёшь числовой объект, то = просто создаёт ещё одну ссылку и все манипуляции отражаются на исходном объекте, портя его. Можно конечно вместо конструкции a += 360 использовать a = a + 360, каждый раз создавая новый объект, но это резко снижает эффективность, поскольку начинаются игры с распределением/освобождением памяти. Поэтому хотелось бы иметь независимый от сущности способ получить её копию. В C++ такой способ есть (их даже несколько), в D, я так понял, нет. В том же Python'е есть функция copy, которая возвращает копию объекта, независимо от того, встроенный это тип или объект, созданный пользователем. Там даже есть функция deepcopy, создающая независимые копии ещё и вложенных объектов. Правда она медленная. В принципе, достаточно написать одну такую функцию и потом ей пользоваться, где понадобится копия. |
| Автор: D_KEY 05.07.17, 21:33 |
| Цитата applegame @ Это не исключение, это ещё один самостоятельный тип. Ты же не называешь указатели исключением. ![]() Так они и не являются исключением. А класс в D является. |
| Автор: applegame 05.07.17, 21:42 |
| Цитата D_KEY @ И чем же он будет отличаться? Будет создана копия значения этого типа, а именно типа класс такой-то. В приведенном выше коде будет создана копия значения этого типа. Если мы хотим сделать указатель на этот тип, мы делаем T* или там shared_ptr<T>. В D же, если это класс, то поведение будет отличаться от поведения для всех остальных "видов" типа. В D будет. Получится нечто похожее на плюсовой T**. |
| Автор: negram 05.07.17, 21:44 |
| Цитата amk @ Qraizer, ну не понимает он, что ссылка на объект и сам объект это не одно и то же. applegame, к примеру, иногда в функции, чтобы получить результат, необходимо "поиграться" с состоянием объекта. Например, объект у тебя притворяется числом (представляет дробь или является числом высокой точности, или ещё что-нибудь в этом роде). К при меру число это представляет собой угол (в градусах), и тебе необходимо загнать его в интервал ±180°. Простейший способ — прибавлять/вычитать 360, но чтобы не испортить состояние исходного объекта, ссылку на который ты передал, тебе лучше бы работать с копией. Если ты передаёшь целое или вещественное (встроенный тип), то простое = создаёт тебе копию, с которой ты можешь спокойно манипулировать. Если ты передаёшь числовой объект, то = просто создаёт ещё одну ссылку и все манипуляции отражаются на исходном объекте, портя его. Можно конечно вместо конструкции a += 360 использовать a = a + 360, каждый раз создавая новый объект, но это резко снижает эффективность, поскольку начинаются игры с распределением/освобождением памяти. Поэтому хотелось бы иметь независимый от сущности способ получить её копию. В C++ такой способ есть (их даже несколько), в D, я так понял, нет. В том же Python'е есть функция copy, которая возвращает копию объекта, независимо от того, встроенный это тип или объект, созданный пользователем. Там даже есть функция deepcopy, создающая независимые копии ещё и вложенных объектов. Правда она медленная. В принципе, достаточно написать одну такую функцию и потом ей пользоваться, где понадобится копия. Не то, чтобы я тут был за кого-то. Но в качестве примера, где мешает ссылочная семантика приведён пример говнокода В данном сценарии я скорее за семантику, которая не одобряет такое поведение |
| Автор: applegame 05.07.17, 21:47 |
| Ты издеваешься? Я тебе не Исмаил Прокопенко, я отлично разбираюсь и в указателях и ссылках и значениях. В D также существует передача по значению и по ссылке, правда самостоятельного типа "ссылка" не существует. Ты мне тут лекции по плюсам для детского сада не читай. У нас тут скорее философский диспут, а не спор о тонкостях работы типов. |
| Автор: KILLER 05.07.17, 21:54 |
| Цитата D_KEY @ Есть тип T. В C++ не важно, какого этот тип "вида"(метатипа?). В приведенном выше коде будет создана копия значения этого типа. Если мы хотим сделать указатель на этот тип, мы делаем T* или там shared_ptr<T>. В D же, если это класс, то поведение будет отличаться от поведения для всех остальных "видов" типа. В частности, не будет иметь смысл T*. На самом деле в С++, с нововведениями их последних стандартов, система типов превратилась тоже в неочевидную. И теперь приходится учитывать много ньюансов. Я про все эти rvalue/lvalue ссылки. |
| Автор: D_KEY 05.07.17, 21:58 |
| Цитата KILLER @ Цитата D_KEY @ Есть тип T. В C++ не важно, какого этот тип "вида"(метатипа?). В приведенном выше коде будет создана копия значения этого типа. Если мы хотим сделать указатель на этот тип, мы делаем T* или там shared_ptr<T>. В D же, если это класс, то поведение будет отличаться от поведения для всех остальных "видов" типа. В частности, не будет иметь смысл T*. На самом деле в С++, с нововведениями их последних стандартов, система типов превратилась тоже в неочевидную. И теперь приходится учитывать много ньюансов. Я про все эти rvalue/lvalue ссылки. Согласен. Ссылки изначально были не логичны. Сейчас все стало совсем плохо. |
| Автор: KILLER 05.07.17, 22:00 |
| По крайней мере там все было очевидно и предсказуемо, а теперь совсем беда. Особенно с универсальными ссылками. |
| Автор: D_KEY 05.07.17, 22:02 |
| Не, ну оно понятно и юзабельно. Но через гланды. |
| Автор: applegame 05.07.17, 22:03 |
| Если вы пишете обобщенную функцию, принимающий любой тип, включая указатели, то для создания копии экземпляра вам придется, как выразился Qraizer, ветвить код, например писать отдельные оверлоады или шаблоны для значений и для указателей. То же самое в D, вам придется ветвиться, но на один тип больше - классы. Важно заметить, что классы в D не похожи на ссылки в плюсах, они похожи именно на указатели. Добавлено не вижу оснований называть это исключением. Например shared_ptr иммитирует ссылочную семантику, но никто не называет его исключением. Добавлено Цитата negram @ Интересно. Назови-ка мне независимый способ получения копии экземпляра объекта в плюсах. Скажем, я передал указатель и нужно создать копию объекта, на который этот указатель указывает. Поэтому хотелось бы иметь независимый от сущности способ получить её копию. В C++ такой способ есть (их даже несколько), |
| Автор: D_KEY 05.07.17, 22:22 |
| Цитата applegame @ не вижу оснований называть это исключением. Например shared_ptr иммитирует ссылочную семантику, но никто не называет его исключением. Так он и не исключение. Есть T, есть shared_ptr<T>. |
| Автор: applegame 05.07.17, 22:32 |
| Не только, T может сам по себе являться shared_ptr<U>. То есть сигнатура шаблона выглядит как будто она принимает значение, а на самом деле это может быть указатель или shared_ptr. |
| Автор: D_KEY 05.07.17, 22:43 |
| Верно. Цитата То есть сигнатура шаблона выглядит как будто она принимает значение, а на самом деле это может быть указатель или shared_ptr. Ну так они же тоже типы. Со своими значениями |
| Автор: applegame 06.07.17, 04:50 |
| Дык и дешный класс тоже тип, со своим значением. И это значение не сам объект (как вы наверное полагаете), а указатель на него. Еще раз, класс в D - это отдельный тип. Если я пишу обобщенный шаблон, я могу специализировать его для классов, также как в плюсах можно специализировать для указателей или shared_ptr. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(T)(T x) if (is(T == class)) { .... } Может в Дельфях как-то иначе устроено и вы неверно понимаете как оно работает в D? |
| Автор: D_KEY 06.07.17, 07:20 |
| Какого типа указатель? |
| Автор: applegame 06.07.17, 08:47 |
| Название типа совпадает с названием класса, так как это все-таки не указатель. Разница во внешнем виде. Написано Foo, а на самом деле это нечто подобное Foo*. И это, как я уже говорил раньше, немного печалит мой перфекционизм. Но опять же, как я уже говорил, это скорее академический недостаток, чем практический. А многие, наоборот, считают его достоинством. Qraizer попытался привести пример случая, когда это начинает мешать, что-то там с клонированием объектов. но потом и ты и он дружно перевели стрелки и сделали вид, что никакого клонирования не было. Приведите пример когда ссылочная семантика классов в D может мешать. Я пытался сам такой пример придумать. Один из приколов, что такой вот классовый псевдоуказатель нельзя разыменовать. Но в случае полиморфных классов его никогда и не нужно разыменовывать, а в случае неполиморфных в D используются структуры. Немного странновастенько, но особо не мешает. |
| Автор: D_KEY 06.07.17, 08:54 |
| Цитата applegame @ Название типа совпадает с названием класса, так как это все-таки не указатель. Разница во внешнем виде. Написано Foo, а на самом деле это нечто подобное Foo* Ну вот о том и речь.Цитата Qraizer попытался привести пример случая, когда это начинает мешать, что-то там с клонированием объектов. Не попытался, а привел. Цитата но потом и ты и он дружно перевели стрелки и сделали вид, что никакого клонирования не было. Так в C++ и не нужно клонирование. Для любого типа сработает копирующий конструктор/оператор=. Цитата Приведите пример когда ссылочная семантика классов в D может мешать. А что там в плане сравнения? Обычно в языках со смешанной семантикой это доставляет определенные неудобства. |
| Автор: Flex Ferrum 06.07.17, 09:12 |
| Цитата applegame @ Qraizer попытался привести пример случая, когда это начинает мешать, что-то там с клонированием объектов. но потом и ты и он дружно перевели стрелки и сделали вид, что никакого клонирования не было. Приведите пример когда ссылочная семантика классов в D может мешать. Смотри. В C++ я могу написать такой метод: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<typename T> T MakeCopy(T val) { T result(val); return result; } Потом понять, что для смарт-указателей мне нужно глубокое копирование и написать специализацию: template<typename T> <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> auto MakeCopy(std::shared_ptr<T> val) { if (!val) return std::shared_ptr<T>(); return std::make_shared<T>(*val); } А так же отдельную специализацию для std::unique_ptr. И всё будет работать для любых вариантов типа параметра. В D, я так понимаю, такой возможности нет. |
| Автор: D_KEY 06.07.17, 09:15 |
| В языках, где все построено на значениях, нужен отдельный generic-тип для значений, эм, местоположения объектов. С операцией, позволяющей достучаться до объекта, который лежит в том месте. В си это указатели. Единственным недостатком с точки зрения логики является то, что невозможно написать свою версию разыменования(или прокси-функцию). <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ??? foo(int *x) { return *x; } В языках, где все ссылки, особых проблем нет. Разве что не очень понятно, как копировать объекты, поэтому просто вводят два вида копирования - обычное и "глубокое". Ну и еще занимаются оптимизацией для примитивных типов, которая хорошо ложится на концепцию ссылок только в том случае, если мы объявляем примитивные типы формально иммутабельными. А вот в языках со смешанным подходом возникают неоднозначности. Как и что мы копируем, как и что мы сравниваем и т.д. Но это все больше теория. На практике, как правило, это не слишком усложняет жизнь. А сложные шаблоны на какой-нибудь яве в любом случае не напишешь А в D, в случае необходимости, можно легко решить проблему и действительно можно считать, что MyClass является просто неким smart_ptr<MyClass__internal>.Вот ссылки в C++ мне совсем не нравятся. Иногда даже думаю, не лучше ли бы было, если бы они не являлись самостоятельными типами, а были просто спецификаторами для параметров функции/возвращаемого значения. А для ссылок можно иметь отдельный generic-тип, что-то вроде указателей без адресной арифметики. Как с этим в D? Добавлено Там выше applegame приводил пример специализации <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(T)(T x) if (is(T == class)) { .... } |
| Автор: applegame 06.07.17, 09:26 |
| Цитата Flex Ferrum @ Неправильно понимаешь. Все точно также, можно специализировать шаблон на классы, на указатели и на все остальное.А так же отдельную специализацию для std::unique_ptr. И всё будет работать для любых вариантов типа параметра. В D, я так понимаю, такой возможности нет. Цитата D_KEY @ Именно так сделано в D. Есть спецификатор ref указывающий, что значение передается по ссылке. Но тип "ссылка" отсутствует. В общем-то не велика беда, можно задействовать указатель, особенно если учесть, что в D указатели агрегатных типов автоматически разыменовываются при обращении к методам и полям. Но я все равно иногда скучаю по плюсовым ссылкам. Их можно с высокой степенью достоверности реализовать в виде структуры-обертки, но это все равно не то. Вот ссылки в C++ мне совсем не нравятся. Иногда даже думаю, не лучше ли бы было, если бы они не являлись самостоятельными типами, а были просто спецификаторами для параметров функции/возвращаемого значения. |
| Автор: D_KEY 06.07.17, 09:28 |
| Можешь пример какой-нибудь привести показательный? |
| Автор: applegame 06.07.17, 09:35 |
| Вряд ли, не помню когда это было. А в последнее время как-то не возникало необходимости в ссылках. У ссылки в плюсах есть серьезное отличие от указателя: ссылка требует обязательной инициализации, то бишь без специальных ухищрений ссылка не может ссылаться на несуществующий объект (уничтожение объекта после создания ссылки не учитываем), а вот указатель может указывать на null или вообще в случайное место. Добавлено Цитата D_KEY @ Вопроса не понял. Поясни. А для ссылок можно иметь отдельный generic-тип, что-то вроде указателей без адресной арифметики. Как с этим в D? |
| Автор: Qraizer 06.07.17, 09:50 |
| Цитата D_KEY @ Как так-то?Единственным недостатком с точки зрения логики является то, что невозможно написать свою версию разыменования(или прокси-функцию). <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int& foo(int *x) |
| Автор: applegame 06.07.17, 09:57 |
| Цитата Qraizer @ Цитата D_KEY @ Как так-то?Единственным недостатком с точки зрения логики является то, что невозможно написать свою версию разыменования(или прокси-функцию). <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int& foo(int *x) Кстати да. Дешный вариант: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ref int foo(int *x) |
| Автор: D_KEY 06.07.17, 09:58 |
| Цитата Qraizer @ Цитата D_KEY @ Как так-то?Единственным недостатком с точки зрения логики является то, что невозможно написать свою версию разыменования(или прокси-функцию). <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int& foo(int *x) Я про Си Добавлено Ссылки в С++ это некий уход от семантики значений. Что является значением типа T&? |
| Автор: settler 07.04.18, 14:27 |
| Для тех кому не нравиться GC Цитата Smooth Operation Related to real time programming is the need for a program to operate smoothly, without arbitrary pauses while the garbage collector stops everything to run a collection. An example of such a program would be an interactive shooter type game. Having the game play pause erratically, while not fatal to the program, can be annoying to the user. There are several techniques to eliminate or mitigate the effect: Preallocate all data needed before the part of the code that needs to be smooth is run. Manually run a GC collection cycle at points in program execution where it is already paused. An example of such a place would be where the program has just displayed a prompt for user input and the user has not responded yet. This reduces the odds that a collection cycle will be needed during the smooth code. Call core.memory.GC.disable() before the smooth code is run, and core.memory.GC.enable() afterwards. This will cause the GC to favor allocating more memory instead of running a collection pass. |
| Автор: Qraizer 07.04.18, 17:30 |
| Угу. Счас набегут RAIIшники и будут смеяться над масштабом этой проблемы. |
| Автор: settler 07.04.18, 21:35 |
| Да тут половина постов про то какое дерьмо этот самый GC, а тут вот вам, не хотите работайте стеком, вот и RAII, не нравиться - gc.disable, хотите чтоб был деструктор - да ради бога , destoy() в помощь, Причем GC тут на вскидку еще круче чем у явы, (могу и ошибаться) А вот и всеми любимые https://dlang.org/phobos/std_typecons.html#RefCounted. Главное при разработке подходы не смешивать иначе - бардак. |
| Автор: D_KEY 07.04.18, 21:45 |
| Цитата settler @ а тут вот вам, не хотите работайте стеком, вот и RAII, не нравиться - gc.disable, хотите чтоб был деструктор - да ради бога , destoy() в помощь, Какой смысл пихать это все в один язык? Как-то не очень себе представляю монолитную систему, где в одном месте GC используется, а в другом нет. Это же неудобно. А если не монолит, то вполне можно использовать разные языки и получить более целостный инструмент в каждом случае. |
| Автор: settler 07.04.18, 22:01 |
| Цитата D_KEY @ Как-то не очень себе представляю монолитную систему, где в одном месте GC используется, а в другом нет. Это же неудобно.Какой смысл пихать это все в один язык? Это ты решаешь, тебе же пишут for RT systems GC can be slow, Можешь вообще Сишный код пускать, в местах где RT, как в Яве, Проблема в том что выбор большой? Вот пусть applegame раскажет, как умные люди делают . |
| Автор: applegame 07.04.18, 22:21 |
| Ошибаешся. Тут он намного хуже, чем у жабы. Цитата D_KEY @ Не более неудобно, чем система, которая в одном месте использует shared_ptr, а в другом нет. RAII и GC ортогональные вещи. Как-то не очень себе представляю монолитную систему, где в одном месте GC используется, а в другом нет. Это же неудобно. |
| Автор: korvin 07.04.18, 22:57 |
| Ха-ха-ха. |
| Автор: Qraizer 07.04.18, 23:23 |
| Он не дерьмо. Он не детерминирован, вот это плохо. Цитата, что ты привёл, рассказывает только об одной проявляющейся проблеме этой недетерминированности, но у неё много сторон, и RAII – одна из них. Я вот честно, не вижу вообще никакой ниши для GC в C++. C++ предлагает другой, более изящный метод решения проблемы lifetime of dynamic storage objects. Он имеет ровно тот же профит, что и GC – отсутствие утечек ресурсов из-за человеческих ошибок, – он детерминирован, чем выгодно отличается от GC, дёшев в эксплуатации и реализации и при сравнении с сырыми поинтерами архитектурно практически от них не отличается. Да, я о смарт-поинтерах. Выходит, что ни сырые поинтеры, ни GC в C++ просто не нужны. Их не к чему применить. P.S. applegame, это не моя цитата. |
| Автор: settler 08.04.18, 05:28 |
| ну а если по ошибке или незнанию ты не тот тип возьмешь? Наличие GC делает невозможным 1. создавать быстрый код, 2. Код где часто надо выделять много памяти есть новый обект , а старый GC eще не стер, (графика например) Я работаю вебом с 2007года , никакой проблемы c GC не вижу , Добавлено Как ты это проверял ? Добавлено Tы сам пару лет назад в другом холиваре, говорил что это не всегда проблема. |
| Автор: applegame 08.04.18, 06:44 |
| Цитата Qraizer @ Весь этот текст довольно бессмысленный, потому что по сути смарт-поинтеры - это одна из реализаций GC.Я вот честно, не вижу вообще никакой ниши для GC в C++. C++ предлагает другой, более изящный метод решения проблемы lifetime of dynamic storage objects. Он имеет ровно тот же профит, что и GC – отсутствие утечек ресурсов из-за человеческих ошибок, – он детерминирован, чем выгодно отличается от GC, дёшев в эксплуатации и реализации и при сравнении с сырыми поинтерами архитектурно практически от них не отличается. Да, я о смарт-поинтерах. Выходит, что ни сырые поинтеры, ни GC в C++ просто не нужны. Их не к чему применить. Да, с мобильного писал, не туда нажал. Исправил |
| Автор: D_KEY 08.04.18, 07:31 |
| Цитата applegame @ Не более неудобно, чем система, которая в одном месте использует shared_ptr, а в другом нет. Если там вместо shared_ptr используется какие-то другие владельцы ресурсов, то вполне удобно(и можно постепенно переводить на unique_ptr, shared_ptr+weak_ptr). Если же там вообще RAII не используется, то это немного странно, но тогда там есть пары функций выделения/освобождения, чем так же можно воспользоваться для перевода на умные указатели. С GC же так не получится. Цитата RAII и GC ортогональные вещи. Вот есть у меня объект, который сам владеет парой объектов(unique_ptr), а над несколькими объектами ещё разделяет владение(через shared_ptr). Может ли такой объект контролироваться GC? Если да, то когда мы "отпустим" ресурсы, которыми объект владеет? Может ли такой объект быть полем объекта, который контролируется GC? Добавлено Считаю, что такая классификация бессмысленна для современного состояния отрасли Я бы RC к GC не относил. Добавлено А будущее, как мне кажется (или хотелось бы), за статическим анализом, за чем-то вроде region inference |
| Автор: applegame 08.04.18, 09:17 |
| Цитата D_KEY @ Получится, точно также. Не забываем, что умные указатели отличаются от скажем инкрементального GC только детерминированностью уничтожения объектов, а в многопоточных системах, даже с умными указателями нереально контролировать время освобождения ресурса, если одновременно несколько потоков совместно этим ресурсом владеют.Если там вместо shared_ptr используется какие-то другие владельцы ресурсов, то вполне удобно(и можно постепенно переводить на unique_ptr, shared_ptr+weak_ptr). Если же там вообще RAII не используется, то это немного странно, но тогда там есть пары функций выделения/освобождения, чем так же можно воспользоваться для перевода на умные указатели. С GC же так не получится. Как показывает практика, детерменированность освобождения ресурса нужна мягко говоря редко. И в этих случаях в GC-языках предусматривают соответствующие средства. Цитата D_KEY @ Может. Зависит от кода, ресурсы можно отпустить и вручную, если нужно. Может. Все эти uniq_ptr и shared_ptr - химеры плюсов, которые языку с GC не нужны, отлично живется без них, поверь.Вот есть у меня объект, который сам владеет парой объектов(unique_ptr), а над несколькими объектами ещё разделяет владение(через shared_ptr). Может ли такой объект контролироваться GC? Если да, то когда мы "отпустим" ресурсы, которыми объект владеет? Может ли такой объект быть полем объекта, который контролируется GC? Цитата D_KEY @ Ну и зря, потому что RC запросто может быть использован в некоторых реализациях GC. Например, GC эрланга исользует RC для некоторых видов ресурсов.Считаю, что такая классификация бессмысленна для современного состояния отрасли ![]() Я бы RC к GC не относил. А GC плохо подходит для плюсов, потому что хороший и быстрый GC для подобных языков нереально сделать. Либо получается говно вроде дешного GC, либо очередной C#. В самом D ничего не намешано. Сам язык сильно GC-ориентирован, а те ссылки, которые привел, Сирожа, это скорее для критических участков кода. Фрилисты с таким же успехом могут быть применены и в плюсах. Цитата D_KEY @ Не знаю что это такое. А будущее, как мне кажется (или хотелось бы), за статическим анализом, за чем-то вроде region inference ![]() |
| Автор: D_KEY 08.04.18, 10:33 |
| Цитата applegame @ Получится, точно также. Не забываем, что умные указатели отличаются от скажем инкрементального GC только детерминированностью уничтожения объектов Так я про это отличие и говорю Оно весьма важно. Цитата а в многопоточных системах, даже с умными указателями нереально контролировать время освобождения ресурса, если одновременно несколько потоков совместно этим ресурсом владеют. А конкретное время и не нужно. Важно знать, что когда "последний" владелец закончит работать, объект будет удален. Ровно в этот момент. И запустит всю цепочку освобождений, связанную с объектом. Цитата Как показывает практика, детерменированность освобождения ресурса нужна мягко говоря редко. Зависит от задачи. Если она нужна редко, то там C++ возможно и не нужен. Цитата И в этих случаях в GC-языках предусматривают соответствующие средства. Ничего толкового, кроме менеджеров контекста/try-with-resources/using и т.п. не видел. А это только локально, внутри функции, без учёта связи объектов. Цитата Может Когда будет освобожден ресурс? Цитата Все эти uniq_ptr и shared_ptr - химеры плюсов, которые языку с GC не нужны, отлично живется без них, поверь. Да чему тут верить? Я ж сам пишу на языках с GC. Тут же мы говорим о сочетании в одном языке, в одной системе. Цитата Ну и зря, потому что RC запросто может быть использован в некоторых реализациях GC. Без детектора циклов это не имеет смысл. А если он есть, то это уже не совсем RC. Это реализация сборщика через RC Сам же RC сборкой мусора не является. Вернее, в современных системах лучше эти понятия разделять. |
| Автор: Qraizer 08.04.18, 13:41 |
| Цитата applegame @ Не согласен. Даже сырые поинтеры вполне можно контролировать "под капотом" технологией, похожей на C++EH. Напомню, что реализация C++EH никак не затрагивает классы и полностью обходится внешними по отношению к охраняемым им объектам структурами данных. Так что вполне можно представить себе реализацию компилятора, который на каждый поинтер заводит счётчик, аддрефит и декрефит его при копировании, присваивании итп и следит за областями видимости этих поинтеров. Это сделает их практически неотличимыми от shared_ptr<>. В итоге получим в общем-то тот самый GC, который хороший, детерминированный и незаметный.А GC плохо подходит для плюсов, потому что хороший и быстрый GC для подобных языков нереально сделать. Либо получается говно вроде дешного GC, либо очередной C#. Только цена подобного решения будет велика. Если C++EH практически не сказывается на производительности кода, кроме собственно случаев, когда исключения выбрасываются, то такие поинтеры будут отнимать ресурсы ЦП постоянно. Т.к. принцип нулевой стоимости запрещает сие, поэтому и есть отдельные библиотечные типы, используя которые программер сознательно идёт на этот оверхед. |
| Автор: negram 08.04.18, 14:17 |
| А RC - это сокращение для чего? |
| Автор: D_KEY 08.04.18, 14:18 |
| Цитата Qraizer @ Так что вполне можно представить себе реализацию компилятора, который на каждый поинтер заводит счётчик, аддрефит и декрефит его при копировании, присваивании итп и следит за областями видимости этих поинтеров. Это сделает их практически неотличимыми от shared_ptr<>. В итоге получим в общем-то тот самый GC, который хороший, детерминированный и незаметный. Ну тот же swift примерно так и работает: https://developer.apple.com/library/content...ceCounting.html Но и там есть явные "слабые ссылки". И без них (или какого-то детектора циклов) ты никак не обойдешься. Добавлено Reference Counting |
| Автор: applegame 08.04.18, 19:40 |
| Оно важно, но не оно превращает GC в не-GC. Когда приспичит GC. Да. И вся аргументация сводится к "мне так кажется". Объективных причин как за смешивание так и против, я не вижу. И в D это не мешает. Мешает просто плохой GC. Цитата D_KEY @ В эрланге нет никаких детекторов цикла. Там RC применяется к объектам, которые принципиально не могут содержать ссылки на другие объекты. Для остальных generational GC.Без детектора циклов это не имеет смысл. А если он есть, то это уже не совсем RC. Это реализация сборщика через RC ![]() Цитата D_KEY @ С чего ты взял? Сам же RC сборкой мусора не является. Вернее, в современных системах лучше эти понятия разделять. |
| Автор: D_KEY 08.04.18, 19:46 |
| Это является следствием работы того, что сейчас называют GC. Полноценная сборка мусора не в состоянии обеспечить детерминированное удаление. Цитата Объективных причин как за смешивание так и против, я не вижу В таком случае лучше не смешивать, ибо так проще. Зачем усложнять, если ценность не ясна? Добавлено Цитата applegame @ Там RC применяется к объектам, которые принципиально не могут содержать ссылки на другие объекты Тогда это можно рассматривать в качестве оптимизации GC для конкретных случаев. От программиста что-то требуется? Цитата Цитата D_KEY @ С чего ты взял?Сам же RC сборкой мусора не является. Вернее, в современных системах лучше эти понятия разделять. Это же просто классификация. Называя RC сборкой мусора легко ввести в заблуждение. Добавлено applegame, посмотри на статью про ARC в swift, что я выше привел. Как думаешь, удобно бы было, если бы они называли это сборкой мусора? |
| Автор: applegame 08.04.18, 19:51 |
| Цитата Qraizer @ Неполноценный GC получится, чреват утечками из-за циклических ссылок.Не согласен. Даже сырые поинтеры вполне можно контролировать "под капотом" технологией, похожей на C++EH. Напомню, что реализация C++EH никак не затрагивает классы и полностью обходится внешними по отношению к охраняемым им объектам структурами данных. Так что вполне можно представить себе реализацию компилятора, который на каждый поинтер заводит счётчик, аддрефит и декрефит его при копировании, присваивании итп и следит за областями видимости этих поинтеров. Это сделает их практически неотличимыми от shared_ptr<>. В итоге получим в общем-то тот самый GC, который хороший, детерминированный и незаметный. Только цена подобного решения будет велика. Если C++EH практически не сказывается на производительности кода, кроме собственно случаев, когда исключения выбрасываются, то такие поинтеры будут отнимать ресурсы ЦП постоянно. Т.к. принцип нулевой стоимости запрещает сие, поэтому и есть отдельные библиотечные типы, используя которые программер сознательно идёт на этот оверхед. Кроме того, почему-то считается, что такой GC будет медленнее современных incremental/generational GC. |
| Автор: Qraizer 08.04.18, 19:57 |
| Почему это? Циклы аутоматично могут детектиться, кто мешает реализовать? |
| Автор: D_KEY 08.04.18, 20:03 |
| Полноценно их можно детектить только в рантайме. И что ты с ними будешь делать автоматически? |
| Автор: applegame 08.04.18, 20:05 |
| Цитата D_KEY @ А что усложняется? Ты можешь полностью забить на RAII и писать так же как пишешь на шарпе или жабе. А ценность ясна - ты можешь применять D для низкоуровневого кода. Я например на D даже микроконтроллеры прогаю, не пользуясь GC.В таком случае лучше не смешивать, ибо так проще. Зачем усложнять, если ценность не ясна? Цитата D_KEY @ Как и в любом языке есть рекомендации в каких ситуациях как лучше поступать или наоборот не поступать.Тогда это можно рассматривать в качестве оптимизации GC для конкретных случаев. От программиста что-то требуется? То есть это вопрос чисто терминологии. Так как мы оба прекрасно понимаем, о чем говорим, то не вижу смысла в дальнейшем споре. Цитата D_KEY @ Да все равно, если честно. Написали бы, сборка мусора обеспечивается при помощи ARC, ничего бы не поменялось. applegame, посмотри на статью про ARC в swift, что я выше привел. Как думаешь, удобно бы было, если бы они называли это сборкой мусора? |
| Автор: D_KEY 08.04.18, 20:08 |
| Цитата applegame @ Кроме того, почему-то считается, что такой GC будет медленнее современных incremental/generational GC. Ну тут комплекс факторов. Ты не сможешь на такой основе сделать быстрое выделение памяти(которое в случае полноценного GC может сводится почти что к инкременту указателя), ибо нет фазы сборки, нет фазы перемещения и уплотнения объектов. Так же у тебя появляется оверхед на каждое копирование ссылки. Да и замеры какие-то вроде проводили, но тут у меня есть сомнения в корректности. |
| Автор: applegame 08.04.18, 20:09 |
| Реализовывали уже, в питоне и в Nim. Тормозно получается. Этож надо строить графы ссылок и искать в нем циклы. Поэтому этот детектор ссылок делают отключаемым. |
| Автор: D_KEY 08.04.18, 20:11 |
| Цитата applegame @ Да все равно, если честно. Написали бы, сборка мусора обеспечивается при помощи ARC, ничего бы не поменялось. Хм. Ну а как бы ты описывал необходимость в слабых ссылках? Ведь они в языках с нормальным GC есть, только совсем другие и для других целей используются. Добавлено Цитата applegame @ А что усложняется? Ты можешь полностью забить на RAII и писать так же как пишешь на шарпе или жабе. Тогда зачем мне D? Есть же kotlin и scala Добавлено Цитата applegame @ А ценность ясна - ты можешь применять D для низкоуровневого кода. Я например на D даже микроконтроллеры прогаю, не пользуясь GC. Но ведь ты сам выше писал, что D gc-ориентированный. Неужели удобнее получается, чем на крестах или rust? |
| Автор: applegame 08.04.18, 20:15 |
| Цитата D_KEY @ Да, я в курсе аргументации противников ARC.Ну тут комплекс факторов. Ты не сможешь на такой основе сделать быстрое выделение памяти(которое в случае полноценного GC может сводится почти что к инкременту указателя), ибо нет фазы сборки, нет фазы перемещения и уплотнения объектов. Так же у тебя появляется оверхед на каждое копирование ссылки. Да и замеры какие-то вроде проводили, но тут у меня есть сомнения в корректности. Несколько лет назад кто-то в D в свое время перехерачил весь рантайм на ARC и доложил о нехилом приросте скорости в какой-то там игре. Но это тоже не совсем корректный замер, так как дешный GC тормозной, и у него кто угодно выиграет. Если бы все эти александрески не парили бы мозг и просто сделали бы те же плюсы, но с синтаксисом и шаблонами D, то очень вероятно, что сейчвс бы Qraizer топил бы за такой D. |
| Автор: Qraizer 08.04.18, 20:22 |
| Цитата applegame @ Ну так как напрограмили, так и работает. Оптимизацию никто не запрещал. Реализовывали уже, в питоне и в Nim. Тормозно получается. Этож надо строить графы ссылок и искать в нем циклы. |
| Автор: applegame 08.04.18, 20:23 |
| Цитата D_KEY @ Да также бы и описывал. Мне неинтересно спорить на тему является ли ARC частным случаем GC или нет. В любом разговоре достаточно договориться о терминах, а там хоть горшком назови. Я твою точку зрения понял, и когда ты будешь писать GC я учту, что ты имеешь в виду "обычный" GC как в D, жабе и т. д.Хм. Ну а как бы ты описывал необходимость в слабых ссылках? Ведь они в языках с нормальным GC есть, только совсем другие и для других целей используются. Это риторический вопрос. Зачем kotlin и scala, когда есть D, Elixir и Haskell? Цитата D_KEY @ Да, удобнее, как ни странно. Фактически ты как бы пишешь на эдаких сильно прокачанных плюсах. Разве что библиотек нет вообще, поэтому чисто как хобби. Профессионально кодить МК на D - это безумие. Но ведь ты сам выше писал, что D gc-ориентированный. Неужели удобнее получается, чем на крестах или rust? Можно конечно предположить, что программисты в Apple криворукие, но я таки склонен полагать, что это не так просто как ты считаешь. |
| Автор: D_KEY 08.04.18, 20:28 |
| Расскажешь, как бы ты сделал детектор циклов? Добавлено Проще же(хотя про scala это вряд ли можно сказать). По крайней мере в рассматриваемом вопросе управления памятью. Добавлено В остальном согласен, там действительно больше о терминологии речь. |
| Автор: applegame 08.04.18, 20:37 |
| Цитата D_KEY @ Не думаю, что проще. На D также легко писать как и на kotlin. Практически все дешные WAT-ы никак с GC не связаны.Проще же(хотя про scala это вряд ли можно сказать). По крайней мере в рассматриваемом вопросе управления памятью. Проблемы возникают, если в программе очень много GC-объектов болтающихся в памяти. У меня например в проекте их сотни тысяч. GC тормозит безбожно. Авторы D2 почему-то забили на опыт Apple. Насколько я помню, в Objective C долго пытались сделять полноценный GC. Мучались, пробовали и так и эдак, но в итоге забили и сделали ARC, потому, что в подобных языках полноценные GC получаются убогими. |
| Автор: korvin 09.04.18, 04:08 |
| В «подобных» — это в каких? В смысле, какой критерий подобности? |
| Автор: applegame 09.04.18, 04:24 |
| Возможность свободно работать с голыми указателями, приводить типы как вздумается, и прочими возможностями ковырять память на низком уровне. |
| Автор: settler 09.04.18, 20:19 |
| Цитата applegame @ Проблемы возникают, если в программе очень много GC-объектов болтающихся в памяти. У меня например в проекте их сотни тысяч. GC тормозит безбожно. Это не проблема GC , а скорее его неверного успользования, запускать каждый раз чтобы убрать один обьект или сразу 50, потом, что мешает создавать обьекты на стеке? Вот, то что в Ди GC плохо документирован, не очень хорошо. |
| Автор: applegame 10.04.18, 05:21 |
| Цитата settler @ Эти объекты иммутабельные и расшариваются между потоками. GC запускается сам, когда ему вздумается. Документации достаточно. Что именно в работе дешного сборщика тебя интересует?Это не проблема GC , а скорее его неверного успользования, запускать каждый раз чтобы убрать один обьект или сразу 50, потом, что мешает создавать обьекты на стеке? Вот серия статей о работе с памятью в D: https://dlang.org/blog/the-gc-series/ |
| Автор: sergioK 29.11.18, 17:51 |
| Снег зимой утомил, есть альтернатива Английский нужно знать, это часть профессии. Добавлено Цитата Qraizer @ Свои программы следует писать сообразно объектной модели выбранного языка, а не наоборот. Вероятно, поэтому другие языки и не зашли. Ну если интерфайсы это плохо, а частное наследование и отсутсвие AOP это хорошо, тогда все верно, ну еще иногда стоит добавлять IMHO, или его аналоги это чтобы не выглядеть швицером .Это сообщение было перенесено сюда или объединено из темы "Блочно-модульное программирование" |
| Автор: Qraizer 29.11.18, 19:51 |
| Цитата sergioK @ Это к чему было?Ну если интерфайсы это плохо, а частное наследование и отсутсвие AOP это хорошо, тогда все верно... Это сообщение было перенесено сюда или объединено из темы "Блочно-модульное программирование" |
| Автор: sergioK 30.11.18, 00:01 |
| Цитата Qraizer @ Цитата sergioK @ Это к чему было?Ну если интерфайсы это плохо, а частное наследование и отсутсвие AOP это хорошо, тогда все верно... к этому Цитата Свои программы следует писать сообразно объектной модели выбранного языка, а не наоборот. Вероятно, поэтому другие языки и не зашли. Посему и Плюсовая может не зайти. Объектная модель у Плюсов одна из наиболее продуманных. Это не значит, что она самая лучшая на свете, но это значит, что если что-то в ней не нравится, скорее всего иначе было бы хуже. Да еще в C++ это не совсем ООП это скорее смесь "is a" && "has a". Te же френды например. И отсутствие полиморфизма на уровне сомпайла, опровергает "скорее всего иначе было бы хуже." И чем не годиться модель языка D например ? Это сообщение было перенесено сюда или объединено из темы "Блочно-модульное программирование" |
| Автор: Qraizer 30.11.18, 05:49 |
| sergioK, не увидел связи между твоими постами. Ты хоть сам-то понял, что хотел сказать или тебя сразу в Холивары? Это сообщение было перенесено сюда или объединено из темы "Блочно-модульное программирование" |
| Автор: sergioK 30.11.18, 09:40 |
| Цитата Qraizer @ sergioK, не увидел связи между твоими постами. Ты хоть сам-то понял, что хотел сказать или тебя сразу в Холивары? Хозяин барин. Это сообщение было перенесено сюда или объединено из темы "Блочно-модульное программирование" |
| Автор: korvin 30.11.18, 19:48 |
| Цитата sergioK @ И отсутствие полиморфизма на уровне компайла, опровергает "скорее всего иначе было бы хуже." А перегрузка? А шаблоны? |
| Автор: Qraizer 01.12.18, 04:09 |
| А за АОП чё ничего не задвинул, korvin? Ща applegame ещё подтянется. |
| Автор: applegame 01.12.18, 22:18 |
А мне особо нечего сказать ![]() Разве что сообщить, что компилятор D смерджен с GCC. |
| Автор: Qraizer 02.12.18, 03:32 |
Как нечего ? Тоже АОП не завезли? Тю, а sergioK так рассчитывал… |
| Автор: korvin 02.12.18, 15:56 |
| А что АОП? |
| Автор: Qraizer 02.12.18, 20:17 |
| Та чёта заглох ажиотаж касательно аспектов. А такие надежды подавал. |
| Автор: sergioK 03.12.18, 17:51 |
| Ажиотаж создал в посте номер 3, показав какой ты швицер и с одного раза не понимаешь что тебе в красивой форме намекнули. Меньше пиши категоричных высказываний. take it or leave it . Теперь про C++ , главный недостаток - отсутствие интерфейсов, частное наследование, и не безопасность кода, Добавлено Цитата korvin @ Цитата sergioK @ И отсутствие полиморфизма на уровне компайла, опровергает "скорее всего иначе было бы хуже." А перегрузка? А шаблоны? А что перегрузка ? Компайлер не понимает что функция должна быть витуальной. Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь, или в мордо книге свои компайлеры пишешь. Добавлено Ну так у вас два дня ушло, выяснить что обревиатура сия значит, |
| Автор: D_KEY 03.12.18, 18:34 |
| На практике не критично, ибо легко достигается просто через абстрактные классы без реализации и полей. Цитата частное наследование Что ты имеешь в виду? Цитата и не безопасность кода Если ты про отсутствие виртуальной машины, то это, в тоже время и достоинство, поскольку не мешает быстродействию и контролю. java-машины тоже на чем-то писать надо Если же ты про сам язык, то да. Есть проблемы. Но развитие в сторону безопасности идет. Цитата А что перегрузка ? Компайлер не понимает что функция должна быть витуальной. Чего ты хочешь? Сам же просил полиморфизм времени компиляции. Цитата Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь, или в мордо книге свои компайлеры пишешь. Да везде это хорошо. Не преувеличивай. Вот исключения действительно не везде используют(есть в стандарт предложения новые на эту тему). |
| Автор: Qraizer 03.12.18, 20:09 |
| Цитата sergioK @ Читаю пост №3: Ажиотаж создал в посте номер 3, показав какой ты швицер с одного раза не понимаешь что тебе в красивой форме намекнули Ни ажиотажа, ни меня. Пукнул мимо лужи?На себя посмотри. Мои высказывания, во-первых, не категоричны, во-вторых, они не мои. Добавлено Цитата sergioK @ Интерфейсы есть ещё с конца 80-ых годов. Частное наследование есть ещё с начала 80-ых. Безопасность кода в твоих руках с вводом в язык исключений. Глазки-то разуй, научить-таки читать учебники. Теперь про C++ , главный недостаток - отсутствие интерфейсов, частное наследование, и не безопасность кода Добавлено Цитата sergioK @ Чё?? Статика в динамике? Второй раз спрашиваю: ты сам-то понял, что хотел сказать? Впрочем, если ты о мультиметодах, добро пожаловать, желаю приятно провести время в трёх темах, им посвящённым. Ну-ка изобрази на дженериках, хочу полюбоваться. А что перегрузка ? Компайлер не понимает что функция должна быть витуальной. Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь, или в мордо книге свои компайлеры пишешь. Добавлено А кому оно нужно было? Как идеология, это прикольная тема, практически же зайцу стоп-сигнал нужнее. |
| Автор: OpenGL 04.12.18, 04:19 |
| Цитата D_KEY @ Вот исключения действительно не везде используют(есть в стандарт предложения новые на эту тему). Что за предложения? Не путай - это динамика в статике! |
| Автор: applegame 05.12.18, 11:23 |
тут в уютненьком эликсировском чятике ФПшники яростно гнобят исключения для ожидаемых ошибок, ранний возврат из функции и прочие любимые зверушки поганых императивщиков. Добавлено Ну и еще новости о D: Liran Zvibel of WekaIO on using D to Create the World’s Fastest File System |
| Автор: Астарот 05.12.18, 11:48 |
| Цитата applegame @ тут в уютненьком эликсировском чятике ФПшники яростно гнобят исключения для ожидаемых ошибок, ранний возврат из функции и прочие любимые зверушки поганых императивщиков. ![]() Так там еще и концепция "пусть оно упадет как можно раньше" |
| Автор: applegame 05.12.18, 12:35 |
Ну не такая конечно. Просто "дай ему упасть". Ну в каких-то случаях такая концепция помогает серверу работать даже с багами. |
| Автор: Астарот 05.12.18, 12:44 |
| Не-не-не, именно "как можно раньше" ![]() С хардкорными багами наврятли. Супервизор попробует поднять упавший процесс N раз, тот, если там баг, накернится на том же месте, и в конечном итоге супервизор решит прервать это мучение. А вот если там баг помяхше, типа нуля на который хочется поделить, пришедшего в процесс снаружи, то да процесс поднимется заново и побежит дальше И все будет хорошо, пока нулей не станет слишком много |
| Автор: applegame 05.12.18, 13:05 |
| Цитата Астарот @ Ага. В целом я, мягко говоря, не фанат этой концепции. Надрачивать на высокие прынцыпы ОТП не в моем стиле. В моем проекте половина процессов имеют невосстановимый стейт, воскрешать их супервизором бесполезно, лучше просто не давать им падать. С хардкорными багами наврятли. Супервизор попробует поднять упавший процесс N раз, тот, если там баг, накернится на том же месте, и в конечном итоге супервизор решит прервать это мучение. А вот если там баг помяхше, типа нуля на который хочется поделить, пришедшего в процесс снаружи, то да процесс поднимется заново и побежит дальше И все будет хорошо, пока нулей не станет слишком много |
| Автор: Астарот 05.12.18, 13:14 |
| Цитата applegame @ Ага. В целом я, мягко говоря, не фанат этой концепции. Надрачивать на высокие прынцыпы ОТП не в моем стиле. В моем проекте половина процессов имеют невосстановимый стейт, воскрешать их супервизором бесполезно, лучше просто не давать им падать. А кто против-то? конечно лучше. Но тут вопрос, скорее, про то, что лучше, если все же упал - воскрешать или не воскрешать? О спасении стейта тут думать уже поздно. Кстати, стейт можно складывать в DTS/ETS, по идее это часть проблем должно закрыть. |
| Автор: applegame 05.12.18, 13:19 |
| Цитата Астарот @ можно, но в моем случае крайне геморно, проще проорать критикал лог и сдохнуть тихо и навсегда, клиенту сказать простите нас грешных, вот вам бонус какой-нибудь. О спасении стейта тут думать уже поздно. Кстати, стейт можно складывать в DTS/ETS, по идее это часть проблем должно закрыть. |
| Автор: Астарот 05.12.18, 13:25 |
Это что за случай такой??? |
| Автор: D_KEY 05.12.18, 13:37 |
| А это зачем нужно? Или так исторически сложилось? |
| Автор: Астарот 05.12.18, 13:52 |
| Зачем нужен стейт? Даже не знаю, что сказать... |
| Автор: applegame 05.12.18, 13:54 |
| Долго объяснять, главная причина: абсолютно непредсказуемый сервис третьей стороны часто не соблюдающий собственные спецификации, и на который мы никак не можем повлиять. Он невосстановимый не потому что так нужно, а потому что слишком сложно его восстановить в валидном состоянии. Конечно ничего невосстановимого нет, но так как я уже вычистил практически все баги и эти процессы перестали падать от слова совсем, то исчезла необходимость городить восстановление , ну и супервизить соответственно тоже не нужно. |
| Автор: Астарот 05.12.18, 14:12 |
| А завершаешь работу ты намертво грохая всю vm? Добавлено Кстати, супервизоры умеют не только супервизить и заверать дочерних супервизоров, но и динамически порождать новые процессы. В общем слишком полезная штука, что бы от нее отказываться. |
| Автор: Qraizer 05.12.18, 14:33 |
| Цитата Астарот @ А какая разница? Если можно не позволить упасть, почему бы этого не сделать? Исключения в жизнь! Если нельзя, то нужно переподнять. Исключения нафик! Это вопрос стоимости усилий. Независимо от реализации нужно логгить и исправлять причину падения. И логгить, и исправлять нужно в обоих вариантах. Но тут вопрос, скорее, про то, что лучше, если все же упал - воскрешать или не воскрешать? |
| Автор: Астарот 05.12.18, 14:44 |
| Я не вижу тут противоречия. Если можно не падать - нужно не падать. А воскрешать или не воскрешать это уже если упал. Само-собой. Просто в одном варианте ты остановишься и будешь стоять пока не исправишь, в другом - будешь как-то бежать периодически спотыкаясь. Что лучше - зависит от каждого конкретного случая. |
| Автор: applegame 05.12.18, 14:55 |
Зачем? Обычно звоним в датацентр и просим обесточить всю стойку Добавлено Цитата Астарот @ Я от них не отказываюсь, кое-где они используются. Например в хттп-сервере. Кстати, супервизоры умеют не только супервизить и заверать дочерних супервизоров, но и динамически порождать новые процессы. В общем слишком полезная штука, что бы от нее отказываться. |
| Автор: Астарот 05.12.18, 15:15 |
| В следующий раз попробуйте закинуть шашку тола! ![]() Вот чего я точно никогда не пойму, так это зачем на erlang/elixir городить свой хттп-сервант |
| Автор: applegame 05.12.18, 15:34 |
| Цитата Астарот @ А зачем его городить? Уже все нагорожено до нас Вот чего я точно никогда не пойму, так это зачем на erlang/elixir городить свой хттп-сервант |
| Автор: Астарот 05.12.18, 16:04 |
| Так и я о том, все давно нагорожено до нас и без OTP |
| Автор: D_KEY 05.12.18, 16:52 |
| Делать ноды с состоянием или без(всякие там кэши - это не состояние, если что) - тоже вопрос, да. Но я спросил не об этом. Вроде автор процитированного меня понял ну и ладно |
| Автор: korvin 05.12.18, 17:59 |
| Цитата applegame @ эти процессы перестали падать от слова совсем, то исчезла необходимость городить восстановление А если баг или какой другой фейл в нижележащем слое (ОС, железо, вот это всё)? |
| Автор: Qraizer 05.12.18, 18:09 |
| Ну так вопрос же о сервисах 24/7, как я понимаю. Цитата Астарот @ Вообще-то в первом варианте остановится лишь тот функционал, который помер, остальные будут продолжать работать. Другое дело, что во втором варианте он-таки будет продолжать попытки взлететь. Ежели так, то я против спотыканий. При спотыканиях оно хоть как-то, но пашет, а когда не пашет, то мотивация поправить багу выше. А вообще, никто не мешает воплотить реинкарнацию и в первом варианте, как бы, тогда вообще пофик. Просто в одном варианте ты остановишься и будешь стоять пока не исправишь, в другом - будешь как-то бежать периодически спотыкаясь. |
| Автор: sergioK 05.12.18, 20:40 |
| Цитата Qraizer @ А кому оно нужно было? Как идеология, это прикольная тема, практически же зайцу стоп-сигнал нужнее. Про зайца не знаю, а вот для EE это мощнейщий механизм, без него вообще их строить оченьсложно, если сильно надо то есть и компиляторы, для секюрити это вообще классика,как и для логов или error handling, по сути это интерапты на уровне аппликации. Если они не нужны для твоих задач, это не значит что они не нужны никому. Добавлено вызывай его явно если есть необходимость, Добавлено Цитата D_KEY @ На практике не критично, ибо легко достигается просто через абстрактные классы без реализации и полей. Ну вообщем то да, хотя зачем в большинстве языков есть и то и то? |
| Автор: korvin 05.12.18, 22:21 |
| Явный вызов GC — моветон. А зачастую, вызов какой-нибудь System.gc() (или как там в Java) вовсе не означает, что он возьмёт и запустится. Потому что в этих языках интерфейсы и абстрактные классы имеют разную семантику. С тем же успехом можно спросить, почему в большинстве языков есть for/while, а в Бейские — только goto. |
| Автор: sergioK 06.12.18, 04:41 |
| Цитата D_KEY @ Цитата и не безопасность кода Если ты про отсутствие виртуальной машины, то это, в тоже время и достоинство, поскольку не мешает быстродействию и контролю. Я про прямой доступ памяти, через поинтер или ссылку. Для одних целей это хорошо, для безопасности нет. Добавлено Цитата korvin @ Явный вызов GC — моветон. А зачастую, вызов какой-нибудь System.gc() (или как там в Java) вовсе не означает, что он возьмёт и запустится. Он для этого и сделан, и он 100% запуститися, я вот если твой указатель не пустой, то результата от GC не будет. А вот зачем в С++ такое, и что с ним делать Я не понимаю. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> class Student:private Person {}; |
| Автор: applegame 06.12.18, 05:24 |
| Помрет, предварительно пискнув в критлог. Помрет только этот процесс, остальные-то продолжат работу. |
| Автор: Астарот 06.12.18, 06:36 |
| Цитата Qraizer @ Ежели так, то я против спотыканий. При спотыканиях оно хоть как-то, но пашет, а когда не пашет, то мотивация поправить багу выше Это если бага у тебя, а не приходит со стороны |
| Автор: korvin 06.12.18, 06:37 |
| Не 100% Цитата -XX:-DisableExplicitGC Enables the option that disables processing of calls to System.gc(). This option is disabled by default, meaning that calls to System.gc() are processed. If processing of calls to System.gc() is disabled, the JVM still performs GC when necessary. |
| Автор: OpenGL 06.12.18, 08:18 |
| Класс, который может отдавать себя как Person, но при этом то, что он является Person - деталь его реализации, а не его контракт. Сплошь и рядом такое может быть. Цитата sergioK @ Я про прямой доступ памяти, через поинтер или ссылку. Для одних целей это хорошо, для безопасности нет. В расте есть прямой доступ к памяти, при этом язык даже более безопасен, пожалуй, чем все эти явошарпы. |
| Автор: JoeUser 06.12.18, 10:13 |
| Цитата OpenGL @ В расте есть прямой доступ к памяти, при этом язык даже более безопасен, пожалуй, чем все эти явошарпы. Зачет-логика!!! Прямой доступ к памяти оборачивается в unsafe-блоки. Наличие только одного такого блока в проге всю безопасность сводит на нет. А вот если бы прямого доступа не было, не было этих unsafe-блоков, тогда конечно, без вопросов. |
| Автор: OpenGL 06.12.18, 12:55 |
| Лол. А наличие монады Io в хаскеле, видимо, сводит на нет всю пользу чистых функций. А наличие типа Any в чём-нибудь а-ля TypeScript сводит на нет всю пользу от типизации |
| Автор: JoeUser 06.12.18, 16:23 |
OpenGL, безопасность - она из другого измерения, нежели польза С хорошей или плохой пользой жить можно. А вот безопасность - это ... короче, там может произойти сигминтация фаульта! |
| Автор: sergioK 06.12.18, 17:41 |
| Цитата OpenGL @ Класс, который может отдавать себя как Person, но при этом то, что он является Person - деталь его реализации, а не его контракт. Сплошь и рядом такое может быть. Это называется салат или каша , a точее has a , тоесть Proxy или Decoratorну так и пиши - этот Proxy/Decorator явно, зачем такие сложности ? https://www.bogotobogo.com/cplusplus/private_inheritance.php |
| Автор: OpenGL 06.12.18, 18:47 |
| О, началась казуистика Нивапрос, замени "сводит пользу от <something> на нет" на "сводит <something> на нет" - не поменяется ничего.Я хз, где ты сложности увидел. |
| Автор: JoeUser 07.12.18, 02:00 |
| Цитата OpenGL @ Нивапрос, замени "сводит пользу от <something> на нет" на "сводит <something> на нет" - не поменяется ничего. Юнит тестирование утверждения "Убить пользу человека на нет" vs "убить человека на нет". Ахтунт!!! Британские ученые заметили, что во втором случае происходит декремент человеческой популяции! |
| Автор: sergioK 07.12.18, 04:27 |
| Я в смысле оверхед, юзать такое можно, но зачем ? keep it simple . |
| Автор: OpenGL 07.12.18, 05:42 |
| Нет там оверхеда. Где ты увидел его вообще? |
| Автор: Qraizer 07.12.18, 08:33 |
| OpenGL, а ещё ты не знал, что у std::vector<> оверхед есть. |
| Автор: applegame 04.05.19, 05:52 |
| Это наконец-то случилось. Вышел релиз GCC 9 с компилятором D: https://www.phoronix.com/scan.php?page=news...mpiler-Released |
| Автор: korvin 05.05.19, 20:57 |
| Команду GCC возглавил Артас? |
| Автор: applegame 06.05.19, 06:06 |
| хз кто это такой, подготовка к сему событию шла лет пять, не меньше. Решение о включении было принято почти два года назад: |
| Автор: D_KEY 06.05.19, 13:39 |
| Отсылка к warcraft 3 же, не? |
| Автор: applegame 06.05.19, 16:34 |
Это надо у korvin спросить. Как-то он слишком тонко пошутил. |
| Автор: D_KEY 06.05.19, 18:10 |
Думаю, это как-то связано с некромантией |
| Автор: korvin 07.05.19, 15:56 |
| D_KEY всё верно понял. Я просто не ожидал, что ты не знаком с этим персонажем. =) |
| Автор: applegame 07.05.19, 17:54 |
| Незнаком. Варя Крофт как-то мимо меня прошла. |
| Автор: OpenGL 22.07.19, 08:15 |
Владение и заимствование в D. Что-то растом запахло |
| Автор: D_KEY 22.07.19, 10:52 |
| Если нормально все запилят, то D будет лучше rust. Но, боюсь, язык это не "спасет", в смысле массового использования. |
| Автор: Астарот 22.07.19, 10:54 |
| D уже 18 лет, а у него все пилят и пилят |
| Автор: OpenGL 22.07.19, 11:57 |
| Хз. Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы, то может и смогут выехать на нормальном метапрограммировании. Всё-таки растовское в сравнении даже с плюсовым убогое. |
| Автор: D_KEY 22.07.19, 12:04 |
| Цитата OpenGL @ Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы Ну опциональный GC нормальная идея. Сейчас они выпиливают(или уже выпилили) зависимость от него во всех стандартных либах. В таком варианте будет ок. Цитата то может и смогут выехать на нормальном метапрограммировании Если C++ к тому времени не догонит. Таки развитие плюсов идет очень хорошими темпами. |
| Автор: OpenGL 22.07.19, 12:33 |
| Иногда да. Но мне не нравится из-за того, что непонятно, как GC должен сочетаться с нормальными деструкторами. Объекты, временем жизни которых предполагается управлять через GC, не должны содержать в себе поля, которым наличие детерминированного деструктора важно? Или пусть содержат, но тогда вызов и их деструкторов будет когда придётся? Оба решения выглядят по-дурацки как по мне. |
| Автор: Астарот 22.07.19, 12:47 |
| Это будет что-то типа метода finalize() из джавы, где наконец-то постановили, что финализаторы - это ПЛОХО, сделали этот метод deprecated и написали злобный коммент в доку. |
| Автор: OpenGL 22.07.19, 13:07 |
| Хм. Не знал. Нагуглил статью, надо будет осилить вечером. PS: никто не знает, откуда гифка в начале статьи? |
| Автор: D_KEY 22.07.19, 13:22 |
| Цитата OpenGL @ Объекты, временем жизни которых предполагается управлять через GC, не должны содержать в себе поля, которым наличие детерминированного деструктора важно? Не уверен, что это всегда можно правильно отследить. Цитата Или пусть содержат, но тогда вызов и их деструкторов будет когда придётся? Думаю, что как-то так, но там могут быть серьезные проблемы с порядком вызова. Цитата Оба решения выглядят по-дурацки как по мне. Ну это же не Java, тут ответственность будет на программисте. applegame может сталкивался, он вроде имел опыт в D. |
| Автор: Астарот 22.07.19, 13:26 |
| https://www.youtube.com/watch?v=O9FNkrrG0tc |
| Автор: JoeUser 23.07.19, 16:05 |
| Ололо. Откуда инфа? Я зык раст весьма специфичен и разнообразен. Вряд ли получится его оценить с любым другим в полной мере (я не говорю про ООП-поддерживающем). Частные тесты - тут да, будут интересны. Все на этом помешались. Раньше пилили чисто либы "под все", щя метапилют ... но выхлопа нуль как-то. |
| Автор: D_KEY 23.07.19, 16:46 |
| Оттуда, что в нем будут все возможности раста, но без ограничений, а еще в нем уже есть нормальное ООП, отличные шаблоны и т.п. И синтаксис у него неплох, в отличие от rust. Добавлено Ты про что? Про производительность? Тут за C++ вряд ли кто сможет угнаться. |
| Автор: OpenGL 24.07.19, 17:17 |
| И всё же местами раст оказывается быстрее. |
| Автор: D_KEY 24.07.19, 17:25 |
| Цитата OpenGL @ Мне лень смотреть, но скорее всего на крестах код написан так себе, а в коде на rust полно unsafe. Насколько я понимаю, сам раст мало делает оптимизаций и там она идет на уровне llvm. И если это так, то странно было бы ожидать от раста производительности си или крестов. Добавлено А там сравнивают с gcc. Это вообще может быть фактически тест gcc vs llvm Честнее сравнить с clang на той же версии llvm. |
| Автор: OpenGL 24.07.19, 17:42 |
| Цитата D_KEY @ Мне лень смотреть, но скорее всего на крестах код написан так себе, а в коде на rust полно unsafe. Правильно, зачем бегло посмотреть в течение 10 секунд, если за пять можно сгенерировать глупое предположение? unsafe там только для использования gmp юзается в одном тесте.Вот это, вероятно, более состоятельный аргумент. |
| Автор: D_KEY 24.07.19, 17:51 |
| gmp как бы сишная либа Даже с asm местами.Или это норм? Там ещё в коде почему-то делают "сишные" структуры через #[repr©]. Интересно, зачем? Надо будет как-нибудь таки потакать палочкой. |
| Автор: OpenGL 24.07.19, 18:20 |
| Я не знаю Это вычисление цифр числа пи, и в сишных исходниках тоже юзается gmp. Странный какой-то тест. |
| Автор: D_KEY 24.07.19, 18:23 |
| Александреску(перевод на Хабре) Какой язык — D, Go или Rust имеет лучшие перспективы заменить C и почему? |
| Автор: OpenGL 24.07.19, 18:27 |
Оригинал 2015 года Добавлено Думаю, где я видел шутку про "день ног" в программировании. Оказывается, я уже читал перевод ответа на эту статью Александреску |
| Автор: D_KEY 24.07.19, 18:35 |
Да, я сначала сюда кинул, а потом прочел |
| Автор: Wound 24.07.19, 19:01 |
| А какая у этих языков ниша? Добавлено Хотелось бы четко понимать, где Rust или D будут лучше, остальных. Или это просто для релакса языки? |
| Автор: Qraizer 24.07.19, 22:43 |
| Кстати, applegame, всё хочу спросить, но постоянно забываю, так, что даже не помню, спрашивал ли уже: реально ли на D напрограммить полноценные мультиметоды? По идее, его метафичи равноценны плюсовым, так что почему бы и нет. |
| Автор: OpenGL 25.07.19, 05:54 |
| Это слишком срачегенераторная формулировка вопроса Исходить надо из плюсов языка, и уже за их счёт определять, насколько они важны лично для тебя и в твоих проектах. Для раста, например, таковые это строгие статические проверки. В нём у тебя у каждой сущности есть своё время жизни, при взятии ссылок компилятор за всеми временами жизни следит и, если обнаруживается несоответствие, отказываться компилить. Это даёт возможность выражать в дизайне API условия навроде "вектор нельзя изменять пока есть итераторы на него". Также есть инструменты, позволяющие сказать, что некий класс нельзя юзать из другого потока. Например, класс Rc, который является аналогом плюсового shared_ptr, но без атомарного счётчика ссылок, очевидно, нельзя заюзать не в том потоке, в котором ты его создал, и не даст тебе сделать это именно компилятор, а не рантайм. Из минусов (хотя это и плюс тоже ) всего этого - необходимо лучше продумывать архитектуру и чётко понимать, кто кем у тебя должен владеть, так что для "херак и в продакшн" раст не годится совершенно. И в итоге всё это делает хаскелевский мем "программа либо компилится, либо работает как надо" в какой-то степени верным и для раста. За D не скажу подробно, это applegame надо звать, либо читать тему с самого начала. |
| Автор: korvin 26.07.19, 21:32 |
| Что такое «нормальное ООП»? Добавлено В первый раз слышу. Откуда это? |
| Автор: Астарот 26.07.19, 21:47 |
| Есть подозрение, что это про Скалу. Ну, и, разумеется, там пропущено "не". |
| Автор: D_KEY 26.07.19, 23:41 |
| Как в мейнстрим языках. Классы, интерфейсы, наследование и т.п. |
| Автор: applegame 27.07.19, 08:56 |
| Тут не запахло, они реально делают это под влиянием идей раста. Правда с вполне конкретной целью. Они хотят библиотечно реализовать всякие RC-контейнеры и хотят сделать это максимально безопасно. Вот и пыжатся, чтобы нельзя было так просто поломать RC. Цитата OpenGL @ Выпиливать GC никто не будет. Программист сам может выпилить GC если он ему не нужен, или прицепить свой собственный GC. Я тут развлечения ради попиливаю на D мелкую RTOS для микроконтроллеров STM32 с кооперативной многозадачностью, никакого GC очевидно там нет. Другой вопрос, что без GC большая часть стандартной либы отваливается, также отваливается и часть фич самого языка. Они работают над этим, добились довольно серьезного прогресса, надо признать.Хз. Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы, то может и смогут выехать на нормальном метапрограммировании. Странная фраза. Чего за ним угоняться-то? Компиляторы для эквивалентного кода в плюсах и D генерят абсолютно одинаковый асм. То же самое касается и сяшки и раста. Цитата Qraizer @ Не знаю, что ты подразумеваешь под "полноценные". Но все, что можно наметапрограммить в плюсах, можно наметапрограммить в D. Кстати, applegame, всё хочу спросить, но постоянно забываю, так, что даже не помню, спрашивал ли уже: реально ли на D напрограммить полноценные мультиметоды? По идее, его метафичи равноценны плюсовым, так что почему бы и нет. |
| Автор: korvin 27.07.19, 09:51 |
| Почему ты считаешь, что оно и только оно — нормальное? |
| Автор: D_KEY 27.07.19, 10:58 |
| Цитата applegame @ Странная фраза. Чего за ним угоняться-то? Компиляторы для эквивалентного кода в плюсах и D генерят абсолютно одинаковый асм. То же самое касается и сяшки и раста. Разница есть даже между разными компиляторами C++. Rust если и у гонится, то только за счет llvm, но, насколько мне известно, пока сам компилятор оптимизации на уровне языка особых не делает. В отличие от того же clang. Т.е. только llvm. За D не скажу, но вроде тесты тоже не в его пользу попадались. Добавлено Нормальное не в смысле "правильное", а в смысле "привычное", "обыденное", как раз "мейнстримные" |
| Автор: OpenGL 27.07.19, 11:21 |
| Хз, собирательное мнение из пары статей по хаскелю. Личный опыт совсем небольшого говнокодинга на нём говорит, что глупые ошибки там сделать сложнее, т.е. в принципе притянуть за уши можно. Фак. И правда |
| Автор: D_KEY 27.07.19, 11:26 |
| Цитата applegame @ Выпиливать GC никто не будет. Программист сам может выпилить GC если он ему не нужен, или прицепить свой собственный GC. Я тут развлечения ради попиливаю на D мелкую RTOS для микроконтроллеров STM32 с кооперативной многозадачностью, никакого GC очевидно там нет. Другой вопрос, что без GC большая часть стандартной либы отваливается, также отваливается и часть фич самого языка. Они работают над этим, добились довольно серьезного прогресса, надо признать. Это хорошо. Так они собираются убрать зависимость стандартной библиотеки от GC полностью или такой цели не стоит, а просто потихоньку убирают там, где можно обойтись? Цитата Не знаю, что ты подразумеваешь под "полноценные". Но все, что можно наметапрограммить в плюсах, можно наметапрограммить в D. А наоборот? |
| Автор: OpenGL 27.07.19, 11:40 |
| Что это за зверь? |
| Автор: korvin 27.07.19, 12:05 |
| С «не» да, слышал такой мем. Добавлено Цитата D_KEY @ Нормальное не в смысле "правильное", а в смысле "привычное", "обыденное", как раз "мейнстримные" Тогда почему ты указываешь это как критерий какого-то положительного качества языка? |
| Автор: D_KEY 27.07.19, 13:46 |
| Цитата korvin @ Тогда почему ты указываешь это как критерий какого-то положительного качества языка? Потому, что будет легче на него перейти и переводить существующие системы на него. |
| Автор: JoeUser 27.07.19, 15:27 |
| Не факт. Все зависит от привычек. Я вот тоже как только начал читать про Раст, сразу как-то воспринял в штыки, что в нем весь фарш ООП реализуется средствами синтаксиса частично. Остальное конечно тоже можно сделать, но чуть сложнее (если не ошибаюсь OpenGL показывал). Но если, к примеру, сравнить С++ и Раст, просто подход разный. У С++ основной подход - это реализация свойств путем объявления методов, наследования для расширения этого "набора свойств", виртуализации методов для переопределения свойств после наследования. У Раста другой подход - реализация поведений. Тоже подход, который имеет право на жысть, как основная концепция. Могу конечно ошибаться, пока только изучаю, но во многих статьях именно это ставят как особенность языка (не говоря конечно о заимствованиях и временах жизни). |
| Автор: D_KEY 27.07.19, 17:03 |
| Да, зависит от привычек. И если их не надо или не обязательно менять, то переход будет легче |
| Автор: JoeUser 27.07.19, 17:07 |
| А если есть привычка не использовать ООП - переход будет труднее |
| Автор: applegame 27.07.19, 17:30 |
| Есть и обратные тесты, где D обгоняет плюсья. Но это все синтетика, в которых если порыться выясняется, что код нихрена не эквивалентный. Референсный компилятор dmd довольно паршиво оптимизирует, а вот gdc (который уже в gcc) и ldc оптимизируют не хуже соответственно g++ и clang. В моей Fedora и gdc и ldc ставится из стандартных реп. Цитата D_KEY @ Там где можно обойтись убирают. Полностью отвязать в принципе невозможно, так как встроенные массивы и замыкания могут задействовать GC.Так они собираются убрать зависимость стандартной библиотеки от GC полностью или такой цели не стоит, а просто потихоньку убирают там, где можно обойтись? Наоборот нет. В D полно метапрограмминга пока недоступного плюсам. По мультиметодам нагуглил вариант реализации: https://github.com/jll63/openmethods.d и блогпост посвященный ей же: https://dlang.org/blog/2017/08/28/open-methods-from-c-to-d/ |
| Автор: Qraizer 27.07.19, 17:40 |
| А насколько просто переносится туда метакод оттуда? |
| Автор: D_KEY 27.07.19, 17:44 |
| Да, но людей с такой привычкой много, мейнстрим же. |
| Автор: Qraizer 27.07.19, 17:44 |
| На джитхабе есть их, но все неполноценные. Например, требующие предоставить полный набор перекрывающих сигнатур. Или всего лишь двупараметрические. Без статических параметров. ...итп. А для полноценности требуются мультиметоды, максимально похожие на обычные функции: произвольная -арность, отсутствие ограничений на типы параметров, лишь некоторые из которых, указывается в прототипе, должны связываться в рантайм, перекрывающие сигнатуры не должны обязательно покрывать полный перебор вариантов, для не предоставленных вариантов должны применяться стандартные правила перегрузки most viable. Как минимум. |
| Автор: applegame 27.07.19, 17:55 |
| Трудно сказать. Что-то простое переносится просто: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ⇓template<typename A> void foo(A a){ ... } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(A)(A a){ ... } Что-то более сложное может потребовать переписывания с нуля, включая алгоритмы и даже философию. Думаю, метапрограмминг в D тебе бы очень понравился, но в дизайне других мест понакосячено серьезно. Так что D умудряется вызывать восторг и ненависть одновременно. ![]() Ну и я бы не стал писать на D код для авионики. |
| Автор: D_KEY 27.07.19, 17:57 |
| Цитата applegame @ а вот gdc (который уже в gcc) и ldc оптимизируют не хуже соответственно g++ и clang. Ну круто, если так |
| Автор: applegame 27.07.19, 18:01 |
| D очень похож на плюсы, так что это не удивительно. |
| Автор: D_KEY 27.07.19, 18:21 |
| Цитата applegame @ Полностью отвязать в принципе невозможно, так как встроенные массивы и замыкания могут задействовать GC. А этим можно как-то управлять? Добавлено Ну оптимизирующий компилятор - достаточно сложная штука, у C и C++ больше и ресурсов и наработок. |
| Автор: applegame 27.07.19, 18:51 |
| Можно заставить компилятор запретить операции с GC в нужном скоупе и не пользоваться этими операциями, заменяя их на RAII, RC (счетчики ссылок), а то и на старое доброе ручное управление памятью. Цитата D_KEY @ Во-первых, автор D - Уолтер Брайт, который сам является разработчиком хорошо известного в прошлом C++ компилятора. Во-вторых, вероятно, ты недооцениваешь оптимизации llvm и бекенда gcc. Все три компилятора D: dmd, gcc и ldc используюут один и тот же фронтенд. А вот бекенды у них разные. Результаты весьма отличаются. Ну оптимизирующий компилятор - достаточно сложная штука, у C и C++ больше и ресурсов и наработок. |
| Автор: Wound 27.07.19, 19:14 |
| D на какую область ориентирован? У него просто синтаксис с какой то встроенной библиотекой? Многопоточность, кросплатформенность на каком уровне? Какие библиотеки под него есть? Игры писать там? Веб? Десктоп? Или это просто какой то красивый синтаксис? |
| Автор: applegame 28.07.19, 07:28 |
| Цитата Wound @ Область у D приблизительно совпадает с C/C++, но из-за достаточно удобного синтаксиса и быстрой компиляции он неплохо зашел в web и даже в скриптинг. С многопоточностью все отлично, с библиотеками не ахти, но к D можно прибиндить сишные и плюсовые либки. Так что игры писать можно. Без рантайма (а значит без GC и большой части стандартной либы) поддерживает, в принципе, все что поддерживают gcc и llvm. Полноценно поддерживаются x86/x86_64 Linux/Windows/MacOS/FreeBSD. Существуют неофициальные билды для Android и Raspberry PI.D на какую область ориентирован? У него просто синтаксис с какой то встроенной библиотекой? Многопоточность, кросплатформенность на каком уровне? Какие библиотеки под него есть? Игры писать там? Веб? Десктоп? Или это просто какой то красивый синтаксис? Короче, если отклонился от официально поддерживаемых платформ - готовся к танцам с бубном. Например: Как на D писать под ARM |
| Автор: Flex Ferrum 28.07.19, 11:33 |
Заканчивалась вторая декада 21-го века. Люди всё ещё придумывали, чем бы им заменить С++. Варианты с Java, C#, D, Go и Rust уже пробовали... Надо придумывать новые! |
| Автор: OpenGL 28.07.19, 11:42 |
| Явошарпы и go разве претендовали на замену плюсам? По-моему максимум на что они претендовали это на какую-либо нишу. |
| Автор: JoeUser 28.07.19, 12:42 |
| Ну в нише мобильных устройств С++ таки подвинулся нехотя |
| Автор: D_KEY 28.07.19, 12:48 |
| Да он много где подвинулся. Просто не все хотят это признавать. |
| Автор: applegame 28.07.19, 13:20 |
| А вот можно ли в плюсах создать "типизированную" лямбду (std::function<void(int)> например) с замыканиями, но без аллокаций в куче? |
| Автор: D_KEY 28.07.19, 13:28 |
| Ну если тебя не устроит auto f = ... или передача в шаблон функции, то нет. Но мне кажется, что о чем-то таком уже был спор тут и даже тесты были, где кресты все равно выиграли по скорости. |
| Автор: applegame 28.07.19, 14:06 |
| Цитата D_KEY @ У кого выигрывали? Я что-то не помню такого спора. Речь именно о типизированной лямбде, для передачи в нешаблонную функцию:Ну если тебя не устроит auto f = ... или передача в шаблон функции, то нет. Но мне кажется, что о чем-то таком уже был спор тут и даже тесты были, где кресты все равно выиграли по скорости. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> pragma(inline, false) void foo(scope void delegate(int) fn) { fn(10); } int bar() { int i = 10; foo((int x){ i += x; }); return i; } Прямой плюсовой аналог однозначно просрет дешному во всем: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> #include <functional> __attribute((noinline)) void foo(std::function<void(int)> fn) { fn(10); } int bar() { int i = 10; foo([&i](int x){ i += x; }); return i; } В дешном аллокаций не будет, в плюсовом, насколько я понимаю, стопроцентно будет. |
| Автор: D_KEY 28.07.19, 14:13 |
| Вот мне помнится, что по крайней мере в скорости вызовов не просирает, а чуть ли не выигрывает Если не лень, можешь померить. Добавлено Цитата __attribute((noinline)) Нахрена? |
| Автор: applegame 28.07.19, 14:26 |
| Цитата D_KEY @ Скорость вызова одинакова, я зырил асм.Вот мне помнится, что по крайней мере в скорости вызовов не просирает, а чуть ли не выигрывает Затем же зачем и <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> pragma(inline, false) Иначе и clang и ldc оптимизируют bar в нуль: вернуть 20. Добавлено Сравниваем шаблонные версии: D: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> pragma(inline, false) void foo(alias fn)() { fn(10); } int bar() { int i = 10; foo!((int x){ i += x; }); return i; } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> template<typename F> __attribute((noinline)) void foo(F fn) { fn(10); } int bar() { int i = 10; foo([&i](int x){ i += x; }); return i; } |
| Автор: applegame 28.07.19, 14:41 |
| Смотрим асм. D: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int example.bar(): push rax mov dword ptr [rsp], 10 mov rdi, rsp call pure nothrow @nogc @safe void example.foo!(example.bar().__lambda1(int)).foo()@PLT mov eax, dword ptr [rsp] pop rcx ret pure nothrow @nogc @safe void example.foo!(example.bar().__lambda1(int)).foo(): add dword ptr [rdi], 10 ret С++: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> bar(): # @bar() push rax mov dword ptr [rsp + 4], 10 lea rdi, [rsp + 4] call void foo<bar()::$_0>(bar()::$_0) mov eax, dword ptr [rsp + 4] pop rcx ret void foo<bar()::$_0>(bar()::$_0): # @"void foo<bar()::$_0>(bar()::$_0)" add dword ptr [rdi], 10 ret В данном случае дешный асм либо равен либо лучше плюсового. Так то. Добавлено Но это все ситуативные оптимизации. Полагаю, что производительность C++ и D можно считать одинаковой, при прочих равных. |
| Автор: Qraizer 28.07.19, 17:16 |
| Нахрена? Добавлено А, сорри, страничка новая. |
| Автор: amk 28.07.19, 20:26 |
| Цитата applegame @ Насколько я понимаю, нет синтаксиса, чтобы типизировать лямбду явно. А неявно компилятор в любом случае её типизирует (поскольку с нетипизированными объектами работать не умеет)А вот можно ли в плюсах создать "типизированную" лямбду (std::function<void(int)> например) с замыканиями, но без аллокаций в куче? И, насколько понимаю, для замыкания всегда выделяется память в стеке. |
| Автор: Qraizer 29.07.19, 17:59 |
| Для замыканий память по любому нужна. Хоть какая-нибудь где-то там. Вопрос "можно ли без аллокаций", думаю, надо понимать как "можно ли без dynamic storage". Добавлено Вопрос в другом: почему хочется без dynamic storage? ИМХО только лишь из-за проблем с производительностью и отсутствием явных языковых правил для dynamic storage duration. С GC можно было бы не париться за duration, но вопрос производительности только ужесточился бы. std::function<> должен быть готов работать с любым объектом, чей интерфейс имеет реализацию указанного operator(), а значит не может не быть полиморфным, а значит в объектной модели C++ должен работать с объектами косвенно, а значит посредством dynamic storage и указателями. Причём с подсчётом ссылок, ибо иначе std::function<> не имел бы семантику значений. |
| Автор: D_KEY 29.07.19, 18:18 |
| Цитата Qraizer @ std::function<> должен быть готов работать с любым объектом, чей интерфейс имеет реализацию указанного operator() Делегаты в D обладают подобным же свойством. |
| Автор: Qraizer 29.07.19, 22:30 |
| Но я-то за Плюсы. Динамический полиморфизм за интерфейсом скрывает информацию об исходном типе, однако её сохраняет статический полиморфизм. Так что да, где спасовал std::function<>, вывозит шаблон. |
| Автор: applegame 30.07.19, 07:56 |
| Какая-нибудь нужна, но в D нередко можно обойтись без дополнительной памяти для замыканий. Ни стековой ни dynamic storage ни GC. Плюсы́ такого фокуса, ЕМНИП, не умеют. Цитата Qraizer @ Ну этот подход работает и в D, так что здесь преимуществ нет. Но я-то за Плюсы. Динамический полиморфизм за интерфейсом скрывает информацию об исходном типе, однако её сохраняет статический полиморфизм. Так что да, где спасовал std::function<>, вывозит шаблон. |
| Автор: Qraizer 30.07.19, 11:20 |
| Каким образом? Причём тут преимущества? Я за недостатки. Просто иначе std::function<> не может быть устроен. Другое дело шаблон, он недостатка не имеет. |
| Автор: applegame 30.07.19, 13:22 |
| Если время жизни лямбды меньше времени жизни переменных замыкания, то можно не резервировать дополнительную память, а обращаться напрямую к данным на стеке. D так умеет. Я приводил пример: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void foo(scope void delegate(int) fn) { fn(10); } int bar() { int i = 10; foo((int x){ i += x; }); return i; } В данном случае в foo передается делегат, время жизни которого, меньше, чем переменной замыкания i. Компилятор знает, что делегат никуда не утечет из функции foo, благодаря атрибуту scope. В foo будет передан указатель на функцию делегата и указатель на стековый фрейм с переменной i. Цитата Qraizer @ А, окай, я тебя неверно понял.Причём тут преимущества? Я за недостатки. Просто иначе std::function<> не может быть устроен. Но есть другой недостаток: например, нельзя сделать массив лямбд с одинаковой сигнатурой, но разными замыканиями. |
| Автор: D_KEY 30.07.19, 13:31 |
| А какие преимущества перед шаблоном в данном случае? Добавлено Цитата applegame @ Но есть другой недостаток: например, нельзя сделать массив лямбд с одинаковой сигнатурой, но разными замыканиями. А для такого случая эта штука со scope как будет работать? |
| Автор: Qraizer 30.07.19, 13:57 |
| Цитата applegame @ Так это просто оптимизация. Оптимизировать и C++ умеет. Для общего-то случая такая оптимизация не гарантируется. Если время жизни лямбды меньше времени жизни переменных замыкания, то можно не резервировать дополнительную память, а обращаться напрямую к данным на стеке. D так умеет |
| Автор: applegame 30.07.19, 23:43 |
| Даже с шаблоном под замыкания в плюсовой лямбде будет выделена память как минимум на стеке. Например, на стеке лежит переменная, а в замыкании ссылка на эту переменную. Ну и template code bloat никто не отменял. К такой штуке scope не прикрутишь никак. Тут будут аллокации в GC. Либо можно как в плюсах хранить функторы аналогичные std::function. Цитата Qraizer @ Плюсы не смогут сделать такую оптимизацию в общем случае. В плюсах нет scope.Так это просто оптимизация. Оптимизировать и C++ умеет. Для общего-то случая такая оптимизация не гарантируется. Но в целом это мелочь, я считаю. Но интересная, на мой взгляд. |
| Автор: Qraizer 31.07.19, 11:44 |
| Во-первых, это сделано в твоём собственном листинге вверху. Я даже проверил, визуалка тоже так умеет. Во-вторых, в Плюсах нет и Cёвого restrict. По той же причине, подозреваю, почему нет scope. |
| Автор: korvin 02.08.19, 20:17 |
| Ну вон в Go нет «нормального ООП» и вообще никакого параметрического полиморфизма, да и обработка ошибок не «нормальная» (привычна разве что для махровых Сишников). Каналы, опять же, для многих «программистов на мейнстримных языках» — не сильно привычный способ синхронизации. Но достаточно много людей его таки начали использовать. |
| Автор: applegame 04.08.19, 09:03 |
| Цитата Qraizer @ Визуалка видимо инлайнит. Если разнести эти функции, то такую оптимизацию в плюсах в принципе невозможно будет сделать.Во-первых, это сделано в твоём собственном листинге вверху. Я даже проверил, визуалка тоже так умеет. Но в целом фигня. Мне бы плюсики с синтаксисом и метапрограммированием дешки и я, наверное, был бы счастлив. |
| Автор: D_KEY 04.08.19, 16:19 |
| Цитата applegame @ Если разнести эти функции, то такую оптимизацию в плюсах в принципе невозможно будет сделать. А с -flto? |
| Автор: Qraizer 05.08.19, 03:49 |
| Та не. Если её не одёрнуть __declspec(), она вообще в компайл-тайм константу 20 высчитывает. |
| Автор: applegame 05.08.19, 13:32 |
| Цитата Qraizer @ Ну поэтому я и одергивал, компилятор D тоже так делает. Та не. Если её не одёрнуть __declspec(), она вообще в компайл-тайм константу 20 высчитывает. |
| Автор: applegame 14.08.21, 10:27 |
| Полюбуйтесь как плюсовой std::function безбожно сливает встроенным дешным лямбдам: C++: https://godbolt.org/z/jzo4aGfGb D: https://godbolt.org/z/senjvanrW Сравните ассемблерный выхлоп функции bar и самой лямбды. |
| Автор: OpenGL 14.08.21, 11:34 |
| Ну и раст тогда уж вдогонку |
| Автор: korvin 14.08.21, 14:21 |
| Я ничего не понимаю в ассемблере. Ocaml, Go. |
| Автор: D_KEY 14.08.21, 14:33 |
| applegame, поясни за scope в данном кейсе, плиз. |
| Автор: applegame 14.08.21, 18:11 |
Это чит ![]() scope гарантирует компилятору, что лямбда не утечет за пределы скоупа функции. Соответственно компилятор может вместо аллоцирования замыкания на куче, просто передать в функцию указатель на контекст на стеке и указатель на функцию лямбды. |
| Автор: Majestio 18.05.26, 16:05 |
| В телегу написал, но повторюсь тут ... Ну так за 5 (пять) лет появилось чо-то в D, с помощью которого можно без напряга гуячить и кроссплатформить?!!! |
| Автор: D_KEY 19.05.26, 06:03 |
| Мертвый же язык. А так вроде были биндинги для gtk и qt |
| Автор: Majestio 19.05.26, 16:40 |
|
| Автор: Qraizer 19.05.26, 16:47 |
| В смысле «мёртвый»? Вообще проектов нет, что ли? Добавлено Цитата applegame @ Полюбуйтесь как плюсовой std::function безбожно сливает встроенным дешным лямбдам: ... Добавлено Удивили козла капустой. Нефик в ГНУсных портах работать:<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> #include <functional> class Foo { public: virtual void foo(std::function<void()> f); }; int bar(Foo* foo, int a, int b, int c, int d) { int e; foo->foo([&] { e = a + b + c + d; }); return e; } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> _TEXT SEGMENT _<e>$ = 8 ; size = 4 _<a>$ = 12 ; size = 4 _<b>$ = 16 ; size = 4 _<c>$ = 20 ; size = 4 _<d>$ = 24 ; size = 4 ??0<lambda_ac228c855dc2c6ed19d01a392d90130f>@@QAE@AAH0000@Z PROC ; <lambda_ac228c855dc2c6ed19d01a392d90130f>::<lambda_ac228c855dc2c6ed19d01a392d90130f>, COMDAT ; _this$ = ecx ; File D:\Work\CPP\2del\q.cpp ; Line 10 mov eax, DWORD PTR _<e>$[esp-4] mov DWORD PTR [ecx], eax mov eax, DWORD PTR _<a>$[esp-4] mov DWORD PTR [ecx+4], eax mov eax, DWORD PTR _<b>$[esp-4] mov DWORD PTR [ecx+8], eax mov eax, DWORD PTR _<c>$[esp-4] mov DWORD PTR [ecx+12], eax mov eax, DWORD PTR _<d>$[esp-4] mov DWORD PTR [ecx+16], eax mov eax, ecx ret 20 ; 00000014H ??0<lambda_ac228c855dc2c6ed19d01a392d90130f>@@QAE@AAH0000@Z ENDP ; <lambda_ac228c855dc2c6ed19d01a392d90130f>::<lambda_ac228c855dc2c6ed19d01a392d90130f> _TEXT ENDS ; Function compile flags: /Ogtpy ; COMDAT ??R<lambda_ac228c855dc2c6ed19d01a392d90130f>@@QBE@XZ _TEXT SEGMENT ??R<lambda_ac228c855dc2c6ed19d01a392d90130f>@@QBE@XZ PROC ; <lambda_ac228c855dc2c6ed19d01a392d90130f>::operator(), COMDAT ; _this$ = ecx ; File D:\Work\CPP\2del\q.cpp ; Line 10 mov eax, DWORD PTR [ecx+16] mov edx, DWORD PTR [ecx+12] push esi mov esi, DWORD PTR [eax] mov eax, DWORD PTR [ecx+8] add esi, DWORD PTR [edx] add esi, DWORD PTR [eax] mov eax, DWORD PTR [ecx+4] add esi, DWORD PTR [eax] mov eax, DWORD PTR [ecx] mov DWORD PTR [eax], esi pop esi ret 0 ??R<lambda_ac228c855dc2c6ed19d01a392d90130f>@@QBE@XZ ENDP ; <lambda_ac228c855dc2c6ed19d01a392d90130f>::operator() _TEXT ENDS ; Function compile flags: /Ogtpy ; COMDAT ?bar@@YAHPAVFoo@@HHHH@Z _TEXT SEGMENT _e$ = -4 ; size = 4 _foo$ = 8 ; size = 4 _a$ = 12 ; size = 4 _b$ = 16 ; size = 4 _c$ = 20 ; size = 4 _d$ = 24 ; size = 4 ?bar@@YAHPAVFoo@@HHHH@Z PROC ; bar, COMDAT ; File D:\Work\CPP\2del\q.cpp ; Line 8 push ecx ; Line 10 sub esp, 40 ; 00000028H ; File C:\VS2022\VC\Tools\MSVC\14.44.35207\include\functional ; Line 855 lea ecx, DWORD PTR _e$[esp+44] ; File D:\Work\CPP\2del\q.cpp ; Line 10 mov eax, esp ; File C:\VS2022\VC\Tools\MSVC\14.44.35207\include\functional ; Line 855 mov DWORD PTR [eax], OFFSET ??_7?$_Func_impl_no_alloc@V<lambda_ac228c855dc2c6ed19d01a392d90130f>@@X$$V@std@@6B@ mov DWORD PTR [eax+4], ecx lea ecx, DWORD PTR _a$[esp+40] mov DWORD PTR [eax+8], ecx lea ecx, DWORD PTR _b$[esp+40] mov DWORD PTR [eax+12], ecx lea ecx, DWORD PTR _c$[esp+40] mov DWORD PTR [eax+16], ecx lea ecx, DWORD PTR _d$[esp+40] mov DWORD PTR [eax+20], ecx ; File D:\Work\CPP\2del\q.cpp ; Line 10 mov ecx, DWORD PTR _foo$[esp+40] ; File C:\VS2022\VC\Tools\MSVC\14.44.35207\include\functional ; Line 978 mov DWORD PTR [eax+36], eax ; File D:\Work\CPP\2del\q.cpp ; Line 10 mov eax, DWORD PTR [ecx] call DWORD PTR [eax] ; Line 11 mov eax, DWORD PTR _e$[esp+4] ; Line 12 pop ecx ret 0 ?bar@@YAHPAVFoo@@HHHH@Z ENDP ; bar _TEXT ENDS P.S. Это VS2022, если что. Банальный ключик-O2 |
| Автор: Majestio 21.05.26, 15:09 |
Не, посоны!!! По-чесноку ... я знаю поговорку "На дураков не обижаются" ... Но я хотя бы попытался |
| Автор: Qraizer 21.05.26, 18:23 |
| Это ты кого... э-э-э... кем обозвал-то? А то был тут у нас один "посетитель": Цитата Я так и не понял, кто кому.— О, привет. А чё ты тут делаешь? — Та вот, денег вам надо заплатить. — P.S. Честно пытался вспомнить, почему тогда замолчал. Не вспомнил. То ли МС-21 заканчивался, то ли SuperJet начинался. |
| Автор: Majestio 22.05.26, 02:18 |
| Я нечяянно, по синьке - а это щетай не щетается! Просто фильм вспомнился клёвый, ретро. |