Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.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
Цитата D_KEY @
У меня дежавю? :)
Ну времени прошло много, многое поменялось. Пора снова просвещать массы :)

Автор: Мяут-Настоящий 11.02.14, 07:22
D это такая Java с плюшками как в Scal'е для C++сников? :)

Цитата applegame @
встроенный

Ну я как раз-таки и люблю (правда не пользую 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
Цитата Мяут-Настоящий @
D это такая Java с плюшками как в Scal'е для C++сников? :)
Не знаю, как в Scala. На жабу не похоже. Гораздо ближе к плюсам, да и компилится в нативный код.
Цитата D_KEY @
Встроенные ассоциативные массивы? Зачем? Не ПХП вроде. А есть выбор между хэш-таблицами и деревьями?
Ассоциативные массивы очень часто используются, так что сделать их одним из базовых типов, ИМХО, верный ход. Выбора нет, в D ассоциативные массивы - это всегда хэш-таблицы. Для деревьев есть стандартная библиотека с соответствующими шаблонами.
Цитата D_KEY @
Тип real? Это который long double?
Близок. Стандарт четко его описывает как максимально большой тип поддерживаемый железом.
Цитата D_KEY @
Плюшки шаблонов не в синтаксисе. Надо задачки решать, чтоб сравнивать.
Давай задачу, или я могу дать. Я решаю в D, ты в плюсах :), вот и сравним.
Цитата D_KEY @
Примеси там не из-за отсутствия множественного наследования, случаем?
В частности, но они и сами по себе весьма хороши, я тебе скажу.
Цитата Wound @
А что на счет тестов производительности?
Вполне достойно: раз, два.

Добавлено
Цитата Повстанець @
На самом деле в средненьком таком проекте никто не пишет сложный, сверхгибкий шаблонный код. Весь он уходит в библиотеки. В лучшем случае -- в утилитарный код, либо куда нить на нижние слои архитектуры, для придания гибкости. В остальном -- стандартненькое ООП, где шаблоны и прочие плюшки по большей части юзаются, нежели создаются.
Это свойство присуще C++. Из-за его крайне громоздкого и корявого синтаксиса шаблонов (посмотрите в буст и ужаснитесь), плюсовое метапрограммирование стало эдаким развлечением для суровых челябинских программистов. В D шаблоны намного проще и мощнее. Благодаря этому они используются повсеместно. В C++ мне приходилось напрягаться чтобы написать очередной относительно сложный шаблон, в D это делается настолько легко и непринужденно, что я даже местами забываю, что это не обычная функция, а шаблонная.

Добавлено
Цитата Flex Ferrum @
applegame, с учётом того, что сейчас творится в рабочих группах комитета по стандартизации C++ - все эти плюшки весьма сомнительные. :)
Это мы еще посмотрим. Комитет по стандартизации - дикий тормоз, а еще ведь нужно ждать пока все эти новшества будут добавлены в компиляторы. А в D - это уже есть: здесь и сейчас.

Автор: 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 @
Это мы еще посмотрим. Комитет по стандартизации - дикий тормоз

Сейчас он достаточно активно жмёт на газ. :) Разбиение на рабочие группы и комитеты пошло явно на пользу.

Цитата applegame @
а еще ведь нужно ждать пока все эти новшества будут добавлены в компиляторы. А в D - это уже есть: здесь и сейчас.

Сейчас два из трёх mainstream-компилятора идут ноздря-в-ноздрю с комитетом. Что gcc, что clang уже активно запиливают новые фичи.

Автор: applegame 11.02.14, 08:12
Цитата OpenGL @
Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов.
Это фича. Почему так сделано не знаю, описано здесь - http://dlang.org/interface.html
Добавлено
Цитата Flex Ferrum @
Сейчас два из трёх mainstream-компилятора идут ноздря-в-ноздрю с комитетом. Что gcc, что clang уже активно запиливают новые фичи.
Ну таки не ноздря в ноздрю. Да и сlang + windows = головная боль.
Короче, как говорится: поживем - увидим. :)

Автор: D_KEY 11.02.14, 08:28
Цитата applegame @
отсуствие необходимости в заголовочных файлах (это свобода, вы плюсовики, просто не знаете как это прекрасно)

Плюсовики пишут и на других языках, поэтому представляют :D
Нормальные модули это хорошо, но вот отделение объявлений и определений - штука полезная. По крайней мере это вопрос дискуссионный.
Кстати, я помню времена, когда в агитках по 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, наткнулся на то ли баг, то ли фичу их реализации интерфейсов. В яве и шарпе интерфейс по-сути предъявляет требования к наличию методов, но откуда они были получены - неважно.
Короче покопал тему. В плюсах сделано также как и в D: http://ideone.com/q5rgmu, И это сделано правильно.
Интерфейс - это требование реализации, а не просто наличия. Кроме того, интерфейс - это еще и базовый тип с виртуальными функциями f() и g(). Класс Base в твоем примере никакого отношения к IBoo не имеет, соответственно функция интерфейса f() в классе Derived не реализована и не может быть вызвана через тип интерфейса. Хз как это сделано в этих ваших явах и шарпах.
Наличие можно проверить по другому и интерфейсы здесь вообще-то не нужны.

Автор: D_KEY 11.02.14, 08:45
Цитата applegame @
Ассоциативные массивы очень часто используются, так что сделать их одним из базовых типов, ИМХО, верный ход.

Какие плюсы от встраивания в язык?

Цитата
Близок. Стандарт четко его описывает как максимально большой тип поддерживаемый железом.

У D, если что, нет стандарта.

Цитата
Это свойство присуще C++. Из-за его крайне громоздкого и корявого синтаксиса шаблонов (посмотрите в буст и ужаснитесь), плюсовое метапрограммирование стало эдаким развлечением для суровых челябинских программистов.

Не согласен :) Шаблоны, как правило, действительно наиболее полезны в библиотеках и "утилитарном" коде. Хотя и не всегда.

Цитата
А в D - это уже есть: здесь и сейчас.

Вопрос в том, есть ли здесь и сейчас сам D и в каком он состоянии.

Добавлено
Цитата applegame @
Цитата OpenGL @
Помню, когда ковырялся с D, наткнулся на то ли баг, то ли фичу их реализации интерфейсов.
Это фича.

Плохая фича.

Добавлено
Цитата applegame @
Короче покопал тему. В плюсах сделано также как и в D

Нет, не так же. В плюсах нет интерфейсов.

Автор: trainer 11.02.14, 08:46
Цитата applegame @
вы плюсовики, просто не знаете как это прекрасно
Ты в прошлом дельфист?
Это характерная кодовая фраза.

Автор: D_KEY 11.02.14, 08:47
Цитата applegame @
Кроме того, интерфейс - это еще и базовый тип с виртуальными функциями f() и g().

А не должен быть :) Иначе это не интерфейс, а обычный плюсовый абстрактный класс. Вот только множественного наследования в D нет :tong:

Автор: 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}>
    version(Windows) {
      ...
    }
    version(linux) {
      ...
    }
Версию можно задать и кастомную через аргументы командной строки, Затем проверять ее. Раскрыто здесь: http://dlang.org/version.html
Цитата D_KEY @
Попадались мне разные тесты, которые показывали, что как-то не очень там все. Впрочем, не найду сейчас :(
Когда-то было худо. Сейчас есть небольшие проблемы с производительностью при очень больших объёмах CTFE-кода. В проекте над которым я тружусь вовсю используются compile-time веб-шаблоны написаные на Diet. Они компиляться прямо в D-код, из-за чего чрезвычайно быстры.
Цитата D_KEY @
Мы вроде даже на форуме выясняли, что преимуществ перед лямбдами и std::function нет. Единственная фича - сохранение захваченного контекста, а не как в C++, где захват по ссылке локальной переменной приведет к проблемам, если лямбда будет жить дольше локального фрейма.
Лямбдами в D просто удобней пользоваться. В D я знаю тип лямбды и могу его использовать, а в C++ у лямбды тип compiler specific, то бишь, фактически, неизвестен. std::function - имеет заметный оверхед по сравнению с лямбдами.
Цитата D_KEY @
Чем это принципиально отличается от возможностей C и C++?
Сейчас уже возможно особо ничем, так как вроде реализовали уже в GCC даже под вынь.
Цитата D_KEY @
Недостатком является его плохая степень опциональности. Сам по себе сборщик это хорошо, если он не вездесущий.
Полностью согласен.

Добавлено
Цитата trainer @
Ты в прошлом дельфист?
Это характерная кодовая фраза.
Фу-фу. Я в прошлом плюсовик, как ни странно. Даже фанат можно сказать.
Цитата D_KEY @
А не должен быть :) Иначе это не интерфейс, а обычный плюсовый абстрактный класс. Вот только множественного наследования в D нет :tong:
Дык, интерфейсы в D - это по сути и есть плюсовый абстрактный класс, в котором все виртуальные функции - чисто виртуальные. Я могу создать переменную с типом интерфейса и хранить в ней любой объект унаследовавший данный интерфейс. Если мне нужно просто проверить наличие функций, я это сделаю без всяких интерфейсов, причем compile-time, так-то. Множественное наследование - не нужно. :P

Автор: Wound 11.02.14, 09:05
Цитата sergioK @
IDE какие для D , кроме Code Blocks ?

А что, тот же NetBeans никак не прикрутить? Да и IDE по мойму самая последняя проблема. В блокноте пиши ну или Far юзай :D

Автор: D_KEY 11.02.14, 09:06
Цитата applegame @
Препроцессор - кривой костыль.

:D

Цитата
В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    version(Windows) {
      ...
    }
    version(linux) {
      ...
    }

Если честно, это выглядит как детский сад. Какие-то зашитые названия ОС прямо в среду. С препроцессором все совсем иначе - это обычные define'ы в системных заголовочных файлах.

Цитата
Версию можно задать и кастомную через аргументы командной строки, Затем проверять ее.

Так чем это отличается от того, что все делают в C и C++?

Цитата
Цитата D_KEY @
Мы вроде даже на форуме выясняли, что преимуществ перед лямбдами и std::function нет. Единственная фича - сохранение захваченного контекста, а не как в C++, где захват по ссылке локальной переменной приведет к проблемам, если лямбда будет жить дольше локального фрейма.
Лямбдами в D просто удобней пользоваться. В D я знаю тип лямбды и могу его использовать, а в C++ у лямбды тип compiler specific, то бишь, фактически, неизвестен. std::function - имеет заметный оверхед по сравнению с лямбдами.

Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю?

Цитата
Цитата D_KEY @
Чем это принципиально отличается от возможностей C и C++?
Сейчас уже возможно особо ничем, так как вроде реализовали уже в GCC даже под вынь.

А раньше чем отличалось? :) Давно уже использовали tls на разных платформах. Да и boost::thread_specific_ptr появился очень давно. В Qt тоже есть что-нибудь на эту тему наверняка.

Добавлено
Цитата applegame @
Дык, интерфейсы в D - это по сути и есть плюсовый абстрактный класс

Так в D же есть абстрактные классы :D Зачем им плюсовые? Что мешало сделать интерфейсы такими же, как в других языках, где они есть? Зачем людей путать? Ради NVI?

Автор: applegame 11.02.14, 09:12
Цитата sergioK @
IDE какие для D , кроме Code Blocks ?
Выбор негуст, но есть:
- плагин для MSVS - VisualD;
- аддон к Monodevelop - Mono-D;
- IDE на базе Eclipse - DDT

Добавлено
Цитата D_KEY @
С препроцессором все совсем иначе - это обычные define'ы в системных заголовочных файлах.
Ага, а потом эти заголовочные файлы надо еще правильно подключить в зависимости от ОС. Привет системам сборки а-ля make, cmake, scons - тысячи их :D Скорей это выглядит как старперский пережиток прошлого. :P
Цитата D_KEY @
Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю?
Мы забросили тесты. Там был слишком простой код, который G++ оптимизировал просто в нуль. Он это умеет, да, также как и GDC. :)
Цитата D_KEY @
Так чем это отличается от того, что все делают в C и C++?
В том что это делает "умный" компилятор, а не "тупой" препроцессор. Что позволяет, например, намного лучше диагностировать ошибки.
Цитата D_KEY @
А раньше чем отличалось? :) Давно уже использовали tls на разных платформах. Да и boost::thread_specific_ptr появился очень давно. В Qt тоже есть что-нибудь на эту тему наверняка.
Раньше не было встроено в язык. В D, по умолчанию, все глобальные переменные - в TLS. А если рассуждать так как ты, то C++ ничем не лучше ассемблера. А что? Там тоже можно пользоваться TLS, через API OS.
Цитата D_KEY @
Так в D же есть абстрактные классы :D Зачем им плюсовые? Что мешало сделать интерфейсы такими же, как в других языках, где они есть? Зачем людей путать? Ради NVI?
Они похожи, но таки разные вещи. В D можно наследоваться от нескольких интерфейсов, но нельзя от нескольких классов. Класс, в отличие от интерфейса, может содержать еще и данные.

Добавлено
D_KEY, ты задаешь слишком много вопросов :D, я не успеваю на них отвечать. Давай лучше разберем каждый аспект по очереди, не торопясь :)

Автор: D_KEY 11.02.14, 09:35
Цитата applegame @
Ага, а потом эти заголовочные файлы надо еще правильно подключить в зависимости от ОС. Привет системам сборки а-ля make, cmake, scons - тысячи их :D

Так эти задачи и должна решать система сборки :) В языке это смотрится как излишек. Да и всех проблем не решить заранее в языке. По схожим причинам мне не нравится зашитая в D поддержка юнит-тестов.

Цитата
Цитата D_KEY @
Так вроде выясняли, что не имеет при нормальной оптимизации, особенно в сравнении с D. Или я что-то путаю?
Мы забросили тесты. Там был слишком простой код, который G++ оптимизировал просто в нуль. Он это умеет, да, также как и GDC. :)

Ну давай продолжим. Придумай тестик с демонстрацией преимуществ D.

Цитата
Цитата D_KEY @
Так чем это отличается от того, что все делают в C и C++?
В том что это делает "умный" компилятор, а не "тупой" препроцессор. Что позволяет, например, намного лучше диагностировать ошибки.

Пример?

Цитата
А если рассуждать так как ты, то C++ ничем не лучше ассемблера. А что? Там тоже можно пользоваться TLS, через API OS.

Во-первых, API нормальных ОС описано на Си. Во-вторых, C++ высокоуровнее ассемблера а не хуже/лучше.

Цитата
В D можно наследоваться от нескольких интерфейсов, но нельзя от нескольких классов. Класс, в отличие от интерфейса, содержит еще и данные.

Это все понятно. Не понятно, почему было не сделать интерфейсы такими, к каким привыкли люди.

Цитата
D_KEY, ты задаешь слишком много вопросов :D, я не успеваю на них отвечать. Давай более последовательно разберем каждый аспект по очереди :)

Странно, у меня на подробных разбор одного аспекта будет времени больше уходить, чем вот так вот отвечать.
"Письмо это вышло более длинным только потому, что мне некогда было написать его короче"(с) Блез Паскаль :D

Добавлено
applegame, ладно, выбирай аспект :)

Автор: applegame 11.02.14, 09:42
Давай про интерфейсы :)
Цитата D_KEY @
Это все понятно. Не понятно, почему было не сделать интерфейсы такими, к каким привыкли люди.
Какие люди? К чему привыкли? Я вообще ни к чему не привыкал. В C++ интерфейсов не было, вместо них юзались абстрактные классы, в похапе я даже не помню были ли интерфейсы. :) На форуме D кстати этот вопрос поднимался. Одна из причин - отсутствие множественного наследования. Интерфейсы могут помочь, когда такое наследование необходимо.

Автор: OpenGL 11.02.14, 09:42
Цитата applegame @
В плюсах сделано также как и в D: http://ideone.com/q5rgmu,

В плюсах-то как раз понятно - там в качестве интерфейсов используются абстрактные классы, не являющиеся интерфейсами. Поэтому плюсовое поведение в данном случае вполне логично.
Цитата applegame @
Интерфейс - это требование реализации, а не просто наличия.

Реализация тоже есть же - в базовом классе.
Цитата sergioK @
IDE какие для D , кроме Code Blocks ?

Видел для студии соответствующий плагин :) Visual D называется.
Цитата applegame @
Дык, интерфейсы в D - это по сути и есть плюсовый абстрактный класс, в котором все виртуальные функции - чисто виртуальные.

Странное решение. Интерфейс показывает, грубо говоря - "что экземпляр класса умеет делать", а наследование - "кем является объект этого класса". Первое связано со вторым, но им, очевидно, не является.

Добавлено
Цитата applegame @
Какие люди? К чему привыкли?

Люди, пишущие на языках, где есть интерфейсы, привыкли пользоваться ими как интерфейсами, а не как абстрактными классами :)
Цитата applegame @
Интерфейсы могут помочь, когда такое наследование необходимо.

Кстати, ЕМНИП, 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
Цитата applegame @
Какие люди? К чему привыкли?

Программисты, использующие языки, в которых есть интерфейсы. Привыкли к тому, что описал OpenGL.

Цитата
На форуме D кстати этот вопрос поднимался. Одна из причин - отсутствие множественного наследования. Интерфейсы могут помочь, когда такое наследование необходимо.

Это причина для добавления в язык интерфейсов, да. Так поступили в Java и в C#. Правда scala показала немного другой путь с trait'ами, но это к делу не относится.
Но зачем же наделять интерфейсы свойствами абстрактных базовых классов? Так, пожалуй, их проще реализовать. Но это не аргумент.

Автор: OpenGL 11.02.14, 09:48
Цитата applegame @
Насчет плюсов встроенных ассоциативных массивов.

Кстати, да - объявление массивов в 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# интерфейс отдельным типом? Можно ли там создать переменную с типом интерфейса?

Добавлено
Цитата D_KEY @
А я typedef'ы использую. В D бы тоже использовал.
Зачем? string[int] выглядит очень наглядно и понятно.

Автор: OpenGL 11.02.14, 10:01
Цитата applegame @
Можно ли там создать переменную с типом интерфейса?

Создать где? В шарпе вроде как в интерфейсах вообще полей не можкт быть - только методы. А если ты имеешь ввиду IFoo tmp = new Derived(), то да, конечно.

Автор: applegame 11.02.14, 10:05
Цитата D_KEY @
Но зачем же наделять интерфейсы свойствами абстрактных базовых классов? Так, пожалуй, их проще реализовать. Но это не аргумент.
Можно попытаться ответить на этот вопрос. Рассмотрим код:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    interface IFoo {
        void g();
    }
     
    class Base {
        void g();
    }
     
    class Derived : Base, IFoo {
    }
     
    ...
     
    IFoo b = new Derived;
    b.g();
Функция IFoo.g() - фактически виртуальная функция. Класс Base вообще ничего не знает об IFoo и Base.g() вообще может быть реализована в стороннем модуле чужим дядей. Ну и как компилятор должен выкручиваться из такой ситуации? Автоматически создать в Derived виртуальную функцию g(), в которой автоматически же вставить вызов базовой функции из Base?

Добавлено
Цитата OpenGL @
А если ты имеешь ввиду IFoo tmp = new Derived(), то да, конечно.
Да, я это имел ввиду. Но смотри выше.

Автор: OpenGL 11.02.14, 10:08
Цитата applegame @
Ну и как компилятор должен выкручиваться из такой ситуации?

Выдать ошибку компиляции :D Ты же не указал, что Derived реализует IFoo.

Автор: D_KEY 11.02.14, 10:08
Цитата D_KEY @
Кстати, мне попадался на глаза какой-то фичебаг с alias'ами в D... Вспомнить бы...

Кажется, вспомнил. 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
Цитата OpenGL @
Выдать ошибку компиляции :D Ты же не указал, что Derived реализует IFoo.
Я уже поправил :P

Добавлено
Цитата D_KEY @
При этом ref является частью типа функции, например.
Ситуация со ссылками в D мне тоже не нравится. ref почему-то не является частью типа. Например, нельзя создать переменную-ссылку. Не знаю зачем так сделали, но мне не мешает.

Автор: D_KEY 11.02.14, 10:43
Цитата applegame @
Ситуация со ссылками в D мне тоже не нравится. ref почему-то не является частью типа. Например, нельзя создать переменную-ссылку. Не знаю зачем так сделали, но мне не мешает.

Так а чего он не ругается на alias с ref, а просто делает какую-то фигню? И почему ref является частью типа возвращаемого значения? ;)

Автор: applegame 11.02.14, 10:49
Цитата D_KEY @
Так а чего он не ругается на alias с ref, а просто делает какую-то фигню?
А почему фигню? "alias ref int ref_int;" полностью аналогичен "alias int ref_int;" сейчас уже, кстати можно писать "alias ref_int = int;".
Цитата D_KEY @
И почему ref является частью типа возвращаемого значения? ;)
Нет, не является. Скорее это некий флажок для компилятора. Если функция возвращает ссылку и ты ее присвоишь переменной с типом auto, то будет создана обычная переменная, а не ссылка.

Но вообще, я согласен с тобой, и в свое время задавал аналогичные вопросы на оффоруме. Там сказали, что-то вроде - ну вот так сделано. :) ref также не являясь частью типа умудряется все же быть частью сигнатуры функции :)
С другой стороны, как я уже сказал, это не мешает и представляет скорее академический интерес, чем практический.

Окай. Перейду к другой части мерлезонского балета. А именно, возможность использовать строковые литералы (и вообще любые строки вычисляемые compile-time) в шаблонах.
В качестве стратегий: http://dpaste.dzfl.pl/adb455e76a45
В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26

Добавлено
На всякий случай сообщаю, что
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    class Container(string type) {
    }
примерно как (хотя в C++ это невозможно)
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    template<string type>
    class Container {
    };

Автор: D_KEY 11.02.14, 10:56
Чего окай-то? :D мне вот подобных косяков со ссылками и интерфейсами уже достаточно. Наверняка там ещё есть :(

Автор: applegame 11.02.14, 11:01
Цитата D_KEY @
Чего окай-то? :D
Ну а что дальше? Этот вопрос рассмотрен и закрыт или у тебя еще есть вопросы? :D Кстати ты не ответил на пост про интерфейсы.
Цитата 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
Цитата applegame @
Я не знаю, является ли в C# интерфейс отдельным типом?
является. interface - ключевое слово
Цитата applegame @
Можно ли там создать переменную с типом интерфейса?
Это ссылка. Почему нет?

Добавлено
Цитата applegame @
В D например для компиляции под разные ОС, не нужно никаких внешних инструментов, все встроено в язык
Так и препроцессор в C/C++ встроен в язык. :D

Автор: applegame 11.02.14, 11:46
Цитата trainer @
Так и препроцессор в C/C++ встроен в язык. :D
Ну и как при помощи только лишь препроцессора узнать тип ОС? :)

Автор: MyNameIsIgor 11.02.14, 11:47
Цитата applegame @
встроенные ассоциативные массивы

Никаких преимуществ перед библиотечными, одни минусы: ни хэш не задать, ни аллокатор.
Цитата applegame @
тип real (идеален для математических вычислений)

Чем он так идеален, что в мире плюсов нет ничего похожего?
Цитата applegame @
мощный и в тоже время простой синтаксис шаблонов

Эти !() просто ужасны и нечитаемы. Следовало идти по пути Scala. И да, что такое "мощный синтаксис" - моя не понимайт.
Цитата applegame @
примеси (mixins)

Костыль при отсутствии множественного наследования.
Цитата applegame @
отсуствие необходимости в заголовочных файлах (это свобода, вы плюсовики, просто не знаете как это прекрасно)

Пишу на C#, Java, C++, Objective-C - я люблю заголовочные файлы. ЧЯДНТ?
Цитата applegame @
Настоящая условная компиляция в зависимости от ключей в командной строке, процессора, кода, версии и т.п.

Препроцессор не менее настоящий. Но то, что static if - часть языка, что плюс, да.
Цитата applegame @
настоящий CTFE, вплоть до compile-time импорта в строку и парсинга файла в код на D

Парсинг из строки - это убожество. Александреску преподносит это как манну небесную, но мне абсолютно непонятно для чего использовать строки, если нужно записывать код - должна быть нормальная возможность описать AST в стандартном синтаксисе языка, как это сделано в макросах Nemerle.
Цитата applegame @
встроенные делегаты

Как и было доказано, они не нужны.
Цитата applegame @
нормальные лямбды, тип которых зависит напрямую от сигнатуры, а не как компилятор на душу положит. Кроме того имеется прекрасный сокращенный стиль их написания

Т.е. встроенная в язык std::function, но опять таки без возможности параметризации аллокатором.
А т.к. тип зависит только от сигнатуры, то прощай тотальное встраивание. Не нужно.
Цитата applegame @
встроенный TLS (thread local storage) - это реально круто

Есть и в C++11. Другое дело, что в D надо наоборот указывать тот факт, что переменная глобальная - в этом плюс есть, да.
Цитата applegame @
встроенный compile-time reflection

Полезно. Вроде как обсуждается к C++17.
Цитата applegame @
сборщик мусора, к тому же еще и не самый продвинутый

Он не то, что не самый продвинутый...Он самый убогий :D Потому что для такого языка возможен лишь консервативный сборщик. Сейчас используется boehmgc... который вообще-то для C/C++ :lol:
А в итоге в D наличие сборщика привёло к большой путанице с деструкторами и переопределёнными new/delete - это fail.


Вообще, D протух ещё до выхода. Когда-то давно я тоже в него верил, но потом разочаровался и понял: D - это говно, очень вонючее говно. Многие из тех, то его тогда поддерживал, сейчас смотрят на Rust или Go.
D_KEY, помнишь, ты даже хотел на форуме подраздел создать, чтобы обсудить D? :) Посмотрел по личным сообщения - 2009 год был :)

Ну, и правильные посты про D.

Автор: trainer 11.02.14, 11:53
Цитата applegame @
Ну и как при помощи только лишь препроцессора узнать тип ОС?
Вот так: 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 @
Objective-C

Как оно, кстати? :)

Автор: MyNameIsIgor 11.02.14, 11:57
Цитата D_KEY @
Как оно, кстати?

Кстати, нормально. Не хуже D :lol:

Автор: D_KEY 11.02.14, 11:58
Цитата MyNameIsIgor @
D_KEY, помнишь, ты даже хотел на форуме подраздел создать, чтобы обсудить D? :) Посмотрел по личным сообщения - 2009 год был :)

Ага :)

Цитата
Многие из тех, то его тогда поддерживал, сейчас смотрят на Rust или Go.

Но и они что-то не очень радуют.

Добавлено
Цитата applegame @
Кстати ты не ответил на пост про интерфейсы

Пропустил, наверное. Ты о чем?

Добавлено
Цитата applegame @
Но тем не менее, почему-то меня не тянет назад на плюсы.

А тебя никто и не тянет ;)

Автор: applegame 11.02.14, 12:07
Кстати, дела идут гораздо лучше, чем год назад и D стремительно обрастает библиотеками: http://code.dlang.org/
Я пытался несколько раз переползти с C++ на D и каждый раз неудачно: плюясь и ругаясь возвращался к плюсам. Но вот последний раз наконец-то D достиг устраивающего меня уровня. Я не отношусь к тем адептам, которые загорелись, а через неделю прогорели и все забросили.
Я уже практически полгода пилю относительно большой коммерческий веб-проект (заодно по мере возможности участвую в разработке vibe.d), с относительно высокой посещаемостью (первая версия работает прямо сейчас на рубях). Как только я его закончу, обязательно покажу. Будет вам саксесс-стори. :)

Автор: MyNameIsIgor 11.02.14, 12:13
Цитата applegame @
веб-проект

Так это вам не с C++ надо будет тягаться, а со всякими Python/Ruby/C#/Scala/Clojure/Go. Вот им и расскажете про успех, а плюсы на веб не претендуют.

Автор: D_KEY 11.02.14, 12:14
Что-то "убийцы" С++ в вебе применяются, с Go та же история.

Автор: MyNameIsIgor 11.02.14, 12:24
Цитата D_KEY @
Что-то "убийцы" С++ в вебе применяются

Ну, именно поэтому ты и написал в кавычках :)

Автор: 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
Цитата korvin @
чтобы найти весь платформозависимый код.

А если у меня зависимость от версии ОС, архитектуры, конкретной POSIX'овой или SUS-константы?

Автор: applegame 11.02.14, 12:31
Цитата korvin @
И грепать содержимое кучи сырцов не надо, чтобы найти весь платформозависимый код.
Никто не мешает разбить код на отдельные модули для каждой платформы, а затем при помощи version импортировать уже нужные части в зависимости от платформы сборки.

Автор: MyNameIsIgor 11.02.14, 12:34
Цитата applegame @
А вообще D используют такие гиганты геймдева, как Remedy Games. Не как основной, а вспомогательный для обработки игровой логики

В геймдеве вообще проблемы с тем, на чём пилить игровую логику. А причина проста - нет строго статически типизированного языка, который был бы столь же выразителен, как сриптовые динамические, кроссплатформенный и при этом легко встраивался в приложение. К C++ сей "успех" не имеет никакого отношения.

Автор: applegame 11.02.14, 12:39
Цитата D_KEY @
А если у меня зависимость от версии ОС, архитектуры, конкретной POSIX'овой или SUS-константы?
Архитектуру тоже можно определить через version. А версия ОС, во время сборки? Спрашивается нафига?

Автор: OpenGL 11.02.14, 12:42
Цитата MyNameIsIgor @
А в итоге в D наличие сборщика привёло к большой путанице с деструкторами и переопределёнными new/delete - это fail.

Кстати, что с ними в D? Считал, что там есть нормальные деструкторы как в плюсах. Это неверно?

Автор: D_KEY 11.02.14, 12:43
Цитата applegame @
А версия ОС, во время сборки? Спрашивается нафига?

Внезапно, в разных версиях могут быть разные API(если мы о винде) или разная степень и подход к реализации стандартов(если мы о *nix).

Автор: applegame 11.02.14, 12:44
Цитата OpenGL @
Кстати, что с ними в D? Считал, что там есть нормальные деструкторы как в плюсах. Это неверно?
Неверно. Деструкторы есть, но используются они гораздо реже, чем в C++.

Автор: 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 @
Ну т.е. в итоге получится тоже самое, что и в Go, только с добавочным костылем в языке, ОК.
Это смотря с какой стороны смотреть. С одной стороны костыль, с другой стороны гибкость. Кроме того version позволяет условно компилять не только в зависимости от платформы, но и как классический #ifdef в зависимости от аргументов командной строки, или в зависимости от режима debug/release и т.п.

Добавлено
Для объектов созданных с помощью 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, например. Может и это в язык сунуть? :D

Автор: applegame 11.02.14, 13:19
Цитата korvin @
Да-да, и снова греп и каша в сорцах... =)
А как по другому? :) Отдельные файлы с исходниками для дебаг-версии, отдельно для релиз? :D

Автор: MyNameIsIgor 11.02.14, 13:19
Цитата korvin @
Да-да, и снова греп и каша в сорцах... =)

Согласен, кстати. Воюю со всеми, в том числе и с коллегами, пытаясь объяснить, что это всё - задача системы сборки и не должно быть с исходниках. Они же должны быть разложены по директориям, а вместо #ifdef должны использоваться либо порождающие паттерны, либо языковые механизмы типа одного .h и по .cpp на конкретную реализацию.
Война проигрывается :(

Автор: applegame 11.02.14, 13:20
Цитата D_KEY @
Может и это в язык сунуть? :D
Вообще в D вставлено ровно две вещи: тип OS и архитектура, остальное внешними ключами.

Автор: MyNameIsIgor 11.02.14, 13:21
Цитата applegame @
А как по другому?

Вот, ещё один...
Цитата applegame @
Отдельные файлы с исходниками для дебаг-версии, отдельно для релиз?

А у вас разный код исполняется в debug и в realese? :wacko: Тогда тестирование debug версии не имеет смысла - у клиента будет работать другой код.

Автор: applegame 11.02.14, 13:23
Цитата MyNameIsIgor @
А у вас разный код исполняется в debug и в realese? :wacko:
В релиз версии не выполняются некоторые проверки, которые делаются в дебаг-версии. Так что код, да, слегка различается.

Добавлено
Продолжаем тему используемости 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
Цитата applegame @
начала миграцию игрового бэкенда с NodeJS на D.

Не удивительно, с 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
Цитата D_KEY @
Хм. Не очень себе это представляю в header only библиотеке, например.

Настройка путей include'а.

Автор: D_KEY 11.02.14, 13:47
Цитата MyNameIsIgor @
Цитата D_KEY @
Хм. Не очень себе это представляю в header only библиотеке, например.

Настройка путей include'а.

В системе сборки? Ну можно, в принципе, да. Но это придется делать каждому пользователю библиотеки.

Автор: applegame 11.02.14, 13:48
Далее.
Sociomatic Labs специализируется на, хз как это перевести - real-time bidding for online display advertising. Вся их кодовая база написана на D. Правда, справедливости ради, надо отметить что на D1/Tango.

Автор: korvin 11.02.14, 13:50
Цитата D_KEY @
Но это придется делать каждому пользователю библиотеки.

Почему же? Система сборки не может определить текущую ОС и архитектуру?

Автор: applegame 11.02.14, 13:53
EMSI компания занимающаяся моделированием экономики. На D написана высокопроизводительный экономический симулятор и некоторый инструментарий. На данный момент продолжают мигрировать на D и планируют полностью перейти на него.

Автор: MyNameIsIgor 11.02.14, 13:54
Цитата applegame @
На D написана высокопроизводительный

Как определили, что он высоко производительный?

Автор: D_KEY 11.02.14, 13:55
Цитата korvin @
Цитата D_KEY @
Но это придется делать каждому пользователю библиотеки.

Почему же? Система сборки не может определить текущую ОС и архитектуру?

Ну да, в принципе, можно именно полностью управлять точным набором хидеров и ставить только их, если ты об этом. И для текущей ОС и архитектуры это не будет большой проблемой, но вот всякие флаги компиляции и конфигурации(boost.config например)... В общем случае, как мне кажется, это не сделать. Но во многом я с вами согласен.

Добавлено
Цитата applegame @
real-time bidding for online display advertising

Торги реального времени для показа рекламы :) Это известная шляпа, система для проведения аукциона между рекламными сетями.

Автор: applegame 11.02.14, 14:03
Эй, не отклоняемся от темы. :)

Автор: MyNameIsIgor 11.02.14, 14:05
Цитата D_KEY @
В общем случае, как мне кажется, это не сделать

Да, в общем случае для плюсовых header only библиотек этого не сделать. Но даже если #ifdef будет только вокруг #include, будет уже хорошо.

Добавлено
Цитата applegame @
Эй, не отклоняемся от темы

А в чём состоит тема? Чтобы показать в лучшем случае несколько десятков проектов на D против стопитсот проектов на C++?

Автор: Wound 11.02.14, 14:08
Цитата MyNameIsIgor @
Но даже если #ifdef будет только вокруг #include, будет уже хорошо.

Ой как меня тоже бесят, как некоторые любят кучу дефайнов трехэтажных намудрить, а потом когда все это глючит, охото найти и оторвать руки писавшему...

Автор: 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

Автор: D_KEY 11.02.14, 14:17
Цитата applegame @
А некоторые еще любят замутить такие вложенные замороченные макросы, что потом когда вылезает ошибка компиляции, приходится мучительно искать, где-же именно это говно вылезло. Ведь компилер бодренько показывает строку в которой макрос был задействован. Это к вопросу D_KEY, почему макросы говно. А потому, что препроцессор - тупой, а компилятор - умный. Поэтому замена препроцессора компилятором - отличная идея. Но упоротые "старики" будут гнуть свое, хотя практически все учебники по C++ говорят одно и тоже: макросы - зло. :D

Совсем этим я согласен как раз. Мы тогда говорили о выигрыше при переходе с C++ на D.

Автор: Wound 11.02.14, 14:18
Цитата applegame @
А некоторые еще любят замутить такие вложенные замороченные макросы, что потом когда вылезает ошибка компиляции, приходится мучительно искать, где-же именно это говно вылезло. Ведь компилер бодренько показывает строку в которой макрос был задействован. Это к вопросу D_KEY, почему макросы говно. А потому, что препроцессор - тупой, а компилятор - умный. Поэтому замена препроцессора компилятором - отличная идея. Но упоротые "старики" будут гнуть свое, хотя практически все учебники по C++ говорят одно и тоже: макросы - зло.

Макросы зло - когда ими злоупотребляют. Когда их используют вместо банальных констант, когда ими пытаются выражение на 5 строчек реализовать макросом в одну строчку, странно почему не функцией и т.д. А так то макросы сами по себе нормальные. Просто есть макрофанаты отдельные...

Автор: applegame 11.02.14, 14:18
Цитата MyNameIsIgor @
Неинтересно. Для небольших проектов хоть Brainfuck прокатит.
Сами пишите на Brainfuck. А мелкие вспомогательные тулзины крутятся вокруг любого крупного проекта.

Автор: D_KEY 11.02.14, 14:19
Цитата applegame @
А мелкие вспомогательные тулзины крутятся вокруг любого крупного проекта.

Так они на каких-нибудь питонах, как правило.

Автор: Wound 11.02.14, 14:22
applegame, вот ты там писал гдето про GC и деструкторы, мол для структор что на стэке - обычные деструкторы, а в остальном GC. А как эта солянка вместе работает? Вот например что там в плане исключений? finally какие нибудь писать нужно? или как?

Автор: MyNameIsIgor 11.02.14, 14:23
Цитата D_KEY @
Цитата applegame @
А мелкие вспомогательные тулзины крутятся вокруг любого крупного проекта.

Так они на каких-нибудь питонах, как правило.

+1
Есть куча языков, на которых можно сделать мелкие тулзы, и языки эти знает куча народу. Зачем мне D?

Автор: applegame 11.02.14, 14:23
Цитата Wound @
Макросы зло - когда ими злоупотребляют. Когда их используют вместо банальных констант, когда ими пытаются выражение на 5 строчек реализовать макросом в одну строчку, странно почему не функцией и т.д. А так то макросы сами по себе нормальные. Просто есть макрофанаты отдельные...
Да, но самое интересное, что главное преимущество препроцессора - это как раз городить костыли, которые нормальным способом не сделать. Например Boost.Foreach. В остальных случаях он не нужен при достаточной поддержке языка. В том же D, например.

Автор: applegame 11.02.14, 14:32
Цитата D_KEY @
Так они на каких-нибудь питонах, как правило.
Я не знаю питона и изучать его нет никакого желания. Я использую D.
Цитата Wound @
applegame, вот ты там писал гдето про GC и деструкторы, мол для структор что на стэке - обычные деструкторы, а в остальном GC. А как эта солянка вместе работает? Вот например что там в плане исключений? finally какие нибудь писать нужно? или как?
Все нормально работает. finally - в D нет и он там не нужен. При выходе из 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) {
        ...
      }
    }

Автор: Wound 11.02.14, 14:37
Цитата applegame @
Я не знаю питона и изучать его нет никакого желания.

Да его изучать и не приходится както, просто берешь и пишешь как тебе нравится и все ))

Автор: MyNameIsIgor 11.02.14, 14:38
Цитата applegame @
finally - в D нет

Лолшто?
Цитата
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

Цитата applegame @
и он там не нужен

Ага, не нужен. Но в D нет общей идеи, это просто бессистемный набор фич.

Автор: D_KEY 11.02.14, 14:39
Цитата applegame @
finally - в D нет

Есть

Автор: 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 @
Есть
Да, ты прав, есть. Я был уверен, что нет :)

Автор: D_KEY 11.02.14, 14:43
Цитата applegame @
Цитата D_KEY @
Есть
Да, ты прав, есть. Я был уверен, что нет :)

Не нужен, но есть. Прямо как сам D.

Автор: applegame 11.02.14, 14:44
Цитата D_KEY @
Кстати, мне кажется, что D очень удобен для холиваров. Можно мимикрировать под разные языки.
Холивара не получается. Всем насрать хорош или плох C++, всем важно насколько плох D. :D
Я привел два примера в чем D однозначно переплюнул C++, но всем пофиг. :)

Автор: Wound 11.02.14, 14:44
Цитата applegame @
Все нормально работает. finally - в D нет и он там не нужен.



Вызовутся ли эти деструкторы в случае, если сработает 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 @
Кстати, мне кажется, что D очень удобен для холиваров. Можно мимикрировать под разные языки.
Холивара не получается. Всем насрать хорош или плох C++, всем важно насколько плох D. :D

Так ты с первого сообщения оборонительную позицию занял. Чего ты ждал? :D

Автор: MyNameIsIgor 11.02.14, 14:45
Цитата applegame @
Я привел два примера в чем D однозначно переплюнул C++

Эммм... Где?

Автор: D_KEY 11.02.14, 14:46
Цитата applegame @
Я привел два примера в чем D однозначно переплюнул C++, но всем пофиг. :)

Про строки в параметрах шаблонов тебя спросили зачем, а рефлексия во время компиляции вроде как все нравится. Проблема в том, что она легко может появиться в C++ :)

Автор: applegame 11.02.14, 14:48
Цитата Wound @
Вызовутся ли эти деструкторы в случае, если сработает GC и/или вызовется ли GC при выходе из этих scope'ов 146% ?
GC не занимается объектами на стеке. Для них вызовутся 146%. Для объектов созданных при помощи new, нет. Они будут жить и после выхода из функции как минимум до тех пор пока в программе есть ссылки на них. После того как все ссылки исчезли, деструктор вызовется, когда GC соблагоизволит прибить данный объект. Это может случиться когда угодно. Поэтому деструктор для классов, как правило бесполезен.

Автор: D_KEY 11.02.14, 14:48
И да, ты мне там писал, что я не ответил про интерфейсы, а я не нашел.

Автор: korvin 11.02.14, 14:49
Цитата applegame @
Я привел два примера в чем D однозначно переплюнул C++, но всем пофиг.

Наверное на любом языке можно привести пару примеров, в чем этот язык переплюнет плюсы, так что не очень интересно. Вот если бы D хотя бы в половине случаев однозначно переплевывал плюсы, было бы интересней. =)

Автор: applegame 11.02.14, 14:50
Цитата D_KEY @
Про строки в параметрах шаблонов тебя спросили зачем
Я там привел, два примера, повторю:
В качестве стратегий: 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 - это убожество, есть следующие вопросы
Цитата applegame @
В качестве стратегий: http://dpaste.dzfl.pl/adb455e76a45

Чем это лучше задания типа-стратегии?
Цитата applegame @
В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26

Чем это лучше просто передачи функтора в find?

Добавлено
Цитата korvin @
Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы?

Потому что для D возможен лишь консервативный сборщик.

Автор: applegame 11.02.14, 14:55
Цитата korvin @
Вот если бы D хотя бы в половине случаев однозначно переплевывал плюсы, было бы интересней. =)
Он в большинстве случаев не хуже, а во многом лучше. Я поставлю пару простых задач, тут сидят плюсовики посмотрим, как они их решат, на C++. И сравним, какое решение изящней.
Цитата korvin @
Обычно же GC копируют достижимые объекты, а не «прибивают» недостижимые, зачем тратить на это время и другие ресурсы?
Зачем и куда копировать достижимые ресурсы? Сразу предупреждаю, я не очень большой специалист в алгоритмах работы GC.

Автор: MyNameIsIgor 11.02.14, 14:56
Цитата applegame @
Зачем и куда копировать достижимые ресурсы?

Как минимум сдвигать для борьбы с фрагментацией.

Автор: korvin 11.02.14, 14:57
Цитата applegame @
Я там привел, два примера, повторю:

Как-то странно смотреть на это строко-ковыряние при наличии compile-time рефлексии и «значительно более мощных возможностей метапрограммирования».
Разработчики D фанаты тикля что ли?

Автор: applegame 11.02.14, 14:59
Цитата MyNameIsIgor @
Потому что для D возможен лишь консервативный сборщик.
Есть два проекта более продвинутых сборщиков для D:A Precise Garbage Collector for DConcurrent Garbage Collection for DНе знаю, являются ли они консервативными, но более продвинутыми точно.

Автор: korvin 11.02.14, 15:02
Цитата applegame @
В C++ для этого юзают классы-пустышки, что является ничем иным, как костылем.

Вообще-то в плюсах теперь, как и во всех нормальных языках для этого используются лямбды теперь. Ты вот скажи, то строковое выражение что, компилируется в рантайме? Или как оно работает?

Цитата applegame @
Зачем и куда копировать достижимые ресурсы? Сразу предупреждаю, я не очень большой специалист в алгоритмах работы GC.

Это основа работы практически всех (полноценных) GC: http://en.wikipedia.org/wiki/Garbage_colle..._vs._non-moving

Автор: D_KEY 11.02.14, 15:04
Цитата applegame @
В качестве стратегий: http://dpaste.dzfl.pl/adb455e76a45

Ну это не стратегия, а имя стратегии. В плюсах можно использовать типы-теги, например или еще что-то такое.

Цитата
В качестве предикатов: http://dpaste.dzfl.pl/30cb1cd23e26

В сложных случаях будет запутано(и вообще интуитивно мне кажется это очень странной фичей), в обычных можно сделать на шаблонах и constexpr.

Автор: korvin 11.02.14, 15:07
Цитата korvin @
Или как оно работает?

Реализацию метода 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
Цитата applegame @
Эдакий синтаксический сахарок, для простеньких предикатов

korvin, как ты считаешь, нужно ли такой "сахарок", прости за выражение, сделать в CL: будем парсить sexp прямо из строки? :whistle:

Автор: 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...);
    }

Оно?

Добавлено
Цитата applegame @
Итеративно, насколько я знаю в плюсах вообще невозможно сделать

А зачем?

Автор: korvin 11.02.14, 15:41
Цитата applegame @
Два решения на D, итеративное и рекурсивное:

Хотелось бы посмотреть, как ты будешь строить список bb динамически, из пользовательского ввода например.

Автор: applegame 11.02.14, 15:43
Цитата korvin @
Что, без макросов слишком медленно компилируется после плюсов?
Не понимаю, к чему это? DMD, кстати компилирует гораздо быстрее GCC. Одна из фишек D - быстрая компиляция.
Цитата korvin @
В чем проблема просто сделать удобный синтаксис для лямбд?
Он есть. Я повторяю, это просто синтаксический сахар. Не нравится - не юзай. Но сама возможность доставляет. Вот вариант с лямбдой: http://dpaste.dzfl.pl/f13179c43403
Кстати как в плюсиках создать подобную шаблоннуя inline-лямбду? Никак, только городить отдельный шаблонный предикат?

Автор: MyNameIsIgor 11.02.14, 15:44
Цитата D_KEY @
А зачем?

D_KEY, ты и показал итеративное решение :rolleyes: И для него не нужен компилятор с поддержкой оптимизации хвостовой рекурсии.

Добавлено
Цитата korvin @
Вот только там это делать не за чем, да и не рекомендуется. =)

Что я и говорю :)

Автор: applegame 11.02.14, 15:48
Цитата D_KEY @
Оно?
Оно, задача была проста. Но теперь сравниваем код, для D и для C++ и смотрим, что наглядней, легче для понимания и проще в написании. В плюсях пришлось городить отдельную вспомогательную функцию, как я и думал.

Автор: D_KEY 11.02.14, 15:49
Цитата MyNameIsIgor @
Цитата D_KEY @
А зачем?

D_KEY, ты и показал итеративное решение :rolleyes: И для него не нужен компилятор с поддержкой оптимизации хвостовой рекурсии.

Это как посмотреть :) Определение-то рекурсивное. То, что рекурсивного вызова в рантайме нет - это уже другой разговор. Мне интересно, зачем итеративное определение в такого рода вещах.

Автор: applegame 11.02.14, 15:50
Цитата korvin @
Хотелось бы посмотреть, как ты будешь строить список bb динамически, из пользовательского ввода например.
Зачем? Это разве входило в условия задачи? Динамически только значения можно передавать. А длина и типы зафиксированы compile-time.

Автор: MyNameIsIgor 11.02.14, 15:51
Цитата D_KEY @
Это как посмотреть Определение-то рекурсивное.

Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном.

Автор: 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...);
    }


Для меня второй вариант проще :) Хотя тут разницы-то нет.

Цитата
пришлось городить отдельную вспомогательную функцию, как я и думал.

Почему вспомогательную? Это функция, которая берет два аргумента разных типов и сравнивает их :D

Автор: applegame 11.02.14, 15:52
Цитата D_KEY @
Мне интересно, зачем итеративное определение в такого рода вещах.
Иногда оно проще в реализации. С точки зрения эффективности разницы никакой.

Автор: D_KEY 11.02.14, 15:53
Цитата MyNameIsIgor @
Цитата D_KEY @
Это как посмотреть Определение-то рекурсивное.

Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном.

Ага. А в D второй вариант вырождается именно в рекурсивные функции?

Автор: MyNameIsIgor 11.02.14, 15:55
Цитата D_KEY @
А в D второй вариант вырождается именно в рекурсивные функции?

Насколько я знаю, нет, тоже итеративный, не дженерики же :) Просто applegame не до конца понимают семантику того кода, который сам и написал :)

Автор: korvin 11.02.14, 15:59
Цитата applegame @
Не понимаю, к чему это? DMD, кстати компилирует гораздо быстрее GCC. Одна из фишек D - быстрая компиляция.

Там опечатка, поправил.

Цитата applegame @
Но сама возможность доставляет

Возможность сделать код непонятным? Кстати, как там с коллизией имен? Если внутри 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))

:P

Добавлено
Цитата applegame @
Зачем? Это разве входило в условия задачи? Динамически только значения можно передавать. А длина и типы зафиксированы compile-time.

Ну так не интересно.

Автор: D_KEY 11.02.14, 16:00
Цитата korvin @
Конечно хаскелл

Только это другая задача :)

Добавлено
Я вот совсем не знаю template haskell. Там никак во время компиляции не сделать?

Автор: applegame 11.02.14, 16:05
Цитата D_KEY @
Ага. А в D второй вариант вырождается именно в рекурсивные функции?
В debug-режиме, как правило да, как и в GCC например. В release оно разворачивает рекурсию, естественно. Я прекрасно знаю, что такое хвостовая рекурсия.

Автор: Wound 11.02.14, 16:06
Цитата D_KEY @
Для меня второй вариант проще Хотя тут разницы-то нет.

Ну да, он же там три строчки то съэкономил, пожалел места :D В принципе так то и выходит что разницы нет =)

Автор: korvin 11.02.14, 16:06
Цитата D_KEY @
Я вот совсем не знаю template haskell. Там никак во время компиляции не сделать?

Там много чего можно, это ж вроде почти как макросы CL, только типизированные. Т.е. наверное правильней сказать «как в Nemerle».
Только в чем сакральный смысл? Часто ты таким образом сравниваешь значения? Обычно, если их довольно много, то это рантайм-коллекция и всё придется делать в рантайме, а если мало, то овчинка выделки не стоит, обход массива в пяток значений просто копеечен по стоимости.

Автор: applegame 11.02.14, 16:07
Цитата MyNameIsIgor @
Просто applegame не до конца понимают семантику того кода, который сам и написал :)
Ошибаешься. Посему тебе, лично - до свидания, не скучай ;)

Автор: MyNameIsIgor 11.02.14, 16:09
Цитата applegame @
В debug-режиме, как правило да, как и в GCC например

Какая может быть рекурсия, если вызывается другая функция? :wacko:
Цитата applegame @
В release оно разворачивает рекурсию

Не разворачивает рекурсию, а инлайнит вызовы других функций.
Цитата applegame @
Я прекрасно знаю, что такое хвостовая рекурсия.

Серьёзно? Я не заметил...

Автор: applegame 11.02.14, 16:09
Цитата Wound @
Ну да, он же там три строчки то съэкономил, пожалел места :D В принципе так то и выходит что разницы нет =)
Дык это только начало. :)

Автор: D_KEY 11.02.14, 16:09
Цитата applegame @
Цитата MyNameIsIgor @
Просто applegame не до конца понимают семантику того кода, который сам и написал :)
Ошибаешься. Посему тебе, лично - до свидания, не скучай ;)

Рано прощаешься, похоже, что он прав :)

Добавлено
Цитата MyNameIsIgor @
Цитата applegame @
Я прекрасно знаю, что такое хвостовая рекурсия.

Серьёзно? Я не заметил...

Господа, при чем тут вообще хвостовая рекурсия сейчас? Давайте лучше холивар продолжим.

Автор: applegame 11.02.14, 16:15
Цитата korvin @
Кстати, как там с коллизией имен? Если внутри find уже будет переменная с именами «a» или «b» такого же типа, что и твои параметры?
Ты о каких a и b. Вот этих?
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    find!((a, b) => a.key == b)(foo, 1);
Это переменные локальные для самой лямбды, внутренности find не имеют к ним никакого отношения. Не нравятся a и b, используй другие имена, главное два аргумента и возвращение значения, которое может быть неявно приведено к bool.

Автор: 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);


Добавлено
Цитата D_KEY @
korvin, это не макросы. Совсем.

Это не значит, что они могут самостоятельно решить, вызывать предварительно foo(), или нет.

Автор: applegame 11.02.14, 16:20
Цитата D_KEY @
Рано прощаешься, похоже, что он прав :)
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 @
с функциональной точки зрения isOneOf

Что такое "функциональная точка зрения"?
Цитата applegame @
isOneOf в дешном варианте - одна функция с переменным числом аргументов

Нет, ибо она параметризуется их типами. И потому это не просто переменное число аргументов - инстанцирование приводит к разным функциям хотя бы из-за проверки типов.

Автор: applegame 11.02.14, 16:27
Цитата D_KEY @
Кстати, именно это как раз деталь реализации, даже если так D делает. А вот семантически там как раз совершенно разные вызовы. Разве нет?
Нет D так не делает. Это будут разные функции. Так как CTFE, то фактически рекурсия разворачивается в итеративный вариант (с foreach) с последующим разворачиванием цикла в последовательность проверок.
Оторвитесь уже, блджад, от плюсов. Представьте это математически: одна функция, рекурсивная, с переменным числом аргументов, вызывает сама себя.

Автор: MyNameIsIgor 11.02.14, 16:28
Цитата applegame @
рекурсия разворачивается

Так а где здесь рекурсия то? :rolleyes:

Автор: D_KEY 11.02.14, 16:28
Цитата applegame @
Цитата D_KEY @
Кстати, именно это как раз деталь реализации, даже если так D делает. А вот семантически там как раз совершенно разные вызовы. Разве нет?
Нет D так не делает. Это будут разные функции.

Значит, нет и рекурсии.

Автор: MyNameIsIgor 11.02.14, 16:29
Цитата applegame @
Представьте это математически: одна функция, рекурсивная

Мы представили. Математически мы не видим одной функции, мы видим метафункцию (шаблон), порождающую разные функции.

Добавлено
Метафункция рекурсивна, да. Порождённые ею функции - нет.

Автор: 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 @
Цитата D_KEY @
korvin, это не макросы. Совсем.

Это не значит, что они могут самостоятельно решить, вызывать предварительно foo(), или нет.

Или «имеют право решать».

Пример, конечно, надуманый, но всякое ведь бывает. =)

Автор: D_KEY 11.02.14, 16:43
Цитата korvin @
но всякое ведь бывает.

В 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
Цитата applegame @
Вот специально для вас. Тут будет ровно одна функция, вызывающая сама себя

Тут да. Потому что здесь нет зависимости аргументов шаблона от аргументов функции. Это есть шаблон функции с переменным числом параметров.
А вот это
<{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
Цитата applegame @
Факт в том, что я прекрасно знаю, что такое разворачивание хвостовых рекурсий

Только её здесь нет :jokingly:

Автор: D_KEY 11.02.14, 17:09
Цитата applegame @
Вообще это фактически пошел холивар терминов. Факт в том, что я прекрасно знаю, что такое разворачивание хвостовых рекурсий, как именно работают шаблонные функции, как они инлайнятся (зависит от компилятора и от опций компиляции). Если кто считает, что я в этом деле профан - ваше право так думать и заявлять об этом, а мое право сказать вам: "до свидания".
А я тем временем вернусь к основному холивару и подгоню более сложную задачу.

А ты мог бы ответить на вопрос korvinа по поводу кода из строки и аргументов/захвата?

Автор: applegame 11.02.14, 17:16
Цитата MyNameIsIgor @
applegame, можно ли в D сделать такую проверку? (грязный хак, знаю)
Так устроит? http://dpaste.dzfl.pl/1e63ac0de3b5
Цитата D_KEY @
А ты мог бы ответить на вопрос korvinа по поводу кода из строки и аргументов/захвата?
На что-то я уже отвечал, процитируй вопрос еще раз.

Автор: korvin 11.02.14, 17:19
Цитата applegame @
На что-то я уже отвечал, процитируй вопрос еще раз.

D vs C++ (сообщение #3413091)

Добавлено
Цитата applegame @
Так устроит? http://dpaste.dzfl.pl/1e63ac0de3b5

Я думаю, Игорь имел в виду эту проверку: http://dpaste.dzfl.pl/7ee97716f99f

Автор: applegame 11.02.14, 17:28
Цитата korvin @
Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром?
А, если предикат задан строкой, то имена жестко зафиксированы за "a" и "b". Дело в том, что D умеет компилировать выражение в строке (конечно, только если значение строки вычисляемо compile-time).

Добавлено
Цитата korvin @
Я думаю, Игорь имел в виду эту проверку: http://dpaste.dzfl.pl/7ee97716f99f
А в чем принципиальная разница?

Автор: MyNameIsIgor 11.02.14, 17:34
Цитата applegame @
А в чем принципиальная разница?

Принципиальной разницы нет - функции разные.

Автор: korvin 11.02.14, 17:35
Цитата applegame @
А в чем принципиальная разница?

Я не знаю, есть ли в D разница между твоим и моим примером, но, думаю, разные адреса намекают на разные функции, а кто-то утверждал, что функция одна.

Автор: applegame 11.02.14, 17:42
Цитата MyNameIsIgor @
Принципиальной разницы нет - функции разные.
Это очевидно. При присвоении значения первому указателю, будут сгенерены две функции для двух и трех int. Для второго указателя сгенерится еще одна функция - для четырех int (для трех и двух уже нет необходимости, так как они уже есть). Если включить оптимизацию, то в готовом коде, вероятно, останутся только две функции: для трёх и для четырех int. Причем также вероятно, что та, что с четырмя не будет вызывать ту, что с тремя. Если компилер совсем крут, аки GCC, то в конечном коде функций может не быть совсем, все будет заинлайнено "в нули".

Добавлено
Цитата korvin @
а кто-то утверждал, что функция одна.
Господи, я же говорил, с математической точки зрения. Можете обзывать это метафункцией:
Цитата MyNameIsIgor @
Метафункция рекурсивна, да. Порождённые ею функции - нет.

Автор: D_KEY 11.02.14, 17:46
Цитата applegame @
Цитата korvin @
Как тогда компилятор выясняет, какие идентификаторы в строке являются аргументами лямбды, а какие — нет? Или контекст вызова просто игнорируется и его также нужно явно передавать параметром?
А, если предикат задан строкой, то имена жестко зафиксированы за "a" и "b". Дело в том, что D умеет компилировать выражение в строке (конечно, только если значение строки вычисляемо compile-time).

Можно подробнее? И есть ли способ захвата контекста в ..эм.. строку?

Автор: MyNameIsIgor 11.02.14, 17:51
Цитата applegame @
Это очевидно

Собственно, не понятно чем вы тогда весь такой недовольный. Я ведь говорил
Цитата MyNameIsIgor @
Рекурсивно определение шаблона. Но не определения функций, порождаемых этим шаблоном.

Автор: applegame 11.02.14, 17:52
Цитата D_KEY @
Можно подробнее? И есть ли способ захвата контекста в ..эм.. строку?
Строка будет скомпилирована в контексте того места, где она собственно скомпилирована, простите за тавтологию. Ща приведу пример, может станет понятней.

Автор: korvin 11.02.14, 17:54
Цитата applegame @
Господи, я же говорил, с математической точки зрения. Можете обзывать это метафункцией

С «математической» точки зрения у всех функций только один аргумент например. =)
Не знаю, зачем вообще надо было приплетать в обсуждение математику и какой «физический смысл» у этой «математической точки зрения» как в контексте обсуждения, так и для компиляторов.

Автор: applegame 11.02.14, 17:55
Цитата MyNameIsIgor @
Собственно, не понятно чем вы тогда весь такой недовольный. Я ведь говорил
Я против этого не возражал. Случилось, вероятно, недопонимание. Предлагаю закрыть эту тему.

Добавлено
Цитата korvin @
С «математической» точки зрения у всех функций только один аргумент например. =)
Да, с ясностью выражения мыслей у меня иногда бывают проблемы, как собственно и у всех. Исключение разве что FlexFerrum, по крайней мере в темах о C++ :)
Цитата korvin @
Не знаю, зачем вообще надо было приплетать в обсуждение математику и какой «физический смысл» у этой «математической точки зрения» как в контексте обсуждения, так и для компиляторов.
Смысл был в ответе на вопрос корректно ли называть второе решение - рекурсивным? То, что оно семантически будет итеративным - вызов нескольких функций одна внутри другой - очевидно, но само решение, я считаю, можно вполне назвать рекурсивным.

Добавлено
Вот обещанный пример. Обратите внимание на удобство и простоту использования auto в качестве возвращаемого типа:
[URL=http://dpaste.dzfl.pl/82aacb91bb0b
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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" );
    }
]http://dpaste.dzfl.pl/82aacb91bb0b
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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" );
    }
[/URL]

Добавлено
И да, на всякий случай, уточню: будет сгенерено четыре функции foo, для разных строковых параметров.

Автор: MyNameIsIgor 11.02.14, 18:25
Цитата applegame @
Обратите внимание на удобство и простоту использования auto

http://en.wikipedia.org/wiki/C%2B%2B14#Fun..._type_deduction
По поводу кривости компилирования строк уже высказывался.

Автор: applegame 11.02.14, 18:34
Цитата MyNameIsIgor @
По поводу кривости компилирования строк уже высказывался.
Никаких аргументов, кроме "мне не навится" и "зачем?" я не видел.

Автор: MyNameIsIgor 11.02.14, 18:39
Цитата applegame @
Никаких аргументов, кроме "мне не навится" и "зачем?" я не видел.

Так вы на вопрос "зачем?" ответили "доставляет" :D Это я должен полагать аргументом?
И таки да, это криво. Посмотрите как пишутся макросы в Nemerle, и вы меня поймёте.

Автор: korvin 11.02.14, 18:48
Цитата applegame @
Обратите внимание на удобство и простоту использования auto в качестве возвращаемого типа

Не прошло и сорока лет... =)

Цитата applegame @
Никаких аргументов, кроме "мне не навится" и "зачем?" я не видел.

Жестко заданные имена параметров, отсутствие возможности автоматически захватить контекст вызова. Кстати, количество параметров-то не жестко 2?

Автор: applegame 11.02.14, 18:48
Цитата MyNameIsIgor @
Так вы на вопрос "зачем?" ответили "доставляет" :D Это я должен полагать аргументом?
Ну вот вы нагло лжете.троллите, а я должен после этого пытаться дискутировать? Никакого вопроса "зачем?" там не было - D vs C++ (сообщение #3413060)

Добавлено
Цитата MyNameIsIgor @
Посмотрите как пишутся макросы в Nemerle, и вы меня поймёте.
Посмотрите на название темы и поймете, что Nemerle тут не нужен.

Автор: korvin 11.02.14, 18:50
Цитата applegame @
Ну вот вы нагло лжете.троллите, а я должен после этого пытаться дискутировать? Никакого вопроса "зачем?" там не было

Пусть теперь будет: зачем?

Автор: applegame 11.02.14, 18:50
Цитата korvin @
Не прошло и сорока лет... =)
Это скорее к плюсам :) В D это уже давно.
Цитата korvin @
Жестко заданные имена параметров, отсутствие возможности автоматически захватить контекст вызова. Кстати, количество параметров-то не жестко 2?
Это ты о чем вообще? Жестко заданные имена параметров только для предикатов в виде строк. Жирным выделил все необходимые условия. Повторю, для непонятливых магические слова: предикаты в виде строк. Не лямбды вообще, а еще раз, только предикаты в виде строк. Не предикаты вообще, а и еще раз только предикаты в виде строк.

Автор: korvin 11.02.14, 18:51
Ах да, для этого кода внутри строк подсветка синтаксиса не работает. А дополнение кода?

Автор: D_KEY 11.02.14, 18:55
Цитата applegame @
Цитата MyNameIsIgor @
По поводу кривости компилирования строк уже высказывался.
Никаких аргументов, кроме "мне не навится" и "зачем?" я не видел.

"Зачем?" - это вопрос, а не аргумент :) Фича действительно не нравится. И не понятно зачем она :D

Автор: korvin 11.02.14, 18:55
Цитата applegame @
Это ты о чем вообще?

Ну ты же сам говорил, что имена параметров a и b жестко заданные.

Добавлено
Цитата applegame @
Жирным выделил все необходимые условия

Не буду выделять жирным ответ, просто кратко перечислю:
1) Речь и идет о строках.
2) У предикатов бывает только два параметра? И я хочу их называть например subject и object, как во всяких прологах и графовых БД, а не a и b, можно?

Автор: applegame 11.02.14, 18:59
Цитата D_KEY @
И не понятно зачем она :D
Чтобы упростить код, для простых предикатов. Лямбда всяко будет длиннее даже в D, а в плюсах и подавно.

Добавлено
Цитата korvin @
Не буду выделять жирным ответ, просто кратко перечислю:
1) Речь и идет о строках.
2) У предикатов бывает только два параметра? И я хочу их называть например subject и object, как во всяких прологах и графовых БД, а не a и b, можно?
Ответы: нет, нет.
"Строковые" предикаты теряют свои косметические преимущества для сложных случаев. Используй в качестве предиката лямбды, делегаты, функторы, все, что callable и подходит по сигнатуре. У "не строковых" предикатов нет ограничений на название переменных. Количество аргументов зависит не от "строковости" предиката, а от функции, которая его требует.

Автор: MyNameIsIgor 11.02.14, 19:05
Цитата applegame @
вы нагло лжете

Это новый тренд на форуме такой?
Цитата applegame @
Посмотрите на название темы и поймете, что Nemerle тут не нужен.

Название темы - это повод отвергать опыт других и творить поделки? А фичу C# с преобразованием лямбд в объекты, представляющие синтаксическое дерево, на которой LINQ работает, вы тоже за пример не рассматриваете? Подозреваю, что проблема не в названии темы, а в том, что вы ничего слащее редьки не пробовали.

Автор: korvin 11.02.14, 19:08
Цитата applegame @
Чтобы упростить код, для простых предикатов. Лямбда всяко будет длиннее даже в D

На пару-тройку символов? Вообще погоды не делает. От каррирования и то больше разницы.

Автор: applegame 11.02.14, 19:10
Цитата MyNameIsIgor @
Это новый тренд на форуме такой?
Это ваш личный тренд, которого вы постоянно придерживаетесь :D
В общем я вас понял, да. Не благодарите за еду - не стоит :)
С вашего позволения я продолжу с другими участниками. Впрочем, пардон, мне не нужно для этого ваше позволение. :)

Автор: MyNameIsIgor 11.02.14, 19:14
Цитата applegame @
Цитата MyNameIsIgor @
Это новый тренд на форуме такой?
Это ваш личный тренд, которого вы постоянно придерживаетесь :D
В общем я вас понял, да. Не благодарите за еду - не стоит :)
С вашего позволения я продолжу с другими участниками. Впрочем, пардон, мне не нужно для этого ваше позволение. :)

Т.е. на другие языки вы смотреть не хотите и продолжаете жевать редьку? :D Ну, это вы зря... :lool:

Автор: applegame 11.02.14, 19:15
Цитата korvin @
На пару-тройку символов? Вообще погоды не делает. От каррирования и то больше разницы.
Во-первых не пара и не тройка, попробуйте что-ли. Во-вторых, любой синтаксический сахар кому-то нравится, а кому-то нет. Это всего лишь один из вариантов применения строковых литералов в качестве параметра шаблона.

Автор: MyNameIsIgor 11.02.14, 19:17
Цитата applegame @
Это всего-лишь один из вариантов применения строковых литералов в качестве параметра шаблона.

Сам сей факт не вызывает отторжения. А вот зачем запихивать в строку код - непонятно. Пример хоть покажите радикальной экономии символов.

Автор: korvin 11.02.14, 19:22
Цитата applegame @
Во-первых не пара и не тройка, попробуйте что-ли.

Ровно два:
<{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
Впрочем, что-то мы увлеклись строковыми предикатами, пример я привел, чтобы разъяснить как вообще работает компиляция строк, в качестве пояснения к вопросу
Цитата D_KEY @
Можно подробнее? И есть ли способ захвата контекста в ..эм.. строку?
"Строковый" предикат - это простая строка. Предикатом его делает функция find, поэтому, естественно, никаких захватов контекстов нет. Для захвата контекста - есть обычные лямбды.

Автор: applegame 11.02.14, 19:29
Цитата korvin @
Ведь без строк нам ненужен параметр b.
Если юзать предикат с одним параметром, то и в "строковом" варианте можно убрать 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. :D

Автор: korvin 11.02.14, 20:03
Цитата applegame @
Доступен, опять же синтаксический сахар, который, лично мне нравится:

Смотри сахарный диабет не заработай.

Автор: MyNameIsIgor 11.02.14, 20:06
Цитата applegame @
Доступен, опять же синтаксический сахар, который, лично мне нравится

Пока такие "киллер фичи" будут продвигаться новыми языками, у 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}>
    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 интерфейсы ведут себя аналогично плюсовой эмуляции. Но так как в плюсах эмуляция, то это нормально, а так как в D есть ключевое слово interface, то это уже косяк. По мне так оно яйца выеденного не стоит, но полемику некоторые все равно развели. Холивары, они такие :D

Добавлено
Цитата Qraizer @
applegame, приведи пример простенького сериализатора на D
Окай, ща набросаю чего-нибудь.

Автор: D_KEY 12.02.14, 06:45
Цитата Qraizer @
Если не ошибаюсь, поправьте, если не если, Александреску задумал D не как убийцу C++, а как язык с ориентацией на парадигму обобщённого программирования и без груза обратной совместимости с чем бы то ни было, а значит и лишённого набившего в C++ оскомину.

Ну автор темы не Александреску. Решили поспорить о D vs C++, почему бы и нет :-? :D

Цитата
Остаётся только вопрос практичности результата там, где D якобы превосходит. Собственно и всё. А вы тут какую-то хрень обсуждаете.

По большому счету именно этот вопрос мы и обсуждаем. Что могут дать возможности D и стоит ли оно того.

Автор: applegame 12.02.14, 08:44
Цитата Qraizer @
applegame, приведи пример простенького сериализатора на D.

Набросал сериализатор/десериализатор. Постарался максимально обобщить, но возможны косяки. 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
Ну, вот почему, почему всегда рефлексию показывают на этом тупом примере сериализации всех полей? :facepalm:

Автор: D_KEY 12.02.14, 10:20
Ну сериализатор его попросили написать. Если для составного типа не задана функция сериализации, то проход по полям лучше бинарной записи.

Автор: MyNameIsIgor 12.02.14, 10:28
Цитата D_KEY @
Если для составного типа не задана функция сериализации, то он не сериализуем вообще

fixed.
Да и я спрашиваю вообще, а не про именно сейчас.

Автор: D_KEY 12.02.14, 11:05
Цитата MyNameIsIgor @
Цитата D_KEY @
Если для составного типа не задана функция сериализации, то он не сериализуем вообще

fixed.

Ну тебя же не смущает дефолтный конструктор копирования, например. Если все поля у объекта сериализуемы, то почему бы и не сериализовать, раз просят.

Автор: korvin 12.02.14, 11:05
Цитата MyNameIsIgor @
Цитата D_KEY @
Если для составного типа не задана функция сериализации, то он не сериализуем вообще

fixed.
Да и я спрашиваю вообще, а не про именно сейчас.

Описывать метод сериализации для каждого своего типа как-то не очень удобно. Обычно это довольно рутинный copy-paste код.

Кстати маршалинг/демаршалинг в xml/json структур в Go не затрагивает скрытые поля структур. ЕМНИП до них и через рефлексию не достучаться.

Автор: D_KEY 12.02.14, 11:22
Цитата korvin @
Обычно это довольно рутинный copy-paste код.

Это смотря какой движок сериализации. Например, в 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 @
Например, в boost.serialization ты фактически просто указываешь, что хочешь сериализовать.
Кстати, это тоже интересный момент: как указать поля которые нужно сериализовать, или наоборот не нужно. В D есть фича, которую можно для этого применить. Это так называемые UDA - user defined attribute. По сути - это что-то вроде пометок, которые ни на что не влияют, но которые можно читать (compile time) и предпринимать в зависимости от этого какие-то действия. Пример: http://dpaste.dzfl.pl/120ff9a20956

Автор: MyNameIsIgor 12.02.14, 12:12
Цитата D_KEY @
Ну тебя же не смущает дефолтный конструктор копирования, например

Потому что если у меня есть поле-мьютекс, то копироваться такой объект не будет. Т.е. поля структуры управляют поведением такого конструктора.
Цитата D_KEY @
Если все поля у объекта сериализуемы

А тут не управляют - сериализуемость определяется тем, что мы можем пройтись по типу рефлексией. Для мьютекс эта чудо-сериализация запишет его дескриптор.
Цитата korvin @
Описывать метод сериализации для каждого своего типа как-то не очень удобно

Меня больше волнует правильность, а не удобство поведения по умолчанию, чреватого детскими грабельками.
Цитата korvin @
Обычно это довольно рутинный copy-paste код.

Это зависит от библиотеки сериализации. Я не замечал копипасты. Кроме того, метаинформацию никто не отменял. Вон и applegame её для себя открыл.

Автор: Qraizer 12.02.14, 12:15
Цитата applegame @
Тут не важно виртуальный базовый класс или нет. Виртуальность ничего не меняет:
А тут и не должно, т.к. как уже говорилось, 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 @
Цитата D_KEY @
Ну тебя же не смущает дефолтный конструктор копирования, например

Потому что если у меня есть поле-мьютекс, то копироваться такой объект не будет. Т.е. поля структуры управляют поведением такого конструктора.

Тут согласен, да. Но это же пример, можно будет дать возможность запретить сериализацию для типа или еще как-то решить данную проблему.

Автор: korvin 12.02.14, 12:51
Цитата MyNameIsIgor @
Меня больше волнует правильность, а не удобство поведения по умолчанию, чреватого детскими грабельками.

Цитата MyNameIsIgor @
Для мьютекс эта чудо-сериализация запишет его дескриптор.

А зачем вообще может понадобиться сериализовать такое значение? Я не храню в данных, предназначенных для передачи во вне/приеме извне какие-то служебные объекты, только "plain data".

Автор: MyNameIsIgor 12.02.14, 12:55
Цитата D_KEY @
Но это же пример, можно будет дать возможность запретить сериализацию для типа

Да пусть так. Я о другом говорю: чуть заходит разговор за рефлексию, как кричат "сериализация!". Я же говорю, что рефлексия при сериализации чаще всего вредна.
Цитата 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++.
Взаимоисключающие параграфы :D

Добавлено
Цитата 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 @
Вообще, кто-то просил сериализацию, получил сериализацию, но ни одного комментария на эту тему так и не сделал.
Зачем что-либо говорить ради что-либо сказать? Я посмотрел, даже понял, как работает, ожидания подтвердились.

Добавлено
Цитата MyNameIsIgor @
А вы ошибку то исправлять не собираетесь?
Я даже примерно представляю как. Это даже скорее не ошибка, а просто плохо задокументированная инструкция по применению. Но так, как я это представляю, будет неудобно, и вот сие улучшить было бы неплохо.

Автор: korvin 13.02.14, 05:41
Цитата jack128 @
прикольно. то есть если бы ты писал excel, то у тебя бы документ представлял бы собой такую вот огромную структуру с открытыми полями?

А ты считаешь, что во всех задачах можно использовать один и тот же подход? У меня нет «огромных структур», все довольно небольшие. Впрочем, может быть так оно и было бы, а в чем проблема?

Автор: MyNameIsIgor 13.02.14, 09:42
Цитата korvin @
Цитата MyNameIsIgor @
Погоди, plain data - это детали реализации. Если ты выставил их наружу так, что их видит библиотека сериализации, то я уже считаю это ошибкой проектирования.

Ты вообще о чем? У меня просто в тех местах, где требуется маршалинг/демаршалинг, нет «объектов» с закрытыми полями, только структуры с открытыми.

Гмм... Как это выглядит в жизни? Т.е. пример бы какой-нибудь.

Автор: korvin 13.02.14, 12:53
Цитата MyNameIsIgor @
Гмм... Как это выглядит в жизни?

Ну например беру из базы нужные записи(структуры) и на их основе создаю новую структуру (с другими полями) или массив структур и отправлю ее/их по 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
Цитата applegame @
Структура объявляется внутри функции (кстати, а плюсы так умеют?)
Уметь-то умеют, но эта структура будет видна только внутри этой функции, так что выдать её в качестве результата не получится, поскольку в точке вызова она не будет существовать.

Хотя, возможно auto может создать безымянный тип, соответствующий этой структуре, и получится использовать его.

Автор: applegame 30.03.14, 13:40
Цитата amk @
Хотя, возможно auto может создать безымянный тип, соответствующий этой структуре, и получится использовать его.
Конечно с auto. Без auto и в D невозможно. ЕМНИП в след версии плюсов, появился полноценный auto, а не инвалид который есть в C++11.

Автор: amk 30.03.14, 13:45
А что такого инвалидного в С++ auto?

Автор: applegame 30.03.14, 13:50
Цитата amk @
А что такого инвалидного в С++ auto?
Опять же, ЕМНИП, там запутанный и неприятный синтаксис для auto - возвращаемых типов. Просто вот так написать не получится:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    template<typename A, typename B>
    auto foo(A a, B b) {
      return a + b;
    }
Вроде Qraizer говорил, что в C++14, уже можно будет писать и так.

Добавлено
Кстати еще вот некоторым не нравится, что в D для объявления шаблонов используются круглые скобки. А мне вот, наоборот, нравится, благодаря этому, инстанцирование шаблона выглядит похожим на вызов функции.

Автор: amk 30.03.14, 13:56
Да, выглядит как недоделка. Если над объекты типов A и B можно сложить, то тип результата а этой точке известен, значит ничего не должно мешать и определению типа возвращаемого значения.

Автор: applegame 30.03.14, 14:04
Цитата amk @
Да, выглядит как недоделка. Если над объекты типов A и B можно сложить, то тип результата а этой точке известен, значит ничего не должно мешать и определению типа возвращаемого значения.
Это возможно, но вот таким странным образом:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    template<typename A, typename B>
    auto hellSum(A a, B b) -> decltype(a + b) {
      return a + b;
    }
Зачем там нужен этот дурацкий decltype непонятно.

Автор: Qraizer 30.03.14, 16:01
Цитата applegame @
Зачем там нужен этот дурацкий decltype непонятно.
Затем:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    template<typename A, typename B>
    auto hellSum(A a, B b) -> decltype(a + b);
Очень информативно увидеть в интерфейсе просто auto без информации о реализации.

Автор: Мяут-Настоящий 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
Цитата Qraizer @
Очень информативно увидеть в интерфейсе просто auto без информации о реализации.
Все прекрасно. Информация дается в комментариях, а не в безумном 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 @
Функция должна вернуть несколько значений, и хочется чтобы доступ к значениям был бы как к полям структуры, а не по индексу, как в обычном плюсовом кортеже.

А почему не объявить структуру и не вернуть её из функции? Изврата захотелось? Типа
Цитата applegame @
Рекурсивный миксин плюс немножко статической рефлексии

Это через какую только жопу гланды не выдирают вместо того, чтобы сделать функции, возвращающие несколько значений, как, например, в Go.
Впрочем, хотите через жопу - получите. Гораздо лучше дишных извращений на пустом месте.

Автор: applegame 30.03.14, 19:08
Цитата MyNameIsIgor @
А почему не объявить структуру и не вернуть её из функции? Изврата захотелось?
У меня таких функций вагон и маленькая тележка, извратом будет как раз объявлять вагон и маленькую тележку структур.
Цитата MyNameIsIgor @
Это через какую только жопу гланды не выдирают вместо того, чтобы сделать функции, возвращающие несколько значений, как, например, в Go.
О да, это же какая жопа написать packTuple!(...) или просто tuple(...), если обычного кортежа достаточно.
Цитата MyNameIsIgor @
Впрочем, хотите через жопу - получите. Гораздо лучше дишных извращений на пустом месте.
Это простите, херня, никакого отношения к сабжу не имеющая.

Вы батенька, как всегда, пукаете в лужу. "Если C++ что-то не умеет, то это не нужно" - вот ваш девиз. Научитесь уже отвечать по существу.

Автор: MyNameIsIgor 30.03.14, 19:37
Цитата applegame @
У меня таких функций вагон и маленькая тележка

И зачем?
Цитата applegame @
извратом будет как раз объявлять вагон и маленькую тележку структур

Нет, это будет явная декларация.
Цитата applegame @
Это простите, херня

Не прощаю. А за нецензурную брань модератор взыщет.
Цитата applegame @
никакого отношения к сабжу не имеющая

Т.е. если что-то сделали иным способом, нежели ваш, то к теме это отношения не имеет? :D
Цитата applegame @
Вы батенька, как всегда, пукаете в лужу

А вы продолжаете нюхать :lool:
Цитата applegame @
"Если C++ что-то не умеет, то это не нужно" - вот ваш девиз

Нет, я лишь предлагаю делать по-уму. Уже посмотрели как возвращаются несколько значений в Go? Это во-первых.
Во-вторых, вы плюсы на уровне второклашки то не осилили, откуда вам знать, что они могут?

Автор: Qraizer 30.03.14, 20:21
Цитата applegame @
Все прекрасно. Информация дается в комментариях, а не в безумном decltype, который, кстати, может содержать трехэтажные конструкции. Эту работу, ИМХО, может и должен делать компилятор.
Молодец! Сам упомянул компилятор. А ну-ка, покажи, как компилятор разгребёт комменты. И с чего он вообще будет это делать. В Плюсах auto с последующим decltype введены для упрощения квалификацированных идентификаторов, каковые становятся возможны только после списка параметров, а отнюдь не для автовывода типа результата. Автовывод, конечно, есть, но для частных случаев.
Цитата applegame @
Особенно если учесть, что интерфейсы шаблонов функций без тела этих функций полезны в C++ чуть более, чем никогда.
Та ладно. И как давно это так? Даже без extern template это встречалось нередко. Интерфейс интерфейсом, но параметризация шаблонов отнюдь не ограничивается пользовательскими желаниями, нередко эта параметризация выбирает платформенные специализации, а в этом случае обычная раздельная компиляция вполне применима и легко реализуется.

Автор: 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
Цитата applegame @
Информация дается в комментариях, а не в безумном decltype

В комментариях? Информация о типах? В языке со статической типизацией? Мда..
А как же самодокументируемость? Нет, я за возможность как указания типа, так и явного decltype/typeof. Кстати, в D же это возможно, о чем ты споришь? В C++14 обязательность decltype уходит.

Автор: applegame 30.03.14, 22:16
Цитата D_KEY @
Не очень понял, что ты этим выиграл. Коллеги твои вряд ли будут довольны. Да и ты сам через полгодика не обрадуешься.
Уже больше времени прошло, и никаких проблем. Удобно, всем наоборот нравится. Я же не везде его пихаю. Там где название типа действительно важно, я указываю его явно. Но в проекте много всяких хелперов, мелких вспомогательных функций и шаблонов, где в общем-то глубоко начхать на название типа. Название функции говорит само за себя, а в комментах описано, что именно она возвращает.
Цитата D_KEY @
В комментариях? Информация о типах? В языке со статической типизацией? Мда..
Зачем о типах? Описание возвращаемого значения и все. Тип не важен. Типы пусть знает и проверяет компилятор.
Одно из преимуществ D, что он при желании позволяет писать в стиле динамических языков. Автоматическое выведение типов, auto и прочие радости. Легкость работы с динамическими языками, но при этом типизация статическая, что позволяет ошибки с типами находить compile-time.
Можно до последнего цепляться за древний уродливый стиль с громоздкими иерархиями классов, тоннами типов объявленных явно и т.п., но это прошлый век. Даже сам C++ эволюционирует, внезапно, может и не совсем по пути D, но явно в туже сторону
Цитата D_KEY @
Кстати, в D же это возможно, о чем ты споришь? В C++14 обязательность decltype уходит.
Обязательность и напрягает. Представь что функция возвращает тип, который можно вывести, но только этот тип будет занимать три строчки кода. Информативность таких кракозябров (особенно в C++) - нулевая. Какая-нибудь лямбда со страшной сигнатурой. А может и не лямбда, может быть функтор, да что угодно, главное что callable. Плевать на тип, главное, что потом с этим значением можно делать.
Цитата D_KEY @
В C++14 обязательность decltype уходит.
Ага, я же говорю дрейфуем туда, куда D ушел уже давным давно.

Автор: D_KEY 30.03.14, 22:43
Так о толку то от твоего "давным давно"? :) Эволюционное развитие - один из козырей C++. Принимается новый стандарт, я обновляю компилятор и, возможно, добавляют флажок поддержки нового стандарта в свой проект и начинаю применять новые полезные для меня фишки, ничего не переписывая и ничего не ломая.

Добавлено
Цитата applegame @
Цитата D_KEY @
В комментариях? Информация о типах? В языке со статической типизацией? Мда..
Зачем о типах? Описание возвращаемого значения и все. Тип не важен.

Имена полей - это тоже информация о типе.

Добавлено
Возможно, ты и прав, но лично я никакого профита от D не вижу... Даже от Go больше потенциальной пользы, как мне кажется. За счёт простоты. Хотя и от него я не в восторге.

Автор: applegame 30.03.14, 22:59
http://habrahabr.ru/post/183488/
Цитата D_KEY @
Возможно, ты и прав, но лично я никакого профита от D не вижу... Даже от Go больше потенциальной пользы, как мне кажется. За счёт простоты. Хотя и от него я не в восторге.
Дело вкуса, наверное. Для меня профит прост: один и тот же код я пишу на C++ значительно медленнее, чем на D.
C++ гораздо "многословнее", а метапрограммирование заметно запутаннее.

P.S. Вот кстати статейка на хабре в тему - http://habrahabr.ru/post/183488/

Автор: D_KEY 30.03.14, 23:42
Так на Питоне задачи ещё быстрее решаются ;) вопрос в том, какие возможности ты имеешь, сколько готовых(своих и сторонних) решений можешь применить, скольким людям это будет понятно и результат какого качества ты получишь.

Автор: OpenGL 31.03.14, 07:37
Цитата D_KEY @
В C++14

Кстати, а он действительно "14" будет? Или они опять слишком оптимистичны? :)

Автор: korvin 31.03.14, 08:49
Цитата OpenGL @
Кстати, а он действительно "14" будет? Или они опять слишком оптимистичны?

Ну может как раз до C++0xF дотянут. =)

Автор: applegame 31.03.14, 09:25
Цитата D_KEY @
Так на Питоне задачи ещё быстрее решаются ;)
Да, но Питон все-таки язык с динамической типизацией, со всеми вытекающими. D же с одной стороны язык с полноценной статической типизацией, с другой позволяет легко обходится во многих случаях без обозначения типов.
Любители вон даже накропали препроцессор для конвертации некоего питонообразного языка Delight в D и наоборот D в Delight.

Автор: Qraizer 31.03.14, 12:58
Цитата applegame @
P.S. Вот кстати статейка на хабре в тему - http://habrahabr.ru/post/183488/
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
Цитата Qraizer @
Ну так а велика разница?
Да, велика. Функция может быть шаблоном, а лямбда нет.
<{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

Автор: D_KEY 28.04.14, 21:22
Цитата applegame @
Скотт Майерс участвует в DConf 2014
Еще один известный плюсовик в лагере D

P.S. Правда он дружбан Александреску, который его, видимо, и сбил с пути истинного. :D

Почему сбил? От C++ вроде ни один ни другой не отказываются.

Добавлено
Вообще C++ сейчас развивается достаточно хорошо. Не знаю, как там будет дальше, но сейчас хороший сбалансированный темп, за которым успевают и компиляторы и разработчики.

Автор: applegame 28.04.14, 21:25
Цитата D_KEY @
Почему сбил? От C++ вроде ни один ни другой не отказываются.
Это была шутка :)

Добавлено
Кстати, ИМХО, интересные конфы, даже не для программистов на 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
Цитата D_KEY @
Мне кажется слабовато с точки зрения аргументации для данного холивара.

Если ты про фразу applegame (а не про видео, я его не смотрел), то она еще и двусмысленна, т.к. по ней непонятно — это «за» C++ или D. =)

Автор: applegame 28.05.14, 17:19
Цитата D_KEY @
Ну так. Мне кажется слабовато с точки зрения аргументации для данного холивара.
Это вообще не аргументация с точки зрения холивара. Холивар, по-моему, уже никому не интересен.

Автор: D_KEY 28.05.14, 17:53
Цитата applegame @
Цитата D_KEY @
Ну так. Мне кажется слабовато с точки зрения аргументации для данного холивара.
Это вообще не аргументация с точки зрения холивара. Холивар, по-моему, уже никому не интересен.

Мне не интересен холивар только потому, что тут нет интересной аргументации :D

Добавлено
Цитата korvin @
Цитата D_KEY @
Мне кажется слабовато с точки зрения аргументации для данного холивара.

Если ты про фразу applegame (а не про видео, я его не смотрел), то она еще и двусмысленна, т.к. по ней непонятно — это «за» C++ или D. =)

Видео против (сложности) C++ :)

Автор: applegame 28.05.14, 18:13
Цитата D_KEY @
Мне не интересен холивар только потому, что тут нет интересной аргументации :D
Сомневаюсь, что в природе вообще существует интересная для тебя аргументация в холиворе D vs C++ :)
На вас ничего не действует ни UDA, ни строковые миксины, ни шаблоны, ни CTFE. На все ответ только один - "ну и чо?" ;)
Только Qraizer признал, что в обобщенном программировании D бьет C++.

Добавлено
Цитата D_KEY @
Видео против (сложности) C++ :)
Ну не совсем против. Майерс говорит также о том, что для C++ эта сложность, фактически, вынужденная мера.

Автор: D_KEY 28.05.14, 18:49
Цитата applegame @
На вас ничего не действует ни UDA, ни строковые миксины, ни шаблоны, ни CTFE. На все ответ только один - "ну и чо?" ;)

Надо заметить, что не только на меня это не действует. Вон у go даже, наверное, аудитория шире уже.

Цитата
Только Qraizer признал, что в обобщенном программировании D бьет C++.

А чего тут признавать? Бьёт. Только насколько это существенно будет в реальной жизни?

Автор: applegame 28.05.14, 20:43
Цитата D_KEY @
Надо заметить, что не только на меня это не действует.
Ага, кроме тебя еще на полтора тролля не лействует :)
Цитата D_KEY @
Вон у go даже, наверное, аудитория шире уже.
Даже? За Go стоит Google, а D сумел развиться до текущего уровня без поддержки крупных корпораций. Популярность Go - не более, чем хорошая реклама.

Автор: korvin 29.05.14, 02:10
Цитата applegame @
Популярность Go - не более, чем хорошая реклама.

Ну да, конечно. Сложно признать, что простой (если не сказать примитивный, по сравнению с D) язык оказался более полезен на практике, потому что вместо задрачивания мало кому нужных языковых фенечек, люди писали полезные библиотеки? =)

Добавлено
Собственно golang dlang

Автор: D_KEY 29.05.14, 05:22
Цитата applegame @
Цитата D_KEY @
Вон у go даже, наверное, аудитория шире уже.
Даже? За Go стоит Google, а D сумел развиться до текущего уровня без поддержки крупных корпораций. Популярность Go - не более, чем хорошая реклама.

С чего ты взял?

Автор: applegame 29.05.14, 05:34
Цитата korvin @
Ну да, конечно. Сложно признать, что простой (если не сказать примитивный, по сравнению с D) язык оказался более полезен на практике, потому что вместо задрачивания мало кому нужных языковых фенечек, люди писали полезные библиотеки? =)
Ага прямо как PHP.
Кстати либы для D надо искать тут

А вообще, если верить вот этому http://www.tiobe.com/index.php/content/pap...tpci/index.html, то Go все же отстает от D. Fail.

Автор: D_KEY 29.05.14, 05:40
Цитата applegame @
Ага прямо как PHP.

При чем тут PHP? Скорее как Python и Ruby.

Добавлено
Цитата applegame @
А вообще, если верить вот этому http://www.tiobe.com/index.php/content/pap...tpci/index.html, то Go все же отстает от D. Fail.

Сколько лет D? :D

Добавлено
А вот на каком-нибудь github, вроде как D сильно отстает от Go. Если я правильно помню.

Автор: applegame 29.05.14, 05:47
Цитата D_KEY @
Сколько лет D? :D
Фактически первая стабильная версия компилятора вышла в 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
Цитата applegame @
А вообще, если верить вот этому

user posted image
=))

Цитата applegame @
Go все же отстает от D. Fail.

А сипсок "production"-пользователей D где можно посмотреть?

Автор: applegame 29.05.14, 05:54
korvin, попробуй Ctrl-F5, так как у меня никаких ошибок нет.
Цитата korvin @
А сипсок "production"-пользователей D где можно посмотреть?
Списка не знаю, но некоторых я перечислял в этой теме.

Автор: D_KEY 29.05.14, 05:54
Цитата D_KEY @
И особой помощи от google я не вижу(сравни, например, с продвижением C# от MS).

За что(отсутствия навязывания Go) гуглу большое спасибо, а то мне лично go не нравится. Но в отличие от D он хотя бы практичен.

Автор: korvin 29.05.14, 05:55
Цитата applegame @
а Go в 2009

Вообще-то в 2012-м. До Go 1 ни компилятор, ни язык не были стабильны.

Автор: applegame 29.05.14, 05:56
Цитата D_KEY @
То, что стабильная версия вышла так поздно для D - это тоже недостаток, а не повод сделать язык моложе, чем он есть.
На самом деле возраст языка вообще ничего не значит, если уж на то пошло.
Цитата D_KEY @
Go занималась не очень большая команда. И особой помощи от google я не вижу
Ты работаешь в Google? Или так, просто потрепаться?

Автор: korvin 29.05.14, 05:57
Цитата applegame @
Списка не знаю, но некоторых я перечислял в этой теме.

Жаль, была бы еще одна линейка. =)

Автор: D_KEY 29.05.14, 06:01
Цитата applegame @
На самом деле возраст языка вообще ничего не значит, если уж на то пошло.

Значит в контексте распространения.

Цитата
Цитата D_KEY @
Go занималась не очень большая команда. И особой помощи от google я не вижу
Ты работаешь в Google? Или так, просто потрепаться?

Мы говорили о продвижении языка. Вот MS продвигала C#, ты видишь, что Google продвигает Go так же? А как развивался Go вроде не закрытая информация.

Автор: applegame 29.05.14, 06:01
Цитата korvin @
Вообще-то в 2012-м. До Go 1 ни компилятор, ни язык не были стабильны.
Но представлен был в 2009. Фактическое развитие D началось лет пять назад. Хотя он и появился он в 2001-году все это время он находился в замороженном состоянии.

Добавлено
Цитата D_KEY @
ты видишь, что Google продвигает Go так же?
На самом деле уже только то, что этот язык был представлен Google имеет огромное значение. О нем узнало очень много народу. А о D мало кто знает.

Автор: korvin 29.05.14, 06:03
Цитата applegame @
Ты работаешь в Google? Или так, просто потрепаться?

А какую помощь (в продвижении Go) оказывал Google? Пара выступлений Пайка?

Автор: D_KEY 29.05.14, 06:04
Цитата applegame @
Хотя он и появился он в 2001-году все это время он находился в замороженном состоянии.

Что тоже отрицательно сказалось на его восприятии. Сколько не читаю холиваров про него, всегда есть истории про "заинтересовался-загорелся-попробовал-плюнул" :D

Автор: korvin 29.05.14, 06:06
Цитата applegame @
Но представлен был в 2009.

Ты говорил про стабильные версии, определись уж.

Автор: 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 достиг той точки, когда уже можно перейти на него.

Добавлено
Цитата D_KEY @
Опять же, Rust, как мне кажется, уведет еще людей с D. Если, конечно, у них все пойдет хорошо.
Может быть, а может и нет. ЕМНИП, в Rust нет полноценных шаблонов, вместо них дженерики.

Добавлено
Цитата D_KEY @
Как раз приведенный тобой индекс tiobe говорит об обратном.
Ты хоть сам веришь-то в то что D более известен, чем Go?

Автор: D_KEY 29.05.14, 11:07
Цитата applegame @
Цитата D_KEY @
Опять же, Rust, как мне кажется, уведет еще людей с D. Если, конечно, у них все пойдет хорошо.
Может быть, а может и нет. ЕМНИП, в Rust нет полноценных шаблонов, вместо них дженерики.

Там дженерики вроде тип не "забывают" в реализации(т.е. кодогенерация эффективна) плюс есть trait'ы, специализации(но только через реализацию trait'ов) и пр. И, самое главное, там есть полноценные макросы.

Добавлено
Цитата applegame @
Цитата D_KEY @
Как раз приведенный тобой индекс tiobe говорит об обратном.
Ты хоть сам веришь-то в то что D более известен, чем Go?

Нет, но tiobe вроде как раз на поисковые запросы и пр. вещи смотрит. Так что "если верить" tiobe, то... :)

Автор: applegame 29.05.14, 12:00
Цитата D_KEY @
Нет, но tiobe вроде как раз на поисковые запросы и пр. вещи смотрит. Так что "если верить" tiobe, то... :)
Полагаю, что известность и популярность, хоть и связанные вещи, но все же разные.

Автор: DarkEld3r 17.06.14, 13:06
Цитата D_KEY @
Там дженерики вроде тип не "забывают" в реализации

Как по мне, "duck typing" С++ шаблонов мощнее. В расте ведь если класс поддерживает нужную операцию, но не через требуемый трейт, то облом. Плюс перегрузки функций нет - из-за этого, по моему, обобщённый код писать менее удобно.

Хотя остальной набор фич мне тоже больше Д-шного нравится.

Автор: D_KEY 17.06.14, 13:09
Цитата DarkEld3r @
В расте ведь если класс поддерживает нужную операцию, но не через требуемый трейт, то облом.

Так ты заведи :)

Цитата
Плюс перегрузки функций нет - из-за этого, по моему, обобщённый код писать менее удобно.

Тут спорно. Есть мнение, что через трейты это делать не сложнее, при этом код будет более понятен и структурирован. Но сам я активно не писал на трейтах, потому утверждать это не берусь. Но похоже на правду.

Автор: DarkEld3r 17.06.14, 15:17
Цитата D_KEY @
Так ты заведи :)

А если класс или генерик не мои и менять нежелательно/невозможно?
Я только за, если бы такие ограничения были опциональными (типа как разрабатываемые концепты).

Цитата D_KEY @
Тут спорно. Есть мнение, что через трейты это делать не сложнее

Или я чего-то не понимаю или не согласен. Скажем как реализовать подобие std::begin из С++? По моему, перегрузка - это удобно.

Автор: D_KEY 17.06.14, 15:20
Цитата DarkEld3r @
Цитата D_KEY @
Так ты заведи :)

А если класс или генерик не мои и менять нежелательно/невозможно?

Так их и не надо менять. У нас есть чей-то trait и есть чей-то тип, а мы можем написать для этого типа нужный impl этого trait'а.

Добавлено
Цитата DarkEld3r @
Скажем как реализовать подобие std::begin из С++?

Ну там все-таки другой подход к обходу коллекций. У них есть метод 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
Цитата D_KEY @
Наверное он мне просто неинтересен. Не вижу, где и зачем его применять.
Понятно.

Автор: DarkEld3r 26.06.14, 11:56
Цитата D_KEY @
Ну там все-таки другой подход к обходу коллекций.

Это был просто пример. В куче случаев мне кажется удобным наличие перегрузки. Да хотя бы to_string или min/max. И если вещи типа то_стр на имплах делаются "вполне нормально", то если аргументов несколько, то уже получается более бредово.

Ещё что-то читал, что макросы у них не попадают в неймспейсы, что тоже не очень здорово.

Впрочем, я раст знаю ещё хуже и очень может быть, что просто слишком привык к тому как эти вещи делаются в С++. Возможно, кто-то, кто знает язык лучше, сумеет разубедить (пока они его не "зарелизят" за изучение браться лень).

Автор: D_KEY 26.06.14, 12:00
Цитата DarkEld3r @
пока они его не "зарелизят" за изучение браться лень

аналогично :)

Автор: Мяут-Настоящий 26.06.14, 12:09
Цитата
не пора ли C++ потихоньку готовиться к пенсии?

Вот вам:

Почему Ваза утонул, а С++ всё ещё на плаву
http://habrahabr.ru/company/infopulse/blog/227529/

:tong:

Автор: DarkEld3r 26.06.14, 13:50
Цитата applegame @
А чем, скажем, тебе лично, D_KEY, не нравится D? :)

А можно я подброшу дровишек в этот вялый холивар?

Сразу говорю - глубоко язык не изучал и ничего хоть немного обьёмного писать не пробовал. Тем не менее, в итоге сложилось не самое лучшее впечатление. Вроде, много улучшений, но в итоге получается так себе. Взять хотя бы строки. В С++ "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
Цитата applegame @
встроенные ассоциативные массивы

Всю переписку ниасилил, но скажу одно - "вы все дураки, я одна стою в белом пальто, красивая" © :) Если скрестить как-то нетипизированность (ну или допущение) и Цэ++ ... это была бы бомба!

Скажу более, не юзавши boost, но слышавши про его тип ::any - тлеет надежда, что строгую типизацию вынесут в разряд "must haVe", вместо обязалова.
А пока ... Perl - the best of the best. Даже не думайте спорить! :wall:

Автор: D_KEY 22.08.14, 19:23
Цитата JoeUser @
нетипизированность (ну или допущение)

Что это? Неявная типизация? Или динамическая типизация? Или что?

Добавлено
По контексту больше похоже на динамическую. Но что тогда оставить в "смеси" от C++? Там все полезное так или иначе связано со статической типизацией.

Автор: korvin 24.08.14, 05:10
Цитата D_KEY @
По контексту больше похоже на динамическую.

Ты смог определить контекст в этом потоке сознания? =)

Автор: Axis 30.10.14, 09:43
Да что-то сколько уже Александреску пиарит D, а воз и ныне там.

Автор: applegame 04.11.14, 07:01
Цитата Axis @
Да что-то сколько уже Александреску пиарит D, а воз и ныне там.
Это не так. Набирает популярность. Медленно так как нет мощной финансовой поддержки.

Автор: Kray74 04.11.14, 08:11
Цитата applegame @
Медленно так как нет мощной финансовой поддержки.

Ага, и facebook совсем не причем, правда?

Автор: applegame 04.11.14, 09:02
Цитата Kray74 @
Ага, и facebook совсем не причем, правда?
Ага, 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
Цитата D_KEY @
Ну у C++ с финансовой поддержкой тоже не густо было. Да и сейчас особо нет.
Нет? А как же 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
Цитата D_KEY @
А D тут при чем?

Да, ближайшая в топе тема из серии C++ vs XXX :)

Добавлено
D_KEY, впрочем, нашёл более подходящую. :)

Автор: Мяут-Настоящий 02.12.14, 14:42
Цитата Flex Ferrum @
XXX

Я хочу этот язык!

Автор: korvin 05.12.14, 15:18
Цитата Мяут-Настоящий @
Я хочу этот язык!

Чтобы писать порно-пасьянсы? =))

А вообще, как там D, еще не сдох?

Добавлено
Цитата MyNameIsIgor @
Как минимум были Эйфель и Objective-C

В отличие от C++ они ж вроде проприетарны. Plan 9 тоже как бы был как альтернатива монструозному Unix, до Linux, но из-за закрытости (тогда) никто их идеями не воспользовался.

Автор: applegame 05.12.14, 16:33
Цитата korvin @
А вообще, как там D, еще не сдох?
Нормалек. Обрастает либами, биндингами к сишным либам и IDEшками.

Автор: D_KEY 05.12.14, 17:10
Цитата korvin @
А вообще, как там D, еще не сдох?

Ну совсем он вряд ли сдохнет.

Кстати, был ли у нас холивар Go и D? После выхода Rust можно будет попробовать устроить Rust vs D. Мне Rust кажется более перспективным.

Автор: DarkEld3r 08.12.14, 13:56
Цитата applegame @
IDEшками.
Например?

Цитата D_KEY @
Мне Rust кажется более перспективным.
Мне тоже, но начал "изучать" язык и постоянно какие-то мелочи "расстраивают". Про отсутствие перегрузки уже говорил, вроде, не смертельно, но местами получается уродливо. Например, вот "конструкторы" хеш таблицы:
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
Цитата DarkEld3r @
Например?

VisualD
DDT
Mono-D

Лично я сижу в Sublime Text 3

Для совсем уж красноглазых есть плагины для vim и какой-то там официальный режим emacs.

Либы тут - http://code.dlang.org/

Автор: DarkEld3r 09.12.14, 13:57
Цитата applegame @
VisualD
DDT
Mono-D

Просто подумал, что я что-то пропустил и появились "чисто-Д" IDE. Про плагины к другим IDE в курсе.

Цитата D_KEY @
Я бы подождал релиза Rust :)

Это принципиально ничего не изменит, насколько я знаю. До версии 1.0 они хотят только всякие "мелочи" подрихтовать. При этом многое не успевают и оно перенесено "на потом". После релиза активная разработка продолжится, планируется по "стабильному релизу" каждые шесть недель.

Автор: applegame 09.12.14, 16:12
Цитата DarkEld3r @
Просто подумал, что я что-то пропустил и появились "чисто-Д" IDE.
А это что значит? Недавно появилась некая альфа IDE - https://github.com/BBasile/Coedit не знаю подходит ли она под определение "чисто-Д" IDE.

Автор: DarkEld3r 10.12.14, 08:54
Цитата applegame @
А это что значит?
Я понимаю, что это не принципиально, но было бы интересно посмотреть на новую IDE созданную именно для D. Ещё лучше, если бы она была сама написана на D. Это было бы своего рода индикатором наличия заинтересованного сообщества вокруг языка. Вон для хаскеля (и на хаскеле) написали Leksah, для Racket тоже. Ну или если бы в существующих IDE "официально" добавили поддержку, то тоже было бы интересно.

Ещё раз - я понимаю, что это не обязательно. У раста ситуация такая же и тоже вряд ли кто-то кинется писать новую ИДЕ. Но на результат я бы посмотрел.

Автор: Kray74 10.12.14, 15:27
Современные IDE, как правило, - комбайны, работающие с несколькими языками через плагины, так что смысла писать новую IDE под один язык не особо много.

Автор: reinterpret_alexey 25.12.14, 16:43
Хороший С++ класс - это такой, глядя на который появляется чувство скуки. :ph34r:

Автор: korvin 26.12.14, 21:25
Перенастрой подсветку кода, чтоб было нескучно, спроси у Попова как.

Автор: Qraizer 26.12.14, 21:58
Я тебя, надеюсь, правильно понял, korvin?

Автор: korvin 28.12.14, 11:34
Цитата Qraizer @
Я тебя, надеюсь, правильно понял, korvin?

Э-м. Ну я даже не представляю, какие есть варианты понимания моего сообщения, поэтому не знаю, что ответить.

Автор: 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
Цитата korvin @
Ага, 226 MB vs 1 MB.
Это вырвиглазная SAX-версия, которой без слез нельзя пользоваться, тем более, что по скорости все равно проигрывает. А юзабельный DOM-вариант - 243 Мб против D-шного 226.

P.S. Это не баян - неделя всего прошла.
А приведенные тобой ссылки - жалкий лепет. Никто не мешает включать в парсер на C++ такие же куски асма, SIMD и прочие оптимизации, но пока как-то слабо. ;)

Кроме того я выше описал чисто D-шную фичу.

Добавлено
korvin, но вообще обсуждение доставляющее, спасибо за ссылку :D :D :D

Автор: 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'шных. =) И это сильно решает, на самом деле.

Цитата applegame @
но вообще обсуждение доставляющее, спасибо за ссылку :D :D :D

Всегда пожалуйста.

Автор: MyNameIsIgor 22.10.15, 23:04
Цитата applegame @
Случилась перемога

Перемога имеет привычку превращаться в зраду.
Цитата applegame @
JSON-парсер написанный на D стал самым быстрым JSON-парсером среди всех языков, обогнав более чем в два раза (!) предыдущего чемпиона RapidJSON написанного на C++.

Трудно без профилирования сказать, где самое слабое место SAX варианта. Но сама идея некую схему JSON интегрировать в парсер мне понравилась. Если дело действительно в лишних вызовах обработчика в SAX, то есть есть мнение, что встраивание схемы даже во время исполнения даст тот же результат. Во время компиляции в C++ можно использовать для этого constexpr. В любом случае я над этим поразмышляю - здесь ещё может быть чёткое/нечёткое соответствие схеме, опциональные поля, действия для неуказанных в схеме полях... Интересно, короче.
Цитата applegame @
Никто не мешает включать в парсер на C++ такие же куски асма, SIMD и прочие оптимизации, но пока как-то слабо.

Это серьёзно аргумент за D? :jokingly:
Цитата applegame @
Это вырвиглазная SAX-версия, которой без слез нельзя пользоваться, тем более, что по скорости все равно проигрывает. А юзабельный DOM-вариант - 243 Мб против D-шного 226.

Стоп-стоп. Чемпион никакой DOM не даёт, а фактически массив десериализованных структур. Здесь, кстати, используется рефлексия, которая для C++ пока только в виде предложений.
А вот DOM версия на D даёт результат 12.42 секунд и 1417.1 Mb против C++ DOM 0.94 секунды и 243.6 Mb. Это многое говорит о кодогенерации и потреблении памяти D. И именно эти два примера эквивалентны по функционалу, ибо мы вовсе не всегда знаем структуру JSON.
Цитата korvin @
Чего? Какой SAX/DOM у JSON?

Ну, просто такие выражения. Имеется в виду способ парсинга.

Автор: applegame 23.10.15, 05:29
Цитата korvin @
Чего? Какой SAX/DOM у JSON?

Условное название способа парсинга. Можно сказать pull/push парсер, если тебе так больше нравится.
Цитата korvin @
Не слабо, а нафиг никому не упало в современном мире. D'шники просто живут в прошлом веке. =)
бла-бла-бла...
Если не можем обогнать, скажем, что это просто не нужно :lool:
На самом деле другим еще как упало, народ возбудился и начал реагировать, например тот самый С++ RapidJSON SAX бенчмарк пояаился буквально вчера.
Цитата korvin @
Зато компилятор Go установить на винду (и, возможно, на осх) значительно проще, чем любой из трёх D'шных. =) И это сильно решает, на самом деле.
Ну это явная ложь. DMD ставится на линупс, макось и винду не сложнее чем Go. Качается бинарный пакет и устанавливается стандартными средствами OS. Для винды это обычный exe-установщик. GDC и LDC - это да на винду поставить еще тот гемор.
Цитата MyNameIsIgor @
Перемога имеет привычку превращаться в зраду.
Ага, именно поэтому это перемога, а не победа. :)

Цитата MyNameIsIgor @
Стоп-стоп. Чемпион никакой DOM не даёт, а фактически массив десериализованных структур. Здесь, кстати, используется рефлексия, которая для C++ пока только в виде предложений.
А вот DOM версия на D даёт результат 12.42 секунд и 1417.1 Mb против C++ DOM 0.94 секунды и 243.6 Mb. Это многое говорит о кодогенерации и потреблении памяти D. И именно эти два примера эквивалентны по функционалу, ибо мы вовсе не всегда знаем структуру JSON.
По показателям потребления памяти RapidJSON SAX бенчмарк не эквивалентен, потому что не запоминает результаты парсинга. Если еще заполнять массив, а потом в цикле считать сумму как сделано в D-шном бенче, то результаты потребления памяти и скорости ухудшатся.
Что же касается "честного" DOM-парсера, то то что приведено в бенчмарке - это встроенный в стандартную либу достаточно убогий JSON-парсер, который устарел и планируется к замене. Самый быстрый на данный момент "честный" DOM-парсер на D - это кандидат в стандартную либу - std.data.json. Его в бенче нет, надо сделать соответствующий pull-request.
Память он кушает также в районе 200Мб (фктически массив для хранения результатов парсинга), но по скорости уступает раза в три RapidJSON. Тут да, таки зрада. :D

Автор: 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
Цитата applegame @
Обработчики - это очень неудобно

Это не вопрос удобства, это вопрос необходимости, о чём нам говорит потребление памяти при SAX.

Автор: applegame 23.10.15, 07:55
Цитата MyNameIsIgor @
Цитата applegame @
Обработчики - это очень неудобно

Это не вопрос удобства, это вопрос необходимости, о чём нам говорит потребление памяти при 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 @
Если дерево, то обработчики в том или ином виде будут присутствовать, это да. Но деревья как правило парсятся целиком

Как правило вообще всё парсят целиком и не имеют проблем. Я говорю о тех случаях, когда проблемы возникнуть могут.
Цитата applegame @
чем городить обработчики токенов

Я и не хочу обрабатывать токены. Я хочу реагировать на свойства так же, как внутри себя реагирует этот парсер на D, только делать это по событийной модели с обратными вызовами.

Автор: applegame 23.10.15, 10:55
Цитата MyNameIsIgor @
Цитата applegame @
чем городить обработчики токенов

Я и не хочу обрабатывать токены. Я хочу реагировать на свойства так же, как внутри себя реагирует этот парсер на D, только делать это по событийной модели с обратными вызовами.

А зачем событийная модель? Просто нравится такой подход, и/или потому что на плюсах иначе не сделаешь?

Автор: MyNameIsIgor 23.10.15, 12:26
Цитата applegame @
А зачем событийная модель?

Говорю же - из-за потребления памяти. Если уж мы в сотых долях секунды соревнуемся, то сотнями мегабайт раскидываться некрасиво.
Цитата applegame @
Просто нравится такой подход, и/или потому что на плюсах иначе не сделаешь?

На 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 @
Если не можем обогнать, скажем, что это просто не нужно :lool:

"Если не можем привлечь чем-то полезным, будем кричать о размере." :lool:

Цитата applegame @
На самом деле другим еще как упало, народ возбудился и начал реагировать, например тот самый С++ RapidJSON SAX бенчмарк пояаился буквально вчера.

Да-да, мужики любят меряться, а толку? Никто не станет из-за этого менять язык, парсинг JSON далеко не самое узкое место в вебсервисе.

Цитата applegame @
Ну это явная ложь. DMD ставится на линупс, макось и винду не сложнее чем Go. Качается бинарный пакет и устанавливается стандартными средствами OS. Для винды это обычный exe-установщик. GDC и LDC - это да на винду поставить еще тот гемор.

Вот только в этом супер-пупер бенчмарке победил GDC, а DMD выдаёт обычный тормозной код. Ты ж читал тему на ЛОРе.

Автор: applegame 24.10.15, 08:59
Цитата korvin @
"Если не можем привлечь чем-то полезным, будем кричать о размере." :lool:
Полезность вопрос спорный, кому полезно, кому нет, а вот размер - вопрос бесспорный. :P
Цитата korvin @
Да-да, мужики любят меряться, а толку? Никто не станет из-за этого менять язык, парсинг JSON далеко не самое узкое место в вебсервисе.
Да-да толку нет, поэтому бенчмарки по любому поводу встречаются на каждом углу. Факт, по существу тебе сказать-то и нечего.
Кроме того, писькомерство часто заставляет мужиков совершенствоваться. Вон глядишь MyNameIsIgor напишет свой парсер JSON, который переможет всех, попутно исследовав интересные технологии программирования.
Цитата korvin @
Вот только в этом супер-пупер бенчмарке победил GDC, а DMD выдаёт обычный тормозной код. Ты ж читал тему на ЛОРе.
Дык и бенч победил в линупсе, а не в винде. В бубунте gdc - один из стандартных пакетов и устанавливается не сложнее g++. Но какое это имеет отношение к этому
Цитата 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
Цитата D_KEY @
applegame, а ты прочёл? На C++ можно реализовать так же?

Там используется рефлексия и CTFE, первое в C++ отсутствует, а второе сильно ограничено. Кроме того там используются некоторые возможности шаблонов, отсутствующие в C++, для реализации удобного API.
Поэтому так же не получится, но похожим образом, полагаю, можно.
Ассемблерные вставки, на которые тыкают некоторые на лоре, на самом деле всего лишь работа с SSE. Причем они завернуты в условную компиляцию, поэтому на платформах не поддерживающих SSE, парсер работать будет, но не так быстро.

Автор: D_KEY 24.10.15, 22:29
Цитата applegame @
Поэтому так же не получится, но похожим образом, полагаю, можно.

Т.е. похоливарить-то не о чем?

Автор: MyNameIsIgor 24.10.15, 22:54
Цитата applegame @
CTFE, первое в C++ отсутствует, а второе сильно ограничено. Кроме того там используются некоторые возможности шаблонов, отсутствующие в C++, для реализации удобного API

Подробнее - что такого дало CTFE, и что за отсутствующие возможности шаблонов?

Автор: applegame 25.10.15, 07:53
Цитата D_KEY @
Т.е. похоливарить-то не о чем?
Ну а как ты хотел? Все что угодно реализованное на языке X можно похожим образом сделать на языке Y. Но, похоливарить действительно особо не о чем. Просто для информации, как можно с пользой применить некоторые особенности D.
Цитата MyNameIsIgor @
Подробнее - что такого дало CTFE, и что за отсутствующие возможности шаблонов?
Например передача строки в качестве параметра шаблона (название поля) или уже упомянутый форвардинг функций через opDispatch. Насчет CTFE, я похоже погорячился, buildRemapTable, которая по сути и занимается рефлексией (разбором структуры), все же не обычная функция (хотя и могла бы быть таковой), а шаблон, но тем не менее она возвращает CT-константу - список строк, что опять же невозможно в C++. Или возможно?

Автор: MyNameIsIgor 25.10.15, 13:41
Цитата applegame @
Например передача строки в качестве параметра шаблона (название поля)

И почему её надо передавать именно параметром шаблона?
Цитата applegame @
Насчет CTFE, я похоже погорячился, buildRemapTable, которая по сути и занимается рефлексией (разбором структуры), все же не обычная функция (хотя и могла бы быть таковой), а шаблон, но тем не менее она возвращает CT-константу - список строк, что опять же невозможно в C++. Или возможно?

Ну, с constexpr функция есть такая сложность, что динамическое выделение памяти невозможно, потому нельзя приемлемым способом вернуть список, который по длине и хранимым значениям будет зависеть от переданного в функцию аргумента. Но это можно сделать в зависимости от шаблонного аргумента constexpr функции. Потому камнем преткновения остаётся рефлексия. Если пофантазировать, что предложение комитету уже где-то реализовано, то там такое возможно.
Цитата applegame @
форвардинг функций через opDispatch

Ценность это фичи вообще не могу оценить. В чём смысл, если компилятор всё равно ничего проверить не в состоянии? И что делать, если мне надо обратиться по имени свойства, полученному во время исполнения?

Автор: applegame 25.10.15, 16:33
Цитата MyNameIsIgor @
И почему её надо передавать именно параметром шаблона?
Чтобы не обрабатывать названия полей 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, что бывает чуть менее, чем всегда.

А что входит в понятие "обрабатывать"?
Цитата applegame @
А что нужно проверять компилятору?

Я о том и говорю - он ничего не может. Потому это возможность никак не влияет на возможности языка, просто синтаксическая фишка, ценность которой лично для меня сомнительна.

Автор: amk 25.10.15, 21:40
Похоже, если строку обрабатывает код, написанный программистом, это называется рунтайм, а если точно такой же, но подставленный компилятором, то это уже рунтаймом не называется.

Автор: applegame 26.10.15, 08:04
Цитата MyNameIsIgor @
А что входит в понятие "обрабатывать"?
Посмотрел код парсера, там действительно выгода не очень большая, но таки есть, а именно, длина имени поля известна 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
Цитата Qraizer @
Танунафик эту динамическую типизацию с run-time рефлексией.
Дык в D статическая типизация со статической же рефлексией.

Автор: jack128 26.10.15, 13:12
Цитата Qraizer @
поэтому на чистом IDispatch, без библиотек и TLB.


user posted image

Автор: 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 @
Что мне не понравилось в D - так это засилье строк. А правильно работать с AST как в Lisp или Nemerle.
Это да, строковые миксины невероятно уродливы, но таки лучше чем ничего. Есть драфт с претензией на приличные макросы и даже ключевое слово macro зарезервировано, но так как это далеко не самое ужасное в D, то запил его отложен на неведомые времена.
Цитата 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
Цитата Flex Ferrum @
Ну ты же понимаешь, что при желании всё это можно сделать и на C++.
Интересно как можно compile-time посчитать длину строки передаваемой как параметр функции, которая парсит соответствующий json-объект?

Автор: MyNameIsIgor 27.10.15, 15:23
Цитата applegame @
Цитата Flex Ferrum @
Ну ты же понимаешь, что при желании всё это можно сделать и на C++.
Интересно как можно 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
Цитата applegame @
Исправьте, если не затруднит:

Я вот об этом уже говорил
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    calc<sum<N>(ch)>

Не получится аргумент функции запихнуть в шаблон.

Автор: applegame 27.10.15, 20:44
Цитата MyNameIsIgor @
Не получится аргумент функции запихнуть в шаблон.
В том то и дело, даже несмотря на то что этот аргумент по идее известен 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 @
Дать доступ к AST, возможность его обходить, конструировать. Как во время компиляции, так и во время исполнения. Как в Nemerle.
В том же C# (.NET) есть такая возможность, но только во время исполнения. Во многом на этом работает LINQ.
А как это связано с шаблонами и прочей уже реализованной метапрограммируемой фигней в D? Доступ к AST и гигиеничные макросы могут добавить, и что, после этого отвращение исчезнет?

Автор: MyNameIsIgor 28.10.15, 13:27
Цитата applegame @
А как это связано с шаблонами и прочей уже реализованной метапрограммируемой фигней в D? Доступ к AST и гигиеничные макросы могут добавить, и что, после этого отвращение исчезнет?

Это связано, потому что пропагандируется метапрограммирование на шаблонах и строках вместо того, чтобы изначально в новом языке сделать цивилизованный способ. Это ахтунг. Это наследие останется навсегда.

Автор: applegame 28.10.15, 14:27
Цитата MyNameIsIgor @
Это связано, потому что пропагандируется метапрограммирование на шаблонах и строках вместо того, чтобы изначально в новом языке сделать цивилизованный способ. Это ахтунг. Это наследие останется навсегда.
Ага, теперь мне понятна ваша точка зрения. Со своей стороны могу сказать следующее:
Макросы заметно сложнее, чем шаблоны, поэтому (со слов знакомых) используются редко в небиблиотечном коде. D-ешные же шаблоны настолько просты и читабельны (в отличие от шаблонов C++), что их используют постоянно, практически в любом коде.
Пожтому я не считаю отсутствие макросов каким-то очень уж серьезным недостатком. Кроме того слишком гибкие макросы - прямой путь к
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 @
Макросы заметно сложнее, чем шаблоны, поэтому (со слов знакомых) используются редко в небиблиотечном коде.

:lool:
Цитата applegame @
LINQ можно успешно реализовать и без макросов.

Он и реализован без макросов :-?
Цитата applegame @
Что касается Nemerle, то там действительно много интересных фич (после изучения Haskell это стало особо ясно), но у меня вызывает отвращение .NET/Mono. Поэтому Nemerle сразу был исключен мною из кандидатов на следующий проект.

Я и не рекомендовал Nemerle. Но его основные достоинства вовсе не функциональщина, а метапрограммирование.
Цитата applegame @
В целом после реального опыта использования D в коммерческом продакшн проекте, могу сказать следующее

А я вот не стал его использовать. Когда-то возлагал на него надежды, но он разочаровал. Язык пытается объять необъятное, противоречив. В качестве конкурента C/C++ себя не оправдал, т.к. не следует принципу нулевой стоимости.
В этом смысле пока что лучше всех выглядит Rust, Go слишком примитивен, остальные просто маргинальные.

Автор: applegame 28.10.15, 15:15
Цитата MyNameIsIgor @
Язык пытается объять необъятное, противоречив.
Верно подмечено, так и есть.
Цитата MyNameIsIgor @
В этом смысле пока что лучше всех выглядит Rust
Отпугивает отсутствие исключений и обилие unwrap().

Добавлено
Цитата MyNameIsIgor @
В качестве конкурента C/C++ себя не оправдал, т.к. не следует принципу нулевой стоимости.
Это о "принцип абстракции с нулевой стоимостью"? Сборщик мусора нарушает этот принцип?

Автор: MyNameIsIgor 28.10.15, 15:20
Цитата applegame @
Это о "принцип абстракции с нулевой стоимостью"? Сборщик мусора нарушает этот принцип?

Это "не плачу за то, чего не использую". Как я понимаю, на практике полностью отключить сборку мусора в D нереально.

Автор: DarkEld3r 28.10.15, 15:27
Цитата applegame @
Кроме того слишком гибкие макросы - прямой путь к
Это очень спорный тезис. Причём противники буквально чего угодно (перегруженных функций и операторов, шаблонов и т.д.), применяют его. Как правило оказывается, что пишут эти люди на языке(ах), где обсуждаемой фичи нет. Тут впору вспомнить о "парадоксе блаба", хотя я и не очень люблю этот аргумент.

Можно зайти с другой стороны - плюсовые шаблоны применяются для метапрограммирования как раз потому что специализированного инструмента в языке не имеется. Результат зачастую не сильно читаемым получается. Нормальные макросы как раз могут сделать ситуацию лучше, ну а "неправильно" и неуместно можно применять что угодно.

К сожалению, я не знаю перспективных языков, претендующих на нишу С++, с действительно хорошим метапрограммированием (уровня Nemerle). Rast хоть и нравится в целом, но имеет в этом отношении немало проблем.

Цитата applegame @
Отпугивает отсутствие исключений и обилие unwrap().
Обилие unwrap - это фича. А вот с исключениями и правда досадно, тем более, что их "нет" исключительно из-за упрямства. В том смысле, что в языке имеется всё необходимое кроме сахара для удобной обработки.

Автор: applegame 28.10.15, 15:44
Цитата MyNameIsIgor @
Как я понимаю, на практике полностью отключить сборку мусора в D нереально.
Реально. Но придется отказаться от многих встроенных приятных вещей и от половины стандартной библиотеки. Тем не менее есть либы совсем не использующие 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 @
Реально. Но придется отказаться от многих встроенных приятных вещей и от половины стандартной библиотеки.

Разве это реальная практическая альтернатива?
Цитата applegame @
очередной атрибут

Нагромождение фич какое-то...
Цитата applegame @
Можно ли вообще отказаться от шаблонов/дженериков в пользу макросов?

Нет. Потому что они решают разные задачи.

Автор: DarkEld3r 28.10.15, 16:11
Цитата applegame @
Ну D-шные шаблоны вполне читаемы. Макросы мне представляются тяжелой артиллерией для каких-то особо сложных случаев.
Но ведь найдутся случаи когда даже D-шные шаблоны окажутся недостаточно мощными?..
Ведь и плюсовые шаблоны для ряда применений отлично подходят, а часто и без них жить можно, но иногда требуется большее.

Цитата applegame @
Можно ли вообще отказаться от шаблонов/дженериков в пользу макросов?
Это в контексте раста/плюсов или в каком-нибудь абстрактном языке? Имхо, это разные инструменты и хорошо иметь и то и другое.

Цитата applegame @
Странная какая-то фича, и, насколько я понял, это обилие unwrap() как раз и есть следствие отсутствия исключений, нет?
Ну фича (спорная) в том, что обработка ошибок происходит явно.

Относительно отсутствия исключений - есть паника, которая точно так же раскручивает стек, вызывает деструкторы и т.д. Есть возможности её перехватить/обработать. Нет "только" удобного способа проверить к какому типу исключение относится. Может когда-то дойдут до того, что это тоже нужно, ведь изначально панику можно было обработать только на границе потоков.

Автор: applegame 28.10.15, 16:17
Цитата MyNameIsIgor @
Разве это реальная практическая альтернатива?
Да, реальная. И становится все реальней. Фобос (стандартная либа) все больше и больше "ренджифицируется", что делает ненужными аллокации памяти вообще. Лямбды далеко не всегда требуют аллокаций, а там где требуют можно заменить на аналог std::function. Получаются эдакие плюсы на стероидах. Посмотрим что будет через полгода.
Цитата MyNameIsIgor @
Нагромождение фич какое-то...
Да, атрибутов нагородили мама не горюй.

Добавлено
Цитата DarkEld3r @
Но ведь найдутся случаи когда даже D-шные шаблоны окажутся недостаточно мощными?
Бывает такое но редко. Строковые миксины 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}>
    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&&          );
    /* ... */
    };
В принципе, выглядит читабельно и, будучи Стандартным, избавляет от разгребания велосипедов C++03, а что ещё надо-то?
Вот только я себя никак не приучу их юзать, и потому не знаю, насколько этого хватает. Вон, для A<>::A() чуток не хватило.

Автор: D_KEY 29.10.15, 08:48
Цитата Qraizer @
В принципе, выглядит читабельно

:D

Это читабельно для тех, кто хорошо разбирается с шаблонами и знает паттерны метапрограммирования с их использованием.

А так у меня ещё есть надежды хотя бы на concepts lite в 17...

Автор: Flex Ferrum 29.10.15, 16:45
Цитата Qraizer @
В принципе, выглядит читабельно и, будучи Стандартным

По-моему ты только что изобрёл фичу C++11 под названием Inheriting constructor.

Добавлено
Цитата D_KEY @
А так у меня ещё есть надежды хотя бы на concepts lite в 17...

Да вроде должны быть.

Автор: Qraizer 29.10.15, 18:53
Цитата Flex Ferrum @
По-моему ты только что изобрёл фичу C++11 под названием Inheriting constructor.
Ага. Ничего проще в качестве примера не придумалось.

Автор: korvin 29.10.15, 19:18
Цитата applegame @
Кроме того слишком гибкие макросы - прямой путь к

Какие макросы слишком гибки на твой взгляд?

Добавлено
Цитата applegame @
Странная какая-то фича, и, насколько я понял, это обилие unwrap() как раз и есть следствие отсутствия исключений, нет?

Скорее это следствие отсутствия do-нотации. Впрочем, если не ошибаюсь, макрос try! там как-то помогает.

Автор: applegame 29.10.15, 20:00
Цитата korvin @
Какие макросы слишком гибки на твой взгляд?
Макросы того же 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
Цитата korvin @
Впрочем, даже в динамически типизированных Scheme и CL получишь ошибку компиляции.
Как, если тип становится известным только в run-time?
Цитата korvin @
Просто Ruby --- это поделие для хипстеров-студентов. =)
Просто Ruby - некомпилируемый язык, что впрочем никак не противоречит твоему утверждению :D

Добавлено
P.S. Только что прочитал, что в Go даже дженериков нет. Ужоснах.

Автор: korvin 30.10.15, 22:27
Цитата applegame @
Как, если тип становится известным только в run-time?

Макроэкспанд происходит во время компиляции и макросы с типизацией никак не связаны.

Цитата applegame @
P.S. Только что прочитал, что в Go даже дженериков нет. Ужоснах.

Ну ты и слоупок. Тем не менее Go уже в "продакшене" (из общеизвестных проектов --- Docker), а D'шники всё еще меряются скоростью парсинга JSON. =)

Автор: applegame 31.10.15, 06:32
Цитата korvin @
Цитата applegame @
P.S. Только что прочитал, что в Go даже дженериков нет. Ужоснах.

Ну ты и слоупок. Тем не менее Go уже в "продакшене" (из общеизвестных проектов --- Docker), а D'шники всё еще меряются скоростью парсинга JSON. =)

Это ни разу не показатель качества языка. На похапе мульёны общеизвестных проектов.

Автор: Бобёр 01.11.15, 07:22
Цитата
Это ни разу не показатель качества языка.

Вероятно, это показатель качества всей инфраструктуры.
Мне, например, D не нужен. Если надо написать такое "супер быстрое" - это это C/C++, а если надо быстро написать - то C# или python. В зависимости от обстоятельств. Зачем учить ещё один язык, если в моей любимой платной IDE его нету.

Автор: applegame 01.11.15, 08:43
Цитата Бобёр @
Вероятно, это показатель качества всей инфраструктуры.
Скорее это показатель легкости изучения и истоических факторов.
Цитата Бобёр @
Мне, например, D не нужен. Если надо написать такое "супер быстрое" - это это C/C++, а если надо быстро написать - то C# или python. В зависимости от обстоятельств. Зачем учить ещё один язык, если в моей любимой платной IDE его нету.
Ну смотря что-ты пишешь. Допустим если нужен супер быстрый веб-сервис. C/C++ плохо подходят для этого, питон тормозной. Кто-то выберет Java, кто-то Go, ну а я выбрал D.
А любимая платная IDE это какая?

Автор: Бобёр 01.11.15, 10:22
Visual Studio вестимо.

Цитата
Допустим если нужен супер быстрый веб-сервис. C/C++ плохо подходят для этого, питон тормозной.

Почему же плохо подходит. есть boost::asio. Оно реально вполне такое себе.
Правда, на golang это вообще превращается в детскую забаву, это правда. Не знаю как на D, на golang сделать http сервер можно минуты за 3 примерно.

Автор: applegame 01.11.15, 10:57
Цитата Бобёр @
Visual Studio вестимо.
Ну тогда на самом деле поддерживает, не из коробки конечно, но без особого геморроя - VisualD
Цитата Бобёр @
Почему же плохо подходит. есть boost::asio. Оно реально вполне такое себе.
Да, это отличая либа, когда-то я активно ей пользовался. Простой веб-сервис на ней написать не сложно, а вот для более сложного придется ваять много обвязки.
Цитата Бобёр @
Правда, на golang это вообще превращается в детскую забаву, это правда. Не знаю как на D, на golang сделать http сервер можно минуты за 3 примерно.
На чистом D + стандартные либы писать http-сервер не намного проще чем на голом C++ + стандартные либы. Но использовав D-шный библиотечный менеджер DUB можно поднять http-сервер за те же считанные минуты. С применением vibe.d простецкий http-сервер на D пишется примерно так:
<{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 @
а по скорости практически идентичен

Это чем-то подкреплено?

Автор: applegame 01.11.15, 12:57
Цитата MyNameIsIgor @
Это чем-то подкреплено?
Да, подкреплено.
Первое: эмпирически выводится, что для идентичного кода 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'а взломали? :D

Автор: 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-а.

Цитата Qraizer @
Кого? Оперу с Хромом? Вивальди на том же движке, кстати.

Вообще не понимаю, о чем ты.

Автор: 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 @
Похапе уже не менее десяти лет уверенно в продакшне, а п факту, почти с рождения; пистон практически основной скрипто-(и не только) язык в никсах (Дишники хотят эту нишу?), после шелла. Про C++ смешно, уже пару десятков лет в продакшне. Да что там. Go уже в продакшне.
И что дальше? То что быдлокодеры очень любят PHP не делает его удобным языком. Жабаскрипт - ну очень популярный язык, что не мешает ему быть говном. XML, один из худших языков разметки - весьма активно используется в продакшене. Популярность и качество практически не коррелируют друг с другом. Неужели тебе это непонятно? Вот ты например, насколько я помню, весьма одобряешь Plan 9. По твоей же логике оно полное говно, потому что никто его не использует, а все сидят на Win/Mac/Linux/BSD.

А D тоже есть в продакшене, я приводил пример и не один. Я сам работаю с D в продакшне. Переписал проект с Ruby на D, потому что тормозило безбожно.
Цитата korvin @
По существу я уже спрашивал: на какую нишу претендует Ди. Вроде, это уже обсуждали, похоже, ничего не изменилось: Дишники продолжают пытаться мерятся прибором в мире, где больше ценится результат, а не размер инструмента. Всё равно, что доказывать, что Хаммер круче лишь потому, что шире.
Ерунда. Я приводил ссылки с результатами из реальной жизни, а не с голым писькомерством. В вопросе же абстрактного меряния прибором дишники ничем не отличаются от сишников, плюсовиков, хаскелистов и всех прочих языкистов. Все одинаковы. Как бы тебе не хотелось обратного.

Автор: Qraizer 02.11.15, 03:12
Цитата applegame @
Вообще не понимаю, о чем ты.
____________________.PNG (, : 701) ___________________________________________.PNG (, : 622)

Автор: applegame 02.11.15, 05:09
Это что-то у тебя. У меня открывается любым браузером.

Автор: OpenGL 02.11.15, 05:35
Может вирус в компе блокирует доступ к некоторым сайтам некоторым приложениям? О том, что вивальди является браузером вирусописатели просто не были в курсе? :)
А с турбо-режимом в опере работает?

Автор: Qraizer 02.11.15, 12:58
У меня? Вирус? :lool:

Добавлено
Кстати, Престо-Опера тоже не робит. А Вивальди тоже на вебките.

Автор: D_KEY 02.11.15, 14:48
Цитата applegame @
И что дальше? То что быдлокодеры очень любят PHP не делает его удобным языком. Жабаскрипт - ну очень популярный язык, что не мешает ему быть говном. XML, один из худших языков разметки - весьма активно используется в продакшене. Популярность и качество практически не коррелируют друг с другом.

А что ты называешь качеством применительно к языкам программирования?

Разве не для решения задач нужны языки? Разве они имеют самостоятельную ценность?

Автор: applegame 02.11.15, 17:13
Цитата D_KEY @
А что ты называешь качеством применительно к языкам программирования?
Например, количество и критичность ошибок дизайна, скорость написания кода, читаемость, уровень сложности поддержки и т.д.
Цитата D_KEY @
Разве не для решения задач нужны языки? Разве они имеют самостоятельную ценность?
Мне непонятно, что ты этим хотел сказать. Очевидно, что ценность языка выявляется в удобстве использования его для решения задач.

Добавлено
Цитата Qraizer @
У меня? Вирус? :lool:

Я бы на твоем месте не стал бы так легкомысленно относиться к этой угрозе. И на старуху бывает проруха. >:-[

Автор: D_KEY 02.11.15, 17:45
Цитата applegame @
Например, количество и критичность ошибок дизайна

А что за ошибки дизайна? Можно пример? И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны?

Цитата
скорость написания кода, читаемость, уровень сложности поддержки и т.д.

Достаточно субъективные вещи. Т.е. опираться объективно мы тут можем только на статистику, в данном случае - на всю ту же популярность.

Цитата
Очевидно, что ценность языка выявляется в удобстве использования его для решения задач.

Но если мы убираем популярность, то как же объективно оценить "удобство"?

Если D такой удобный, то почему им так мало пользуются?

Добавлено
Приведу пример. Мне не нравится Go, но я не могу отрицать, что он зацепил многих и на нем уже пишут серьёзные проекты, которые используются в реальных системах. Это значит, что go полезен, что он смог привлечь внимание существенной части разработчиков и оказался удобен(чтобы я сам не думал по этому поводу и каким бы убогим не считал этот язык).

Автор: applegame 02.11.15, 18:50
Цитата D_KEY @
А что за ошибки дизайна? Можно пример?
Не задавай глупых вопросов. Если ты действительно не в состоянии найти в интернетах ошибки дизайна, например PHP, то собственно разговор с тобой можно считать оконченым.
Цитата D_KEY @
Достаточно субъективные вещи. Т.е. опираться объективно мы тут можем только на статистику, в данном случае - на всю ту же популярность.
Есть объективные критерии, а опираться на популярность - весьма глупая затея.
Цитата D_KEY @
Но если мы убираем популярность, то как же объективно оценить "удобство"?
Чтобы оценить съедобность говна, тебе нужно собрать статистику о его популярности в народных массах?
Цитата D_KEY @
Если D такой удобный, то почему им так мало пользуются?
Я точно не знаю. Мое личное мнение - недостаток корпоративной поддержки, а также огромный выбор других языков, которого не было 20 лет назад. В наше время маргинальным языкам очень трудно набрать популярность, если никто не трезвонит о них.
Цитата D_KEY @
Приведу пример. Мне не нравится Go, но я не могу отрицать, что он зацепил многих и на нем уже пишут серьёзные проекты, которые используются в реальных системах. Это значит, что go полезен, что он смог привлечь внимание существенной части разработчиков и оказался удобен(чтобы я сам не думал по этому поводу и каким бы убогим не считал этот язык).
Причина проста - Google. И то, что Go даже при такой поддержке очень тухло набирает популярность - лишний раз доказывает, что он убог.

Закономерно, что с появлением korvin и тебя, разговор опять смещается в совершенно левую плоскость.
При выборе языка мне не интересна популярность, от слова совсем. Мне важны конкретные аргументы за и против.
MyNameIsIgor четко и ясно сказал, что ему не нравится в D, мне тоже дохрена чего не нравится в D и я тоже об этом сказал. Я также четко и ясно сказал, что мне не нравится в Rust и Go.
А ты и korvin, вместо беседы по существу, аппелируете к избитому, глупому аргументу - миллионы не могут ошибаться. Не надоело?

Автор: D_KEY 02.11.15, 19:01
Я сейчас даже не высказал свою позицию, не говоря уже об аргументах :)
Я просто пытаюсь уточнить твою точку зрения.

Добавлено
Цитата applegame @
Есть объективные критерии

Какие?

Добавлено
Цитата applegame @
Чтобы оценить съедобность говна, тебе нужно собрать статистику о его популярности в народных массах?

Если ты хочешь обънктивности, то да. А то получится вкусовщина :)

Добавлено
Цитата applegame @
Причина проста - Google. И то, что Go даже при такой поддержке очень тухло набирает популярность - лишний раз доказывает, что он убог.

Какой такой? Я вот не вижу, чтобы они его особо продвигали.

Исходя из разговоров с адептами, могу сказать, что go, например, удачно подошёл тем, кто время от времени испытывает потребность в быстром создании относительно производительных сервисов, а опыт имеет при этом несколько другой - php/python. Такие специалисты не будут брать C/C++ и вряд ли полезут в Java-мир. Им просто и быстро даётся go, а ещё он позволяет решить их задачи. И Google тут ни при чем. D бы у них не пошёл, как бы и кто бы его не продвигал.

Добавлено
Цитата applegame @
А ты и korvin, вместо беседы по существу, аппелируете к избитому, глупому аргументу - миллионы не могут ошибаться. Не надоело?

Я к этому аргументу не аппелирую, я лишь пытался понять твою логику отрицания фактора популярности.

Автор: applegame 02.11.15, 19:59
Цитата D_KEY @
Какие?
:facepalm: Все. :) Нет никаких объективных критериев. Только популярность решает. Тебе Go не нравится, но ты неправ, так как он популярен.
Цитата D_KEY @
Какой такой? Я вот не вижу, чтобы они его особо продвигали.
Имя Google само по себе очень мощный двигатель. Каждый чих Гугла мгновенно разносится по новостным сайтам и прочим реддитам без всяких усилий с его стороны.
Цитата D_KEY @
Исходя из разговоров с адептами, могу сказать, что go, например, удачно подошёл тем, кто время от времени испытывает потребность в быстром создании относительно производительных сервисов, а опыт имеет при этом несколько другой - php/python. Такие специалисты не будут брать C/C++ и вряд ли полезут в Java-мир. Им просто и быстро даётся go, а ещё он позволяет решить их задачи. И Google тут ни при чем. D бы у них не пошёл, как бы и кто бы его не продвигал.
Я в свое время очень много писал на PHP и мне он очень нравился, я даже пытался его защищать от нападок. Наверное мне тогда очень понравился бы Go, если бы он тогда был. :)
А насчет пошел бы D или не пошел, вопрос спорный. В одном я уверен, если бы например, Microsoft вдруг начал поставлять по умолчанию плагин VisualD вместе со своим VS, то популярность D выросла бы на порядки без каких-либо дополнительных телодвижений со стороны Microsoft.

О кривизне PHP написано множество статей. Мне в свое время понравилась вот эта - PHP: Фрактал плохого дизайна (перевод). Там, на мой взгляд, очень точные и в тоже время забавные метафоры. И заодно есть ответы на твои вопросы.

Автор: DarkEld3r 02.11.15, 20:33
Цитата D_KEY @
И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны?
Нет, это только говорит, что (по сумме параметров) ничего лучше не нашлось. При этом на выбор влияет, в том числе, наличие инструментов, библиотек, готовых специалистов и т.д. Так что новым языкам взлететь действительно нелегко, особенно если это языки "общего назначения" не дающие сильного преимущества в чём-то конкретном.

Ну и я поддержу applegame в том, что это повторение банальностей и не интересно. В конце концов, я уверен, что тут это каждый понимает, а значит можно пофлеймить не отвлекаясь на эти "скучные вещи". :D

Автор: 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/

Прочел. Мда :D
Может быть у участников темы есть какие-то возражения?

:)

Добавлено
Цитата applegame @
Цитата D_KEY @
Какие?
:facepalm: Все. :) Нет никаких объективных критериев.

Да меня твоё мнение интересует. Ты считаешь, что есть объективные критерии, а значит, вероятно, можешь их назвать.

Цитата
Тебе Go не нравится, но ты неправ, так как он популярен.

Почему сразу неправ? Просто необъективен.

Цитата
А насчет пошел бы D или не пошел, вопрос спорный.

Ну конкретно в приведенном мною случае точно не пошёл бы :) Слишком сложен.

Цитата
В одном я уверен, если бы например, Microsoft вдруг начал поставлять по умолчанию плагин VisualD вместе со своим VS

А он бы и начал, если бы было выгодно ;) C++ же поставляет. Хотя и по C++ видно, что к нему внимания меньше, чем когда-то...

Цитата
то популярность D выросла бы на порядки без каких-либо дополнительных телодвижений со стороны Microsoft.

Хм. Популярность, скажем, F# оставляет желать лучшего. А это детище ms, его проповедуют их евангелисты, по нему пишут книги и т.д. и т.п. Не все определяется поддержкой. Людям проще взять C#.

Вообще довольно интересно, почему взлетает тот или иной язык... Это что-то из области психологии/социологии, как мне кажется.

Добавлено
Цитата DarkEld3r @
Цитата D_KEY @
И если мы говорим о популярных языках, разве популярность не говорит о том, что ошибки не существенны?
Нет, это только говорит, что (по сумме параметров) ничего лучше не нашлось.

Ну так это и есть "не существенны" :) Т.е. задачу позволяют решить лучше, чем другие. Даже при наличии недостатков...

Цитата
Так что новым языкам взлететь действительно нелегко, особенно если это языки "общего назначения" не дающие сильного преимущества в чём-то конкретном.

Так может такие языки и не нужны? Естественный отбор, ничего личного.

Цитата
а значит можно пофлеймить не отвлекаясь на эти "скучные вещи". :D


Да я не против. Просто выходит не очень весело.

Автор: DarkEld3r 03.11.15, 10:05
Цитата D_KEY @
Хм. Популярность, скажем, F# оставляет желать лучшего. А это детище ms, его проповедуют их евангелисты, по нему пишут книги и т.д. и т.п. Не все определяется поддержкой. Людям проще взять C#.
Забавно, что я тоже F# в пример привести хотел, правда вывод сделал прямо противоположный. MS особо и не продвигает этот язык, особенно если с шарпом сравнить. Да чего там, мне кажется, что про С++ они и то больше говорят.

Тем не менее, про F# "все", как минимум, знают. Скала на .net не взлетела, а F# худо-бедно живёт как раз потому что есть из коробки и сделан "хозяевами платформы".

Цитата D_KEY @
Ну так это и есть "не существенны" :) Т.е. задачу позволяют решить лучше, чем другие. Даже при наличии недостатков...
Нет, не значит.

Ну и давай всё-таки отделять более-менее объективные достоинства/недостатки и зрелость языка/платформы.

Цитата D_KEY @
Так может такие языки и не нужны? Естественный отбор, ничего личного.
Смотря для чего. Мне они нужны, как минимум, чтобы мозг размять. Опять же, эксперименты отрасль двигают, что тоже хорошо.

Цитата 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 @
И спустя 14 лет существования и развития, услышать "на нём можно быстрый JSON-парсер написать" --- это как-то уныло и не отвечает на вопрос.
Это ты так поставил вопрос сам, а не я. Я уже приводил ссылку на реальный проект с применением vibe.d, но ты же видишь только то, что тебе хочется видеть. У меня есть реальная история успеха перевода проекта с Sinatra (ruby) на vibe.d, с многократным увеличением производительности при примерно таких же расходах на разработку.
Форум 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_KEY @
Просто игнорировать популярность значит отрицать конкурентную борьбу и её плоды.
Что значит игнорировать? Я ж не отрицаю фактор популярность и что это, при выборе языка, довольно много значит. Просто предлагаю не подменять популярностью всё остальное. Если у языка есть объективные достоинства или недостатки, то их можно и нужно учитывать, а не сводить всё к "ну раз он популярнее, то лучше (во всём)".

Тем более, что ты сам говоришь про "определённое время и место". Да, у текущего мейнстрима было, в своё время, были (а может и остались, не важно) преимущества. Вот только сейчас к ним добавилось большое количество библиотек, специалистов, книг, курсов и т.д. Плюс в раскрутку многих языков были вложены немалые ресурсы.

И это всё очень сильно перевешивает чашу в их пользу. Я просто сомневаюсь, что сейчас возможны быстрые революции, а не постепенное наращивание популярности. Вон даже свифт - более продвинутый, продвигается владельцами платформы, активно развивается и всё такое. И то на обжектив-С продолжают и ещё долго будут продолжать писать. И это при том, что язык изначально делался для лёгкой интеграции с имеющейся инфраструктурой.

Если что, я не считаю, что всем нужно бросать "старьё" и бегом браться за новомодные языки. Тем более, что не могу сказать, что хоть один из них меня прямо так "идеально устраивает".

Кстати, в D реализуют понемногу возможность использовать "любые" плюсовые библиотеки. Это здорово может на популярность языка повлиять.

Цитата korvin @
Как языки, не предоставляющие ничего нового, помогают мозги размять? Я-то думал для этого обычно берут языки, сильно отличающиеся от тех, что ты уже знаешь.
Речь о другом шла - не о наличии нового, а о ярко выраженной "практической пользе" и о том, что это помогает для "взлёта" языка. Вот у Go она есть похоже, хотя "принципиально нового" и нет. Ну если мы гороутины таким считать не будем.

И наоборот - в языке могут быть новаторские вещи, но сами по себе, не приносить (очевидной?) пользы.
Скажем, лайфтамы в расте - вроде и полезно и ново (в курсе про Cyclone), но я не уверен, что этого будет достаточно. К счастью, у языке есть и другие приятные вещи.
Или макросы в немерле - удобно и мощно, но похоже люди не ощущают явной необходимости в них.

Цитата korvin @
Ну если на неё не отвечать, то её и будут повторять.
Да, мысль понятна и я, в общем-то более-менее согласен.

Но тут есть нюансы. Скажем по расту есть специальный ресурс с новостями (кстати, у D такое есть?). То есть люди используют язык, пишут всякое разное и делятся опытом. Там и про низкоуровневый опыт пишут и про серво и игровые движки делать пробуют и т.д. То есть информации хватает, просто надо интересоваться, но ведь не будешь всё на форум тащить?

Плюс хватает людей, которые язык (любой) более-менее изучили, но применять на практике не могут или "не хотят". Обсуждать на форуме проще чем тянуть проект. Впрочем, applegame писал же, что D применяет и доволен. Конечно, тут возникнет вопрос "а есть ли реальная польза", но это не всегда легко измерить.

Кстати, как по мне, то даже новости типа обсуждаемой (про "самый быстрый парсер") полезны - напоминают об языке и всё такое.

Добавлено
Цитата D_KEY @
проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать.
Просто из любопытства: уровень как меряется? Количеством кода, "качеством" или популярностью?

Автор: applegame 04.11.15, 18:49
Цитата D_KEY @
applegame, проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать.
Почему для Docker'а был выбран Go - интересный вопрос. Я нашел соответствующую презентацию - http://www.slideshare.net/jpetazzo/docker-...te-docker-in-go и похоже, что выбор был сделан чуть ли не из желания попробовать новый язык. На слайде 26 упоминается D :), авторы даже не знали, что это такое. Потому что о Go кричат на каждом углу, а D никому не известен. А так, кто знает, что было бы если бы авторы при выборе языка посмотрели на бы на D.
Цитата D_KEY @
И не надо путать. Популярность является не аргументом, а скорее критерием. У D было достаточно времени, чтобы показать себя.
Критерием чего? Успешного маркетинга? - полностью согласен :D

Добавлено
Цитата DarkEld3r @
Впрочем, applegame писал же, что D применяет и доволен. Конечно, тут возникнет вопрос "а есть ли реальная польза", но это не всегда легко измерить.
Да не я один. Есть несколько контор работающих с D. Даже пара вакансий есть где-то там далеко :D
Цитата DarkEld3r @
Но тут есть нюансы. Скажем по расту есть специальный ресурс с новостями (кстати, у D такое есть?)
Да, ведет один из активных участников коммьюнити. Даже называется аналогично :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 @
Ну серьезно, если язык выбирают, значит даже с его недостатками он справляется с решением задач.
Да, но это не значит отсутствие и несущественность недостатков.

На мой взгляд, существенный недостаток - это такой, который приводит к невозможности решить задачу или крайне затрудняет ее решение. А ты как считаешь?

Добавлено
Цитата DarkEld3r @
Если у языка есть объективные достоинства или недостатки

Так я предлагаю их таки назвать :D

Цитата
Тем более, что ты сам говоришь про "определённое время и место". Да, у текущего мейнстрима было, в своё время, были (а может и остались, не важно) преимущества. Вот только сейчас к ним добавилось большое количество библиотек, специалистов, книг, курсов и т.д. Плюс в раскрутку многих языков были вложены немалые ресурсы.

И какой из этого можно сделать вывод?

Цитата
Я просто сомневаюсь, что сейчас возможны быстрые революции, а не постепенное наращивание популярности.

Пусть будет постепенное. Я что против? Но за 14 лет можно было себя показать...

Цитата
Вон даже свифт - более продвинутый, продвигается владельцами платформы, активно развивается и всё такое. И то на обжектив-С продолжают и ещё долго будут продолжать писать.

Так это как раз пример того, что популярность далеко не во всем связан с продвижением. Мне, например, свифт не показался интересным языком. Возможно, разработчики просто не видят смысла в переходе.

Цитата
Кстати, в D реализуют понемногу возможность использовать "любые" плюсовые библиотеки. Это здорово может на популярность языка повлиять.

Зависит от качества решения. Но так да. Вообще, им следовало подумать об этом на раннем этапе развития языка.
Проблема с D еще в том, что многие уже "перегорели".

Цитата
Цитата D_KEY @
проекты могут быть разного уровня. Было бы что-то на уровне докера, можно было бы сравнивать.
Просто из любопытства: уровень как меряется? Количеством кода, "качеством" или популярностью?

Объемом решаемых задач, контрибьютерами, комьюнити, компаниями и проектами, которые используют данный проект и т.п.

Добавлено
Цитата applegame @
Цитата D_KEY @
И не надо путать. Популярность является не аргументом, а скорее критерием. У D было достаточно времени, чтобы показать себя.
Критерием чего? Успешного маркетинга? - полностью согласен :D

В данном случае, видимо, неуспешного :)

Но вообще к D это неприменимо. Маркетинг маркетингом, но в определенный момент разработчик выделяет время и пробует новый язык/технологию. И тут уже маркетинг уходит на задний план, а конкретные недостатки и достоинства на первый. Я уже приводил пример с Go. Вот конкретные разработчики, которые таки стали использовать Go, D бы использовать не стали. Языку нужна ниша. Нужны те реальные задачи, которые он позволит решать "лучше"(в каком-то из востребованных смыслов).

Автор: DarkEld3r 06.11.15, 14:09
Цитата D_KEY @
Пусть будет постепенное. Я что против? Но за 14 лет можно было себя показать...
Ну я не собирался защищать именно D. :D
Просто тоже "задела" эта апелляция к популярности.

Ладно, этот спор всё равно зашёл в тупик. Относительно достоинств и недостатков. Думаю, что ты можешь назвать немало раздражающих "мелочей" в С++. Доказывать, что это "существенные недостатки" не собираюсь, тем более, что я сам пишу как раз этом языке, как минимум, "без отвращения". Да и ничего нового мы друг другу не скажем.

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? :D
И таки там не спрашивали Александреску. Там спрашивали вообще, а Алекандреску один из ответивших. Quora - это нечто вроде ответов.майл.сру.

Интересно, чем руководствовались люди называя свой язык, например, "Коррозия Металла"? :)

Автор: korvin 10.11.15, 20:06
Цитата D_KEY @
Мне, например, свифт не показался интересным языком.

Это только если сравнивать его с ЯП общего назначения (хотя Свифт формально тоже является таковым, но мы-то понимаем, что за пределами яблочных осей он никому не нужен, как и Обжектив-Си), но вот в качестве замены Обжектив-Си он более чем хорош.

Автор: DarkEld3r 11.11.15, 15:38
Цитата applegame @
почитываешь forum.dlang.org? :D
Не совсем, конкретно это нашёл на реддите (раз, два). :) Не так уж удивительно, что именно ответ Александреску тиражируют везде, тем более, что оно довольно взвешенным оказалось.

Хотя и на 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".

Впрочем, учитывая разнообразие ответов, мне кажется, что объяснения появились позже самого названия.

Ага, то есть его на самом деле назвали не "Коррозия Металла", а "Ржавчинный гриб"? :D

Автор: applegame 11.11.15, 17:14
Цитата DarkEld3r @
Не совсем, конкретно это нашёл на реддите (раз, два). :)
Вот еще впечатление от 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 @
Лучше бы кто-нибудь рассказал, например, подробности ухода от gc в стандартной библиотеке D, да и несколько муторно отказываться от gc для классов и пр.
Тебе это реально интересно? Эта тема постоянно перетирается на форуме dlang.org
В стандартной либе стараются все максимально 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
Цитата applegame @
Тебе это реально интересно?

Мне интересен потенциал опционального сборщика. Тут же заход немного с другой стороны.

Цитата
В стандартной либе стараются все максимально 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.
Цитата D_KEY @
А это как с GC связано?
Напрямую с GC не связано, но связано с аллокациями. Функции возвращающие ленивые ренджи никогда не делают аллокаций памяти.
Цитата D_KEY @
Вот это грустно. Вроде же все средства для этого есть, просто не реализовали еще?
В стандартной либе вроде есть RefCounted и Unique но они почему-то не работают с классами (не в смысле глючат, а в смысле запрограмиированы не принимать классы).
На форуме идут дискуссии. Александреску помешан на безопасности, а библиотечная реализация таких объектов действительно не может быть полностью безопасной. Ему отвечают: ну и что? Пусть будет небезопасно, живут же всякие shared_ptr/unique_ptr - все довольны. Конечно же все кому сильно надо написали свои велосипеды на эту тему. Ну а Александреска предлагает встроить поддержку RC-объектов непосредственно в язык шобы было ну ваще безопасно. По мне так это перебор. В крайнем случае достаточно изобрести очередной аттрибут, для пометки RC-объектов, чтобы компилятор знал, что это RC и пресекал попытки вынести из комнаты кишки такого объекта.
Цитата D_KEY @
Не понял мысль.
Это относительно большая тема. В 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
Цитата applegame @
В C++ пришлось бы использовать shared_ptr

Зачем, если объект иммутабельный? Все его копии равнозначны. Отдайте в другой поток его копию. И тогда уже нельзя будет поспорить, что производительнее: стек или черепаха GC.
Цитата applegame @
без гарантий иммутабельности, а значит небезопасно

Вы тут вообще мешаете понятия неизменяемости и умные указатели. Это вещи ортогональные. shared_ptr не привносит никакой небезопасности, кроме той, что уже есть в языке.

Автор: D_KEY 12.11.15, 09:39
Цитата applegame @
Эм, потенциал таков, что ты можешь отказаться от GC полностью.

И страдать? :)

Цитата
Какая разница для контейнера откуда взялась память для объектов (если конечно эту память не выделяет сам контейнер)?

Цитата
Что касается аллокаторов, то на данный момнет нет встроенных в стандартную либу контейнеров умеющих использовать аллокаторы.

Так а кто выделяет память? Память для элементов лежит в 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 @
Зачем, если объект иммутабельный? Все его копии равнозначны. Отдайте в другой поток его копию. И тогда уже нельзя будет поспорить, что производительнее: стек или черепаха GC.
Копирование массивов или глубокое копирование объектов содержащих другие объекты - не очень-то производительное решение. Речь идет об указателях на immutable-данные.
Цитата MyNameIsIgor @
Вы тут вообще мешаете понятия неизменяемости и умные указатели. Это вещи ортогональные.
Не совсем ортогональные. Умный указатель не может быть "честно" иммутабельным по определению. А значит не может содержаться в другом иммутабельном объекте.

Цитата D_KEY @
И страдать? :)
Страдать? Не более, чем в C++. Если сначала жил с GC, а тут, опа, и нужно от него отказаться, тогда да, будешь страдать. :)
Цитата D_KEY @
Так а кто выделяет память? Память для элементов лежит в GC?
Эту уже от самого контейнера зависит. Пока все встроенные в стандартную либу контейнеры берут память исключительно у GC. Контейнеры построенные на базе аллокаторов берут память собственно у аллокатора, в качестве которого может выступать также и GC. То есть это уже будут универсальные контейнеры. По умолчанию память хапается у GCAllocator, а там можно переключиться на Mallocator или какой-нибудь FreeListAllocator с бэкендом на том же GCAllocator/Mallocator.
Цитата D_KEY @
Цитата
То есть immutable-объекты можно спокойно распространять по всей программе, в том числе мужду потоками без синхронизации и без счетчика ссылок. Я не представляю как сделать такое поведение объектов без GC.
По мне так управление памятью ортогонально иммутабельности.
Я так не считаю. ИМХО, честную иммутабельность принципиально нельзя сделать без 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 @
Цитата
который при каждом копировании создает write barrier со всеми вытекающими, а так как такие копирования происходят постоянно и в больших количествах

Почему постоянно? Почему в больших количествах? Очень часто тебе вообще достаточно unique_ptr и каких-то очередей/каналов между воркерами. Нет?
Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов. Причем несколько потоков могут одновременно работать с одними и теми же объектами. Объекты регулярно уничтожаются и создаются новые. Можно было действительно просто копировать все целиком и отправлять копии другим потокам, но это я посчитал очень неэффективным в плане производительности, да и зачем, если все иммутабельное, и я могу спокойно слать потокам только указатели на эта данные.
Цитата D_KEY @
Сейчас речь не о холиваре "GC против всех", а о том, насколько хорошо в языке может жить опциональный сборщик.
Хз, по мне "опциональный" не совсем корректное выражение. Сам язык не требует GC, кроме считанных фич. И тут не стоит впрос использовать эти фичи с GC или без. Либо с фичами и с GC, либо без GC и без фич. Лишение этих фич доставляет страдания только тем, кто ими раньше активно пользовался. Скажем плюсовики и раньше не могли взять и склеить два массива специальной конструкцией языка, так что лишение такой возможности в D они даже не заметят.

Автор: MyNameIsIgor 12.11.15, 10:40
Цитата applegame @
Умный указатель не может быть "честно" иммутабельным по определению

Не хватает ещё "внатуре" Что такое "честно" иммутабельный по определению?

Автор: applegame 12.11.15, 10:52
Цитата MyNameIsIgor @
Что такое "честно" иммутабельный по определению?
"Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет.

Автор: D_KEY 12.11.15, 10:56
Цитата applegame @
Умный указатель не может быть "честно" иммутабельным по определению.

Почему не может? И зачем ему быть иммутабельным, если нужен иммутабельный объект, а указатель можно копировать.
Или тебя смущают изменяемые счетчики? Но это внутренние потроха, потокобезопасность же тебе гарантируется.

Цитата
Страдать? Не более, чем в C++.

Ну как не более, если даже контейнеры без GC не работают в D?

Цитата
ИМХО, честную иммутабельность принципиально нельзя сделать без GC.

А почему?

Цитата
Дык, объект-то нифига не иммутабельный, то бишь владелец объекта может его легально изменить (например по ошибке программиста) без сопротивления со стороны компилятора

Там же константные поля. Так что с сопротивлением :)
Покажи код(лучше на C++, чтобы не было недоразумений).

Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов. Причем несколько потоков могут одновременно работать с одними и теми же объектами. Объекты регулярно уничтожаются и создаются новые. Можно было действительно просто копировать все целиком и отправлять копии другим потокам, но это я посчитал очень неэффективным в плане производительности, да и зачем, если все иммутабельное, и я могу спокойно слать потокам только указатели на эта данные.

Цитата
Сам язык не требует GC, кроме считанных фич.

И контейнеров, например :D

Автор: MyNameIsIgor 12.11.15, 10:58
Цитата applegame @
"Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет.

Что такое "действительно не меняет своё внутреннее состояние"? У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи?

Автор: D_KEY 12.11.15, 11:02
Цитата applegame @
Цитата MyNameIsIgor @
Что такое "честно" иммутабельный по определению?
"Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет.

Так какая разница, если тебе предоставляют гарантии корректной работы счетчиков RC в многопоточной среде?

Автор: applegame 12.11.15, 11:30
Цитата D_KEY @
Ну как не более, если даже контейнеры без GC не работают в D?

Цитата D_KEY @
И контейнеров, например :D

Контейнеры - это не D, это библиотеки. В сторонних библиотеках (которые можно поставить дешным пакетным менеджером dub) есть контейнеры с аллокаторами, RC и прочая. То что нет в стандартной - это да печаль и говно.
Цитата D_KEY @
Там же константные поля. Так что с сопротивлением :)
А что будет если владелец уничтожит объект? Например первый поток закончит работу раньше второго?
Цитата MyNameIsIgor @
Что такое "действительно не меняет своё внутреннее состояние"? У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи?
Это гарантия того, что в любой момент времени можно прочитать это состояние и оно всегда будет одним и тем же. Допустим некий компилятор увидев, что данный объект иммутабельный, и со спокойной совестью берет и помещает его в область памяти с защитой от записи. И если Вася вас обманул, то в какой-то момент ваше приложение упадет.

Автор: MyNameIsIgor 12.11.15, 11:37
Цитата applegame @
Это гарантия того, что в любой момент времени можно прочитать это состояние и оно всегда будет одним и тем же. Допустим некий компилятор увидев, что данный объект иммутабельный, и со спокойной совестью берет и помещает его в область памяти с защитой от записи.

Не понимаю, как из гарантии того, что я прочитаю одно и то же состояние, следует, что объект может быть в области с защитой от записи?

Автор: applegame 12.11.15, 11:42
Цитата D_KEY @
Так какая разница, если тебе предоставляют гарантии корректной работы счетчиков RC в многопоточной среде?
Тут дело в безопасности. Зачем, например, нужен модификатор const, если тебе предоставляют гарантии, что эта вот функция, мамой клянус, не изменяет состояние этого вот объекта? То есть то что касается именно shared_ptr, то тут никаких сомнений нет. Я знаю, что он меняет cвое состояние (счетчик), и его константные функции не совсем константные (так как опять же меняют счетчик), но на это можно закрыть глаза, так как это работает. Но если вот этот тип T для меня сделал Вася, то я бы очень хотел, чтобы его const функции были бы на самом деле const. А то я создам immutable глобальную переменную типа T, компилятор запихнет ее в data-сегмент, а тут выяснится, что const-функция оказалась не const и все дело падает в ран-тайме. Нехорошо, Вася. Нехорошо.

Добавлено
Цитата MyNameIsIgor @
Не понимаю, как из гарантии того, что я прочитаю одно и то же состояние, следует, что объект может быть в области с защитой от записи?
не просто прочитаете одно и тоже состояние, а в любой момент времени прочитаете одно и тоже состояние, из чего следует, что никто и никогда не должен изменять эти данные.
Почему бы параноидальному компилятору и не засунуть этот объект в область с защитой от записи? Более того, компиляторы в некоторых случаях так и делают. Например строковые литералы в C++/D "честно" иммутабельные. В линупсе попытка записи в такой литерал приведет к сегфолту.

Автор: MyNameIsIgor 12.11.15, 11:48
Цитата applegame @
не просто прочитаете одно и тоже состояние, а в любой момент времени прочитаете одно и тоже состояние, из чего следует, что никто и никогда не должен изменять эти данные.

Дададада.
Цитата applegame @
Почему бы параноидальному компилятору и не засунут этот объект в область с защитой от записи? Более того компиляторы в некоторых случаях так и делают

На каком основании? С чего вы вообще взяли, что всегда читать одно и то же состояние - это всё равно, что в объект никто не пишет?

Добавлено
Я, конечно, троллю. И знаю, что поскольку в D было слабо вставить зависимые типы, сделали тупо побитовую неизменность, назвали это безопасностью и вот теперь адепты этого недоязыка познают понятие неизменяемости через призму D. Печально, фигли...

Автор: applegame 12.11.15, 12:04
Цитата MyNameIsIgor @
Я, конечно, троллю. И знаю, что поскольку в D было слабо вставить зависимые типы, сделали тупо битовую неизменность, назвали это безопасностью и вот теперь адепты этого недоязыка познают понятие неизменяемости через призму D. Печально, фигли...
А кому было не слабо вставить зависимые типы? Idris? ATS? Такие чисто ситемные языки приближенные к hardware. И совсем не академические. :)
И зря вы так об адептах D. Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше?

Автор: MyNameIsIgor 12.11.15, 12:06
Цитата applegame @
Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше?

Да любой функциональный язык может. Там все сущности иммутабельны, но почему-то не расположены в памяти с защитой от записи. Интересно, почему? :jokingly:

Добавлено
Цитата applegame @
Такие чисто ситемные языки приближенные к hardware. И совсем не академические.

Проблема в том, что если хочется приблизиться к "железу", то чем-то надо жертвовать. Я не понимаю обеспечение безопасности с помощью изъятия у всех кухонных ножей.

Автор: D_KEY 12.11.15, 12:16
Цитата applegame @
Цитата D_KEY @
Там же константные поля. Так что с сопротивлением :)
А что будет если владелец уничтожит объект? Например первый поток закончит работу раньше второго?

Так там же shared_ptr.

Добавлено
Цитата applegame @
Но если вот этот тип T для меня сделал Вася, то я бы очень хотел, чтобы его const функции были бы на самом деле const. А то я создам immutable глобальную переменную типа T, компилятор запихнет ее в data-сегмент, а тут выяснится, что const-функция оказалась не const и все дело падает в ран-тайме. Нехорошо, Вася. Нехорошо.

Это возможно неплохая соломка, но по сути своей гарантии корректной работы в данном случае ничем не отличается от других контрактов. Если Вася тебя обманул в этом вопросе, то где гарантии, что он в принципе корректно реализовал то, что ты используешь?

Автор: applegame 12.11.15, 12:23
Цитата MyNameIsIgor @
Да любой функциональный язык может. Там все сущности иммутабельны, но почему-то не расположены в памяти с защитой от записи. Интересно, почему? :jokingly:
Потому что у всех изъяли, как вы выразились, кухонные ножи. А в каком-нибудь Haskell изъяли также вилки, ложки и иголки.
Цитата MyNameIsIgor @
Проблема в том, что если хочется приблизиться к "железу", то чем-то надо жертвовать. Я не понимаю обеспечение безопасности с помощью изъятия у всех кухонных ножей.
Я тоже этого не понимаю. В итоге имеем монстра D, в который все пичкают и пичкают всякие ненужные хрени вроде якобы безопасного RC. Правильно ругался на Александреску один из адептов D: прежде чем думать о безопасном аж жуть RC, сделайте обычный не совсем безопасный RC а-ля шаред_птр, и не совсем безопасные контейнеры с аллокаторами. А они вместо этого дружно ломают голову над тем как впихнуть невпихуемое.
Цитата D_KEY @
Так там же shared_ptr.
Во второй поток ты передал ссылку на сам объект а не 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
Цитата applegame @
Во второй поток ты передал ссылку на сам объект а не shared_ptr.

Сорри, я неправильно объяснил. Это не второй поток. Или все потоки работают с shared_ptr или есть отдельные воркеры, которые не являются владельцами и просто читают объект по ссылке и есть какой-то агрегатор, который владеет объектом и ожидает завершения воркеров.

Автор: Qraizer 12.11.15, 12:55
Цитата applegame @
Я понимаю, что иммутабельность через битовую неизменность - это суррогат, но можете ли вы предложить что-нибудь лучше?
Константные объекты вместо константных ссылок на них, не? А честная она там или нет, это никому не интересно. Если даже и есть внутри mutable-поля, это проблемы сугубо автора класса и компилятора.

Автор: applegame 12.11.15, 13:10
Цитата Qraizer @
Константные объекты вместо константных ссылок на них, не?
Тоже предлагаешь копировать константный массив на сто элементов?
Цитата Qraizer @
А честная она там или нет, это никому не интересно. Если даже и есть внутри mutable-поля, это проблемы сугубо автора класса и компилятора.
А если такой объект расположен в ПЗУ? Компилятор же не в состоянии распознать честная иммутабельность или нет? Написано immutable, значит immutable.

Автор: Qraizer 12.11.15, 13:52
Зачем копировать? Создал константный объект и радуешься. Хочешь – копируй, хочешь – ссылайся.
Если объект расположен в ПЗУ, он по определению не может быть создан конструктором, потому что тот предполагает модификацию полей объекта для придания ему некоего состояния. В таком случае он должен быть туда помещён уже сконструированным, и для работы с ним достаточно ссылки.

Автор: MyNameIsIgor 12.11.15, 14:14
Цитата applegame @
Тоже предлагаешь копировать константный массив на сто элементов?

Это же был пример, т.к. вы говорили про "маленькие иммутабельные объекты" :facepalm:
Вариантов может быть много.

Добавлено
Во, кстати, а какой GC сейчас использует D? Если как и раньше BoehmGC, то это fail.

Автор: applegame 12.11.15, 14:22
Цитата Qraizer @
Зачем копировать? Создал константный объект и радуешься. Хочешь – копируй, хочешь – ссылайся.
Сосбственно об этом я и говорил.
Цитата Qraizer @
Если объект расположен в ПЗУ, он по определению не может быть создан конструктором, потому что тот предполагает модификацию полей объекта для придания ему некоего состояния. В таком случае он должен быть туда помещён уже сконструированным, и для работы с ним достаточно ссылки.
Отлично. А теперь ты по этой ссылке вызываешь некий const-метод этого класса, а он оказывается не совсем const и пытается модифицировать свои поля, которые находятся в области недоступной для записи.

Добавлено
Цитата MyNameIsIgor @
Во, кстати, а какой GC сейчас использует D? Если как и раньше BoehmGC, то это fail.
Ага, он самый, родной. В теории может течь, но на практике не течет. По крайней мере на 64-битном линупсе.

Автор: MyNameIsIgor 12.11.15, 14:40
Цитата applegame @
Ага, он самый, родной. В теории может течь, но на практике не течет. По крайней мере на 64-битном линупсе.

Да он не должен течь. Просто консервативный, может что угодно за указатель посчитать и не почистить. С другой стороны он должен меньше ресурсов требовать, тегирование всякое ему не нужно. Но получается, что я и на C++ могу получить GC того же качества, что в D :jokingly:

Автор: applegame 12.11.15, 14:44
Цитата MyNameIsIgor @
Да он не должен течь. Просто консервативный, может что угодно за указатель посчитать и не почистить.
Поэтому и может течь. Теоретически. Точнее даже не течь, а просто зажимать память до некоторого момента.
Цитата MyNameIsIgor @
Но получается, что я и на C++ могу получить GC того же качества, что в D :jokingly:
Конечно. Собственно, ЕМНИП, BoehmGC изначально и был придуман для C/C++.

Автор: MyNameIsIgor 12.11.15, 14:46
Цитата applegame @
ЕМНИП, BoehmGC изначально и был придуман для C/C++

Именно так.

Автор: DarkEld3r 12.11.15, 15:02
Цитата applegame @
Вот еще впечатление от Rust после С++/D - Rust impressions from a C++/D programmer
Читал, местами интересно. С чем-то согласен (например, Display/Debug), а что-то наоборот кажется преимуществом. Ну и кое-что "когда-то допилят/исправят".

Автор: 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 @
У меня есть тип T, разработчик которого Вася уверяет, что он иммутабельный, как мне проверить слова Васи?
По моему, это не сильно отличается, скажем, от гарантий в плане того, что функция openFile может делать совсем другое.

Кстати, 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), что нечто будет меняться.

:wacko: Если мы допускаем mutable, то мы опять приходим к "чем это отличается от openFile".
Дилемма ясна - либо такой вот кастрат, либо развитие системы типов для возможности через неё точнее выражать семантику кода.

Автор: applegame 12.11.15, 16:25
Цитата DarkEld3r @
Кстати, D вообще никак не позволяет нарушить иммутабельность? Даже через всякие хаки?
Конечно можно, как в плюсах - cast'ом, но если поставить @safe, то нельзя, но если сильно захотеть и поставить @trusted, то можно. D - такой D. :D
Имутабельность в D скорее защита от случайной ошибки и самодокументироемости, чем реальная защита от Васи. Также как и pure.

Автор: korvin 12.11.15, 20:54
Цитата applegame @
Цитата MyNameIsIgor @
Что такое "честно" иммутабельный по определению?
"Честно" иммутабельный - это который действительно не меняет свое внутреннее состояние, а не делает вид, что не меняет, а на самом деле меняет.

Счётчик ссылок не внутренне состояние объекта, и 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, даже если вам кажется, что объект должен жить к моменту использования этого указателя. Лучше перекреститесь и добавьте оверхеда заверните this в shared_ptr и не забудьте про злотрахучий enable_shared_from_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, даже если вам кажется, что объект должен жить к моменту использования этого указателя. Лучше перекреститесь и добавьте оверхеда заверните this в shared_ptr и не забудьте про злотрахучий enable_shared_from_this, а то будете долго ломать голову

Это все тот же вопрос о владении и контроле времени жизни. Да, об этом нужно думать.

Только я так и не понял, при чем тут иммутабельность.

Добавлено
applegame, а если в C++ использовать boehm, то насколько это сильно страдабельнее, чем в D?

Автор: Qraizer 13.11.15, 12:54
  1. std::shared_ptr<> и не разрабатывался для каруселей. Он создавался для автоматического подсчёта владельцев объекта в случаях, когда невыгодно или невозможно наделять каждого из них своей копией оригинала. Естественно, что использование его в ситуациях с циклическими ссылками приведёт к бесконечному времени жизни, и это правильное поведение. Для пользователей объекта, а не владельцев, должен использоваться std::weak_ptr<>. Ничего сложного, нужно просто не косячить с архитектурой.
  2. Даже если вытащишь, сторонняя библиотека ничего с ним плохого сделать не должна. Не удалит же она его, если только это не прописано в её контракте. Другое дело, что время жизни теперь нельзя контролировать только лишь смартами, ну так это решаемо.
  3. Он потокобезопасен полностью. Его гарантия не распространяется на объект, это да. А ты можешь предложить универсальный механизм обеспечения такой безопасности?
  4. И что тут удивительного? Гарантии объекта кончаются, как только с данными объекта начинают работать в обход его интерфейса. std::shared_ptr<> имеет чёткий интерфейс: вся работа с подссыльным объектом – только через его операции. Вытащив из него голый this ты фактически получил пункт 2.

Автор: MyNameIsIgor 13.11.15, 13:07
Цитата Qraizer @
Он потокобезопасен полностью

Потокобезопасен подсчёт ссылок. Сам объект shared_ptr таких гарантий не даёт, да они и не нужны.

Автор: applegame 13.11.15, 13:41
Цитата D_KEY @
Вот именно это я и не понимаю... Каким образом?
Что именно ты не понимаешь? Указатель на иммутабельный объект можно просто передать, а при использовании shared_ptr будут атомики с барьерами памяти. Я уже писал об этом.
Цитата D_KEY @
Только я так и не понял, при чем тут иммутабельность.
К иммутабельности относился только первый абзац моего ответа. Остальное уже относится скорее к GC vs shared_ptr.
Цитата D_KEY @
applegame, а если в C++ использовать boehm, то насколько это сильно страдабельнее, чем в D?
Если честно, для меня главные преимущества D перед C++: читабельные и мощные шаблоны, UFCS, полноценное CTFE, рефлексия может еще какие-нибудь мелочи забыл. GC просто приятная плюшка без которой можно жить, а местами очень хорошо жить.
Говорят D1 был таким, а потом пришел Александреску и все испортил :D
Цитата Qraizer @
  1. std::shared_ptr<> и не разрабатывался для каруселей. Он создавался для автоматического подсчёта владельцев объекта в случаях, когда невыгодно или невозможно наделять каждого из них своей копией оригинала. Естественно, что использование его в ситуациях с циклическими ссылками приведёт к бесконечному времени жизни, и это правильное поведение. Для пользователей объекта, а не владельцев, должен использоваться std::weak_ptr<>. Ничего сложного, нужно просто не косячить с архитектурой.
  2. Даже если вытащишь, сторонняя библиотека ничего с ним плохого сделать не должна. Не удалит же она его, если только это не прописано в её контракте. Другое дело, что время жизни теперь нельзя контролировать только лишь смартами, ну так это решаемо.
  3. Он потокобезопасен полностью. Его гарантия не распространяется на объект, это да. А ты можешь предложить универсальный механизм обеспечения такой безопасности?
  4. И что тут удивительного? Гарантии объекта кончаются, как только с данными объекта начинают работать в обход его интерфейса. std::shared_ptr<> имеет чёткий интерфейс: вся работа с подссыльным объектом – только через его операции. Вытащив из него голый this ты фактически получил пункт 2.

Ну а что есть в C++ для каруселей? Да и все тобой сказанное известно. Все подводные камни shared_ptr хорошо изучены, описаны и придуманы методы их обхода. Но от этого они не перестают быть подводными камнями. Само наличие подобных комней - это минус.

Автор: D_KEY 13.11.15, 13:47
Цитата applegame @
Указатель на иммутабельный объект можно просто передать, а при использовании shared_ptr будут атомики с барьерами памяти. Я уже писал об этом.

Ну и что? Один раз при передачи в тред ты скопируешь shared_ptr. Я уверен, что для большинства задач это будет абсолютно незаметно.

Цитата
Цитата D_KEY @
Только я так и не понял, при чем тут иммутабельность.
К иммутабельности относился только первый абзац моего ответа.

А там были аргументы? ;)

Цитата
Остальное уже относится скорее к GC vs shared_ptr.

Ну это неинтересно :)

Автор: applegame 13.11.15, 17:26
Цитата D_KEY @
Ну и что? Один раз при передачи в тред ты скопируешь shared_ptr. Я уверен, что для большинства задач это будет абсолютно незаметно.
Для большинства задач вообще не нужны треды и immutable как таковые. А в реальных сложных многопоточных приложениях, треды имеют свойство постоянно обмениваться друг с другом объектами. А в моем реальном приложении они это делают постоянно. Ну и в конце-концов это просто удобнее.

Автор: D_KEY 13.11.15, 17:32
Цитата applegame @
А в реальных сложных многопоточных приложениях, треды имеют свойство постоянно обмениваться друг с другом объектами.

:)
В реальных многопоточных приложениях будет так, как ты сделаешь. Для обмена объектами достаточно unique_ptr и передачи владения.

Добавлено
Цитата applegame @
Ну и в конце-концов это просто удобнее.

Возможно. Но это выходит за рамки холивара, т.к. не является объективным критерием.

Автор: applegame 13.11.15, 17:52
Цитата D_KEY @
Для обмена объектами достаточно unique_ptr и передачи владения.
К сожалению, зачастую недостаточно. Точнее, зачастую невозможно передать владение.

Автор: Qraizer 13.11.15, 18:08
Цитата applegame @
Ну а что есть в C++ для каруселей?
Твоя фантазия. Ну сам посуди, какая логика владения должна быть, скажем, у двусвязного списка?

Автор: applegame 13.11.15, 18:55
Цитата Qraizer @
Ну сам посуди, какая логика владения должна быть, скажем, у двусвязного списка?
GC? Которого нет в C++, хотя вполне может быть. :D

Автор: D_KEY 13.11.15, 19:11
Цитата applegame @
Цитата Qraizer @
Ну сам посуди, какая логика владения должна быть, скажем, у двусвязного списка?
GC? Которого нет в C++, хотя вполне может быть. :D

У D же C/C++'ый GC :D

Автор: applegame 13.11.15, 19:27
Цитата D_KEY @
У D же C/C++'ый GC :D
Именно, и вроде даже был пропосал на GC.

Автор: D_KEY 13.11.15, 19:46
Цитата applegame @
Цитата D_KEY @
Для обмена объектами достаточно unique_ptr и передачи владения.
К сожалению, зачастую недостаточно. Точнее, зачастую невозможно передать владение.

А ты мог бы привести какой-нибудь интересный пример? Задачку может какую.

Автор: korvin 13.11.15, 20:44
А почему бы вместо указателя на (большие)данные не передавать указатель на функцию обработки в обратном направлении? Т.е. построить протокол взаимодействия потоков таким образом, чтобы обмен происходил исключительно маленькими порциями сообщений, которые можно тупо копировать и не париться ни над счётчиком ссылок, ни над потокобезопасностью (данные же иимутабельны в нашем обсуждении).

Да, чревато callback-hell, но ведь можно сделать это нормально.

Автор: applegame 14.11.15, 08:07
Цитата D_KEY @
А ты мог бы привести какой-нибудь интересный пример? Задачку может какую.
Есть один большой массив иммутабельных данных, нужно обрабатывать его части параллельно множеством потоков. Если я передаю один и тот же элемент в несколько потоков, то тут либо голые указатели, либо 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
Цитата D_KEY @
А зачем ты передаешь один и тот же элемент в разные потоки?
Ну а как иначе, если у меня есть скажем сто внешних наблюдателей, которые через 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 @
Кем?
Потоками-обработчиками. Операции чтения/записи в массив приходится синхронизировать мьютексом. Но они достаточно дешевые, так как копируются не сами объекты а только ссылки на них. И массив на самом деле не массив в смысле непрерывной области памяти. Там набор хэш-таблиц.
Цитата D_KEY @
Ну shared_ptr вполне справится :-? Или ты думаешь, что затраты на копирование shared_ptr будут существенными?
Зависит от нагрузки. Лично я в своем проекте ориентировался не на существенность оверхеда shared_ptr, даже если бы прибавилось скажем 10% я бы не переживал особо. Для меня было гораздо важнее удобство использования и безопасность. Хоть ты и сказал, что удобство - это субъективный параметр, но в данном случае он вполне объективный. Простое при прочих равных объективно удобнее сложного.

Автор: D_KEY 14.11.15, 12:43
Цитата applegame @
Операции чтения/записи в массив приходится синхронизировать мьютексом.

Но при этом ты беспокоишься о копировании 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
Цитата D_KEY @
Но при этом ты беспокоишься о копировании shared_ptr :)
Во-первых на одну синхронизацию массива приходится сотня копирований shared_ptr. Во-вторых я тебе уже объяснял, о чем я на самом деле беспокоюсь. Сочинять-то зачем, тролль несчастный. :)
Цитата D_KEY @
Безопасность чего?
Ну что ты такой бестолковый? Очевидно же чего - безопасность космических полетов.
Цитата D_KEY @
Ты так говоришь, как будто "простое" и "сложное" - это объективные вещи :)
Я вот не помню, чтобы shared_ptr мне когда-либо казался сложным. GC сам по себе гораздо сложнее, как и возможные случаи утечек при его использовании.
Я так говорю, потому что сущность shared_ptr<T> объективно сложнее сущности T*. И причем здесь сложность GC? И о каких возможных случаях утечек ты говоришь?
Цитата Qraizer @
Мне кажется, applegame, ты смешал иммутабельность данных, подлежащих обработке, с иммутабельностью контейнера, их содержащего.
Где именно?
Цитата korvin @
Нет, указатель может стать невалидным, если поток-владелец вызвал деструктор объекта, пока поток, получивший от него указатель на данные, ещё не завершился.
Такого не произойдет если есть GC, потока-владельца не существует. объектами владеет GC, который уничтожит их, как только перестанут существовать указатели на объекты во всех потоках приложения. Все потоки использующие объект отработали, этот же объект удален из массива - GC его удаляет.Весьма похоже на shared_ptr, только без всякого shared_ptr.
Цитата korvin @
Вообще, развивая мысль: передавай между потоками не указатели на сами объекты, а unique_ptr на сообщения. Ведь отправителю сообщение нужно только до момента отправки, а получателю только с момента получения, т.е. в каждый промежуток времени у сообщения только один владелец, соответственно никакие shared_ptr и подсчёт ссылок не нужны совсем.
Это ортогонально обсуждаемому вопросу. Я и так применяю сообщения там где это имеет смысл. Речь идет о совместном доступе нескольких потоков к одним и тем же данным.

Автор: D_KEY 15.11.15, 09:44
Цитата applegame @
Во-первых на одну синхронизацию массива приходится сотня копирований shared_ptr.

И вот снова появились новые условия в задаче :D

Цитата
Ну что ты такой бестолковый? Очевидно же чего - безопасность космических полетов.

А если серьезно? У тебя "безопасность" какое-то магическое слово.

Цитата
Я так говорю, потому что сущность shared_ptr<T> объективно сложнее сущности T*.

Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr.

Цитата
И причем здесь сложность GC? И о каких возможных случаях утечек ты говоришь?

Все те, для которых предназначены SoftReference и WeakReference в той же Java. Даже с GC ты не можешь просто забить на работу с памятью и анализ времени жизни объектов. Пусть и в более редких случаях, но зато менее явных.

Цитата
Я и так применяю сообщения там где это имеет смысл. Речь идет о совместном доступе нескольких потоков к одним и тем же данным.

Не знаю, по мне так ты хочешь странного.

Автор: applegame 15.11.15, 10:32
Цитата D_KEY @
И вот снова появились новые условия в задаче :D
Они не новые:
Цитата applegame @
Ну смотри сам. У меня есть достаточно большое количество (сотни тысяч) относительно небольших объектов. Эти объекты хрянятся в некой структуре, что-то вроде весьма узкоспециализированной простой БД в памяти. Также есть множество потоков, которые работают с какими-то срезами из этой БД, обычно lazy-range/слайсы, иногда небольшие иммутабельные масивы по нескольку десятков объектов.

Цитата applegame @
Тоже предлагаешь копировать константный массив на сто элементов?


Разговор с тобой стал неприятным для меня. Ты как обычно скатился в жЫрноту: начал "забывать", то что говорилось раньше и придумывать то, чего не говорилось, делать вид, что не понимаешь о чем речь, спрашивать значение общеизвестных терминов, требовать формализовать неформализуемое, выводить диалог на обсуждение малозначительных сущностей и так далее. Я не хочу по-кругу повторять одно и тоже.

Посему предлагаю поменяться ролями. :)
Цитата D_KEY @
Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr.
Что ты имеешь в виду? Почему это она сложнее? :)
Цитата D_KEY @
Все те, для которых предназначены SoftReference и WeakReference в той же Java. Даже с GC ты не можешь просто забить на работу с памятью и анализ времени жизни объектов. Пусть и в более редких случаях, но зато менее явных.
А для чего предназначены в Java SoftReference и WeakReference? И ты так говоришь, как будто "явность" - объективный критерий. :)
Цитата D_KEY @
Не знаю, по мне так ты хочешь странного.
А по мне ты просто не сталкивался со сколь-нибудь сложными многопоточными приложениями.

Автор: D_KEY 15.11.15, 10:50
Цитата applegame @
Они не новые

И где тут сказано, что лочишь мьютексом ты сразу для работы со многими элементами?

Цитата
Цитата D_KEY @
Вот никогда не понимал этого. Ты же не просто используешь T*, ты используешь T* + GC. А эта система сложнее shared_ptr.
Что ты имеешь в виду? Почему это она сложнее? :)

Я имею в виду, что shared_ptr - это подсчет ссылок на объект, его работа детерминирована и прозрачна. GC бывают очень разные, с разными стратегиями обхода, распределения памяти, работы с поколениями(и обработки ссылок между поколениями), гарантий времени остановки и пр. и пр.

Цитата
А для чего предназначены в Java SoftReference и WeakReference?

Для того, чтобы с разной степенью свободы позволять GC удалять те объекты, на которые мы еще имеем ссылки.

Цитата
И ты так говоришь, как будто "явность" - объективный критерий. :)

В случае ручного управления памятью утечки связаны с ошибками программиста, есть специальные тулзы, которые ищут утечки и пр. В случае RC есть детекторы циклов, которые покажут наличие циклических ссылок. Случаи "случайных" ссылок тяжелее выявлять и автоматических инструментов я не видел. Если есть - расскажи :)

Цитата
А по мне ты просто не сталкивался со сколь-нибудь сложными многопоточными приложениями.

:D
По мне так все наоборот... Вернее, ты не умеешь такие приложения проектировать. Но давай оставим в покое личности и попытаемся поговорить конструктивно.

Добавлено
И да, все хочу спросить, ты профайлером в том или ином виде пользуешься или на глаз оцениваешь, что медленно?

Автор: applegame 15.11.15, 11:31
Цитата D_KEY @
Я имею в виду, что shared_ptr - это подсчет ссылок на объект, его работа детерминирована и прозрачна. GC бывают очень разные, с разными стратегиями обхода, распределения памяти, работы с поколениями(и обработки ссылок между поколениями), гарантий времени остановки и пр. и пр.
Какое дело программисту до всей этой внутренней кухни? Убрал последнюю ссылку и забыл про объект и нет сюрпризов с неожиданным обращением к уже удаленному объекту. То же самое можно было бы сказать и о shared_ptr, если бы не несколько подводных камней и ограничений использования.
Цитата D_KEY @
Для того, чтобы с разной степенью свободы позволять GC удалять те объекты, на которые мы еще имеем ссылки.

Цитата D_KEY @
В случае ручного управления памятью утечки связаны с ошибками программиста, есть специальные тулзы, которые ищут утечки и пр. В случае RC есть детекторы циклов, которые покажут наличие циклических ссылок. Случаи "случайных" ссылок тяжелее выявлять и автоматических инструментов я не видел. Если есть - расскажи :)
А случаи "случайных" ссылок можно подумать не связаны с ошибками программиста :D, Да и shared_ptr могут привести к ним с тем же успехом. А заявить, что WeakReference в Java предназначены для борьбы с утечками, это примерно как сказать, что delete в C++ предназначен для борьбы с утечками :D
Инструмент для обнаружения причины таких "утечек" не нужен. Потому что твои пресловутые "случайные" зависшие ссылки - явление весьма специфичное и точки их возникновения легко находимы без каких-либо инструментов, кроме собственной головы. Как правило, это кеши, которые забыли периодически очищать. Тут я тебе без всякого valgrind найду утечку.
Цитата D_KEY @
:D
По мне так все наоборот... Вернее, ты не умеешь такие приложения проектировать. Но давай оставим в покое личности и попытаемся поговорить конструктивно.
Да, давай оставим. Но так как ты первый перешел на личности, то последнее слово за мной: ты - некомпетентен в этой области. :D Вот теперь, да, не будем о личностях.

Автор: D_KEY 15.11.15, 11:59
Цитата applegame @
Но так как ты первый перешел на личности

Нет ты :D

Добавлено
Цитата applegame @
Какое дело программисту до всей этой внутренней кухни?

:facepalm: И ты еще рассуждаешь о компетентности?

Добавлено
Цитата applegame @
А случаи "случайных" ссылок можно подумать не связаны с ошибками программиста

Это не ошибки. Это доверие сборщику.

Но вернемся к конструктивному обсуждению. Мне так и неясна связь иммутабельности с наличием/отсутсвием GC. По-моему, все что ты говоришь справедливо и для мутабельных данных, разве нет? Твой ответ про профайлинг так же интересен.

Автор: Qraizer 15.11.15, 12:11
Цитата applegame @
Цитата Qraizer @
Мне кажется, applegame, ты смешал иммутабельность данных, подлежащих обработке, с иммутабельностью контейнера, их содержащего.
Где именно?
Вот тут я могу присоединиться к D_KEY-ю. Разве не ты начал говорить о неком контейнере для ссылок на иммутабельные объекты, который то и дело, что меняет своё состояние? Объясни мне, плз, как можно рассуждать о тем или иным способом поумневшим ссылках на иммутабельные объекты, напрочь игнорируя содержащий их контейнер? При том что если бы контейнер был константным, мы могли бы обойтись тупо сырыми поинтерами и не париться. Пока я не вижу, зачем бы вообще могло понадобиться отдаваемые объекты оборачивать в смарты.

Добавлено
Цитата D_KEY @
И вот снова появились новые условия в задаче
Огласи уж полные условия, что ли. Без последующих отказов и дополнений.

Автор: applegame 15.11.15, 17:02
Цитата Qraizer @
Объясни мне, плз, как можно рассуждать о тем или иным способом поумневшим ссылках на иммутабельные объекты, напрочь игнорируя содержащий их контейнер?
Ссылки из этого контейнера рассылаются другим потокам. Не весь контейнер, а его различные части.
Цитата D_KEY @
Это не ошибки. Это доверие сборщику.
:facepalm: И ты еще рассуждаешь о компетентности? Сборщик тут не причем. Такие же "утечки" можно получить и с 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 @
Как в C++ определить был ли объект изначально константным или нет? Насколько я знаю никак. Фактически immutable в D обозначает изначальную константность. При этом immutable неявно может быть скастовано в const, но не наоборот. Теперь вопрос: нужен ли immutable в C++?
И слава богу, что нет. Иначе от const не было бы никакого проку вообще, как сейчас от register. Или от C99-шного restrict. Зато есть (в какой-то мере) прямая противоположность: const volatile. И это ИМХО идеологически правильнее immutable.

Автор: 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++. Но тогда стоило бы написать, что ты говорил о другом языке, вместо благодарностей капитанам, нет?

Цитата korvin @
Всё просто: совместный доступ не нужен. Каждым ресурсом владеет только один поток.
А какая связть между владением ресурсом и совместным доступом к ресурсу?

Автор: 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 @
Да нужно что-то более конкретное. Т.е. обозначить, что за контейнер, как данные туда попадают, как удаляются, кто, как и когда их читает и что, собственно, с этими данными делает. Что-то надо придумать. Тогда можем поиграться(в том числе и на Go вариант может появиться).
А смысл? Проверить что быдет быстрее GC или RC? Придумай сам что-нибудь с передачами групп объектов и типа их обработкой :) Я-то свою задачу решил и решение работает хорошо и, главное, поддерживается и расширяется тоже хорошо. Могут быть проблемы с масштабированием, но я полагаю, что мы вряд ли в обозримом будущем упремся в потолок текущей архитектуры.

Автор: D_KEY 16.11.15, 13:02
Цитата applegame @
Придумай сам что-нибудь с передачами групп объектов и типа их обработкой :)

Это можно. Но нам тут нужно, чтобы "обработка" была на одних и тех же данных много раз(и параллельно эти данные могут исключить из контейнера), причем данные должны быть достаточно большими, чтобы мы обеспокоились стоимостью копирования. Вот пока не придумывается ничего.

Автор: MyNameIsIgor 16.11.15, 13:06
Цитата applegame @
я полагаю, что мы вряд ли в обозримом будущем упремся в потолок текущей архитектуры

Так а какова сама задача, для которой была придумана такая архитектура?

Автор: applegame 16.11.15, 13:09
То что мне приходит в голову не требует копирования или совместного доступа, достаточно обмениваться уникальными идентификаторами, что в общем-то не эффективней обмена сырыми указателями, но зато не требует GC. Разве что прописать в условиях задачи необходимость полного доступа к объекту в потоках.

Добавлено
Цитата MyNameIsIgor @
Так а какова сама задача, для которой была придумана такая архитектура?
Подробности разглашать не могу, так как оно коммерческое и проприетарное.

Автор: MyNameIsIgor 16.11.15, 13:12
Цитата applegame @
То что мне приходит в голову не требует копирования или совместного доступа, достаточно обмениваться уникальными идентификаторами

Это не то же самое, ибо тогда получившие идентификатор не будут владеть данными. Со сборщиком мусора или подсчётом ссылок они ими владеют, даже если данные удалены из контейнера.

Добавлено
Цитата 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.

Цитата applegame @
А какая связь между владением ресурсом и совместным доступом к ресурсу?

Прямая:
- с GC владельцем является GC и он же освобождает память. Т.е. имея ссылку на один и тот же ресурс оба потока будут иметь её до тех пор пока оба не завершаться.
- Без GC программист сам выбирает политику владения памятью и организовывает совместный доступ таким образом, чтобы не было дыр, позволяющих привести систему к некорректному состоянию.

Вот тебя не устраивает smart_ptr из-за каких-то там проблем, я тебе предлагаю [не использовать smart_ptr и не шарить сам ресурс напрямую (через какие бы то ни было указатели вообще)] и не иметь этих проблем.

Добавлено
Давай хоть для начала определимся, что это за ресурс.

Автор: applegame 17.11.15, 21:33
Цитата korvin @
Мы же обсуждали указатели и владение памятью при использовании иммутабельных объектов в многопоточной среде в языках без GC.
Я полагал, что мы обсуждаем замену иммутабельным объектам в языке с GC.
Цитата korvin @
Прямая:
- с GC владельцем является GC и он же освобождает память. Т.е. имея ссылку на один и тот же ресурс оба потока будут иметь её до тех пор пока оба не завершаться.
- Без GC программист сам выбирает политику владения памятью и организовывает совместный доступ таким образом, чтобы не было дыр, позволяющих привести систему к некорректному состоянию.
Как ты там говорил? Спасибо, кэп. Но владение ресурсом и совместный доступ - понятия ортогональные. Совместный доступ - проблема синхронизации, владение ресурсом - проблема времени жизни ресурса.
Цитата korvin @
Вот тебя не устраивает smart_ptr из-за каких-то там проблем, я тебе предлагаю [не использовать smart_ptr и не шарить сам ресурс напрямую (через какие бы то ни было указатели вообще)] и не иметь этих проблем.
Я такого не говрил. Я говорил что по крайней мере в моем проекте immutable + GC удобнее, чем shared_ptr и может быть эффективней. А ты как-то странно заявил, что совместный доступ не нужен, если владелец всего один. Прямо вот совсем никогда не нужен? Создал объект в одном потоке раздал указатель на него еще десятерым, подождал пока они завершаться, уничтожил объект. Вот тебе схема с одним владельцем и совместным доступом.

В любом случае я тебя понял, такой вариант не всегда удобен и эффективен, но кое-где я его применяю.

Автор: korvin 17.11.15, 21:50
Цитата applegame @
Но владение ресурсом и совместный доступ - понятия ортогональные.

Нет, если доступ требует владения, как в случае с shared_ptr.

Добавлено
Цитата applegame @
Создал объект в одном потоке раздал указатель на него еще десятерым, подождал пока они завершаться, уничтожил объект. Вот тебе схема с одним владельцем и совместным доступом.

Э-э... Если ты ждешь пока потоки завершатся, то зачем тебе GC, если объект прекрасно и безопасно удалится создателем? Полезность GC проявляется как раз, когда ты не ждешь, пока потоки, обрабатывающие объект, завершатся, поэтому ты не можешь сам удалить объект там, где создал.

Автор: D_KEY 17.11.15, 22:07
Цитата applegame @
Но владение ресурсом и совместный доступ - понятия ортогональные. Совместный доступ - проблема синхронизации, владение ресурсом - проблема времени жизни ресурса.

Так вот именно. Потому наличие GC упрощает для тебя вопросы владения вне зависимости от иммутабельности(которая, в том числе, позволяет тебе не беспокоится о синхронизации).

Добавлено
Цитата applegame @
Но я попробую сформулировать нечто попроще. Будет эдакий многопоточный бенчмарк, пусть даже не похожий на реальный проект. Такое устроит?

Меня бы устроило. Не факт, что как следует похоливарим, но подумать можно. А может и поиграться с реализацией будет интересно.

Автор: applegame 18.11.15, 08:51
Цитата korvin @
Нет, если доступ требует владения, как в случае с shared_ptr.
Доступ никогда не требует владения (по крайней мере в D/C++). Для получения доступа к объекту внутри shared_ptr/unique_ptr не обязательно передавать владение, можно просто вытащить указатель с помощью get(). Владения, в том числе и совместного, может требовать архитектура приложения, но не доступ сам по себе.
Цитата korvin @
Э-э... Если ты ждешь пока потоки завершатся, то зачем тебе GC, если объект прекрасно и безопасно удалится создателем? Полезность GC проявляется как раз, когда ты не ждешь, пока потоки, обрабатывающие объект, завершатся, поэтому ты не можешь сам удалить объект там, где создал.
Это был просто пример. Я так не делаю.
Цитата D_KEY @
Меня бы устроило. Не факт, что как следует похоливарим, но подумать можно. А может и поиграться с реализацией будет интересно.
Скорее всего никак не похоливарим. Я пытался начать писать, все равно получается портянка. Но я попробую позже.

Автор: Qraizer 18.11.15, 12:11
Цитата applegame @
Для получения доступа к объекту внутри shared_ptr/unique_ptr не обязательно передавать владение, можно просто вытащить указатель с помощью get().
А ещё можно вытащить символьный массив из строки std::basic_string<>::c_str(). А ещё динамический массив из вектора &std::vector<>::front(). Вопрос только, зачем. Ответ известен: для передачи легаси-коду. Совет: для иных целей использовать не следует.

Автор: applegame 18.11.15, 14:11
Цитата Qraizer @
А ещё можно вытащить символьный массив из строки std::basic_string<>::c_str(). А ещё динамический массив из вектора &std::vector<>::front(). Вопрос только, зачем. Ответ известен: для передачи легаси-коду. Совет: для иных целей использовать не следует.
Это не отменяет того факта, что доступ к объекту не требует владения этим объектом. Кроме того почему обязательно легаси? Любому коду не работающему с shared_ptr/unique_ptr, например разнообразного рода API операционых систем или библиотек.

Автор: Qraizer 18.11.15, 14:33
Это тоже легаси.

Автор: applegame 18.11.15, 18:23
Цитата Qraizer @
Это тоже легаси.
Все, что не умные плюсовые указатели - легаси :D

Автор: 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-story. =) Больше таких и D, может-таки, завоюет популярность у масс. =)
success-stories есть немного тут - http://wiki.dlang.org/Current_D_Use
Цитата korvin @
Правда, неплохо бы показать преимущества реализации этой задачи на D вместо C++.
Да какие тут преимущества? Любит человек писать на 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_KEY @
Иначе так и неясно кто на ком стоял и зачем.
В 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
Цитата MyNameIsIgor @
Не вижу особой перемоги в замене <> на [].

Ну на мой взгляд [] читаются легче. Это же субъективно все.

Цитата
Кстати, если в скалке стали использовать функций для массивов, в плюсах можно сделать так же
<{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
Не, я хочу на разных уровнях разные контейнеры.

Добавлено
Цитата applegame @
Цитата D_KEY @
Иначе так и неясно кто на ком стоял и зачем.
В D все прозрачно: все что слева стоит на том что справа

А зачем он там стоит и какая логика за этим? Тайпдефы не только сокращают объявления, они ещё и позволяют уточнять смысл.

Автор: MyNameIsIgor 28.11.15, 18:55
Цитата D_KEY @
Не, я хочу на разных уровнях разные контейнеры.

Ну, сам сделаешь? :D

Автор: 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 @
Цитата D_KEY @
Не, я хочу на разных уровнях разные контейнеры.

Ну, сам сделаешь? :D

Ну вот чтоб синтаксис нормальным был не сделаю :(

Мне вариант с вложенными типами нравится больше. И [] нравится больше <>.

Вкусовщину обсуждаем, дожили.

Автор: 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;

Нет, а в чем проблема?

Да не, все прекрасно, начиная от великолепного и понятного названия переменной, заканчивая говорящим описанием типа.

Добавлено
Цитата applegame @
В D можно и так
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    int[5][string][] 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] - или просто двумерный ассоциативный массив.
Цитата D_KEY @
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    vector[map[string, array[int, 5]]]
О да, тут все читабельно, сразу видно где тут типы ключей, а где типы значений.
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].
А почему при объявлении скобки вложены, а при обращении нет? Потому что гладиолус.

Цитата D_KEY @
[string->[int:5]]
Тут вообще все сразу понятно: массив функций с одним параметром типа 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] - или просто двумерный ассоциативный массив.

Ну а мне это не нравится. Я привык, чтобы сначала был ключ, а потом значение. Так удобнее читать.

Цитата
Цитата D_KEY @
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    vector[map[string, array[int, 5]]]
О да, тут все читабельно

Да. Все прямо как ты сказал:
Цитата
Массив ассоциативных массивов со строковым ключем содержащих статические массивы по пять элементов типа int каждый.

Ну дословно же.

Цитата
map[A, B] - двумерный массив?

С какой стати это должен быть двумерный массив? Если ты не понял, то [] тут вместо плюсовых <>.

Цитата
А если мне нужен ассоциативный массив по двум ключам

Что это такое? Я думаю, что ты понимаешь, что у тебя ассоциативный массив с K1 и значениями в виде других ассоциативных массивов с ключем K2 и значением V.

Цитата
это будет map[A1, A2, B]? Нее, map[A1, map[A2, B]].

:crazy:

Цитата
А обращаться к элементам, значит нужно вот так - 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]

Все логично и понятно :D

Автор: 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
Цитата amk @
Давай я попробую:
Мододец. :)

Автор: D_KEY 29.11.15, 17:05
Цитата applegame @
У сей свои ребусы еще похлеще

Да. Но там объявление типа полностью соответствует использованию операторов, с помощью которых сложный тип дает доступ к своим компонентам. В 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 @
Да. Но там объявление типа полностью соответствует использованию операторов, с помощью которых сложный тип дает доступ к своим компонентам. В D это не так. А заговорил о связи объявлений и использования ты
Связь должна быть визуальная, чтобы удобно было человеку, а не компилятору. Чтобы не надо было учить чтение объявлений по спирали и прочий brainfuck,
Но мо собственно отклонились от первичного вопроса. Korvin спросил в чем преимущество D, я ответил, что в удобстве, которое кому-то может показаться наоборот неудобным.
То есть преимущество выражается в конкретном человеке. Допустим я на D пишу гораздо быстрее и с меньшим числом ошибок, чем на C++, потому что многие конструкции и идиомы D мне проще и понятней для понимания, чем аналогичное в C++. А если взять, например Qraizer'а, то у него, возможно, все будет наоборот.

Добавлено
Цитата D_KEY @
Но вообще тут в любом случае нужны typedef'ы, каким бы прекрасным не был синтаксис. ИМХО.
Это да, typedef или дешный аналог - alias тут явно не помешал бы.

Автор: D_KEY 29.11.15, 18:54
Цитата applegame @
Korvin спросил в чем преимущество D, я ответил, что в удобстве, которое кому-то может показаться наоборот неудобным.
То есть преимущество выражается в конкретном человеке. Допустим я на D пишу гораздо быстрее и с меньшим числом ошибок, чем на C++, потому что многие конструкции и идиомы D мне проще и понятней для понимания, чем аналогичное в C++. А если взять, например Qraizer'а, то у него, возможно, все будет наоборот.

Т.е. объективных преимуществ ты назвать не можешь? ;)

Автор: applegame 29.11.15, 19:02
Цитата D_KEY @
Т.е. объективных преимуществ ты назвать не можешь? ;)
Ну для тебя лично нет, ты ведь вообще не считаешь какие-либо преимущества одного языка перед другим объективными.
Сможешь ли ты назвать объективные преимущества 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
Цитата D_KEY @
Ну вот чтоб синтаксис нормальным был не сделаю

Давно все сделано в Perl'е :lol:

<{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 @
И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? Автор языка разве финансистом был? Я слышал, что он лингвист.
доллар обозначает, что значение -- скаляр, похож на букву "s" из соответствующего слова.
ps: код не промышленный, люди так не пишут :)

Добавлено
процент -- хеш-таблица, кружочки вокруг палочки (слеша) символизируют отображение одного значения на другое

Автор: korvin 02.12.15, 19:29
Цитата negram @
ps: код не промышленный :)

Но хоть коммерческий? =)

Автор: 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
Цитата D_KEY @
Ну а как ты на уровне грамматики это сделаешь?

Э-м... А как связаны грамматики типов и грамматика операторов? Ну например:
<{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", ""]}

Где тут конфликт?

Цитата D_KEY @
Так там же ! перед ними стоит.

А разве ! не для этих их строковых "миксинов"?

Автор: MyNameIsIgor 08.12.15, 21:52
Цитата korvin @
А разве ! не для этих их строковых "миксинов"?

Нет, он для шаблонов. Просто строка является аргументом шаблона.
Цитата korvin @
map["bar"] <- arr                -- use "operator grammar"

Вот как парсер здесь определит, что это оператор? Можно в парсере запоминать, какие идентификаторы являются именами переменных, а какие - типов. Но и это не всегда работает, поэтому в 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]}{"вес"}

Потому, как элементы хэша уже не похожи на элементы массива, и предваряются неизменяемыми префиксами % и @. Но мне непривычно.

Добавлено
Цитата applegame @
Чтобы легче парсилось, полагаю.

Именно.

Автор: korvin 09.12.15, 22:52
Цитата MyNameIsIgor @
Вот как парсер здесь определит, что это оператор?

Наверное, по тому, что токен перед ним --- переменная?

Цитата 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 @
Наверное, по тому, что токен перед ним --- переменная?

Если ты запоминаешь идентификаторы или идентификаторы имеют разный вид для переменных и типов. А иначе ты получишь лишь идентификатор.
Цитата korvin @
Почему бы и нет?

Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже.
Цитата korvin @
Я и говорил лишь про конкретно проблему в синтаксисе Scala и конкретно возможность её решения при использовании чуть более другого синтаксиса

Не вижу такой возможности.
Цитата korvin @
Т.е. вполне себе легко определить, что в <type> [] --- параметры, а в <expr> --- оператор.

Это всё хорошо либо при теоретизировании, либо для синтаксически нищего языка. Например, что такое a[b]© в каком-то выражении? Это я из массива a беру по индексу b функцию и вызываю её с аргументом c? Или это я прямо в выражении без объявления переменной конструирую значение параметрического типа a с параметром b и отдаю в конструктор аргумент c?
А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c?
Цитата korvin @
Не вижу, в чём ограничение. ... В Хаскелле, например, нельзя объявить оператор ::

:D
Цитата 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? :tong:

Цитата MyNameIsIgor @
А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c?

Вот это уже чуть интересней, но допустим у нас нет статических полей, у нас есть модули, где мы можем объявить статические переменные. Поэтому ответ: зависит от того, это <type> или <expr>, а это уже строго определено синтаксисом. Более того, зачем вообще явно указывать тип-параметр, если он выводится из контекста, как во всех нормальных языках? =)

Цитата MyNameIsIgor @
:D

Я и не говорил, что Хаскелл --- образец для подражания в этом вопросе.

Цитата MyNameIsIgor @
Навскидку: в Java аргументами обобщений не могут быть значения, в C++ - могут.

Т.е. вместо a можно подставить 1? Будет 1<b>? И что тогда в C++ означает выражение 1<2>(3)? Создание объекта шаблонного класса 1 с шаблонным параметром 2 и параметром конструктора равным 3? =) Ну, допустим, про 1 я утрировал, но a<1>(2)?

Пара-пара-пам?

Добавлено
Цитата MyNameIsIgor @
Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже.

Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций.

Цитата MyNameIsIgor @
:D

Кстати, в Хаскелле параметры же пишутся просто через пробел и ведь не путаются с применением функций-конструкторов, которые так же, как и типы, пишутся с заглавной буквы. Т.е. их идентификаторы неотличимы, да и вообще часто совпадают, если конструктор один.

Добавлено
Цитата 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 @
В каком "каком-то" выражении?

В любом.
Цитата korvin @
И как разделение выражений на <type> и <expr> вдруг делают язык "синтаксически" нищим?

Вводом ограничений.
Цитата korvin @
А где оператор new?

В синтаксически нищих языках :-?
Так что я так и не понял, как ты будешь определять, что это не вызов конструктора.
Цитата 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? =)

Нет. У тебя осталось две попытки ;)
Цитата korvin @
Ну, допустим, про 1 я утрировал, но a<1>(2)?

Пара-пара-пам?

Это боян. Например
<{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 @
Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций.

Усложнения парсера - требуется определить конец откладываемой части.
И не всегда осуществимо - например, ты разбираешь обобщение (как у меня в примере выше), но при этом тебе его надо положить в байт-код.
Ещё может возникнуть веселуха с циклически ссылающимися друг на друга кусками разбираемого кода.
Цитата korvin @
А может наплевать на всех, и заюзать символы вне ASCII диапазона? =)

А набирать то их как?

Автор: D_KEY 10.12.15, 19:58
korvin, а обобщённые функции как тогда выглядели в такой Java?

Автор: korvin 10.12.15, 20:43
Цитата MyNameIsIgor @
Вводом ограничений.

Как будто что-то плохое. Тебя же не смущает отсутствие возможности переопределения ключевых слов или использования их в качестве идентификаторов? А то в каком-то языке можно было легко получить код вроде
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    if if begin begin

Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =)

Цитата MyNameIsIgor @
В синтаксически нищих языках

Типа C++?

Цитата MyNameIsIgor @
Так что я так и не понял, как ты будешь определять, что это не вызов конструктора.

Как угодно, я выше D_KEY'ю написал пример про Жабу. Или так же, как парсер Хаскелла отличает идентификатор типа от идентификатора конструктора.

Цитата MyNameIsIgor @
Как нормальные языки выведут, что я имел в виду именно int?

В нормальных языках нет нужды в подобном коде. =)

Цитата MyNameIsIgor @
Это боян.

Это пример того, как духовносинтаксически богатый язык превозмогает обсуждаемую трудность. С чем ты споришь? =)

Цитата MyNameIsIgor @
Усложнения парсера - требуется определить конец откладываемой части.

Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл []. Это смысл будет дальше определён вычислителем/компилятором. Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)? У Java сложный парсер? Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет?

Цитата D_KEY @
а обобщённые функции как тогда выглядели в такой Java?

Вот, так и знал, что что-то упущу. Навскидку могу предложить foo(T)(x), выглядит не ок, но логично, т.е. вначале мы передаём конкретный тип и как бы создаём замыкание на его основе, а потом применяем замыкание к аргументу x. Вообще же, тут тип мог бы просто выводиться из типа аргумента, но из-за субтипирования, он может оказаться более общим, чем нужно.

Добавлено
Цитата MyNameIsIgor @
Т.е. я не смогу иметь отдельные переменные для каждого инстанса параметрического типа a?

В нормальных языках параметрический тип ---- это параметрический тип, а не хрен пойми что, плодящая кучу кода. =)

Добавлено
Цитата MyNameIsIgor @
А набирать то их как?

Compose+( например. В нормальных же операционных системах есть поддержка клавиши Compose =)

Автор: MyNameIsIgor 10.12.15, 21:02
Цитата korvin @
Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =)

Т.е. обязательно new и отсутствие статических членов - это ненормальные ограничения :D
Цитата korvin @
Типа C++?

Нет, типа Go и Java. Впрочем, они не только синтаксически, они и семантически нищие.
Цитата korvin @
Это пример того, как духовносинтаксически богатый язык превозмогает обсуждаемую трудность. С чем ты споришь? =)

Нет, не превозмогает. И я привёл тебе код почему не превозмогает.
Цитата korvin @
Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл [].

Эммм... Все твои рассуждения как раз и сводятся к тому, что мы при парсинге знаем смысл [].
Цитата korvin @
Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)?

Это не означает, что все неоднозначности можно разрулить без дополнительных приседаний. Что ты и доказал с теми же статическими членами.
Цитата korvin @
Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет?

Неоднозначности потому и неоднозначности, что без дополнительных телодвижений не разруливаются. Естественно грамматика C++ однозначна, но она контекстно-зависимая и потребовала подпорок typename/template.

Добавлено
Цитата korvin @
В нормальных языках

На самом деле ответить тебе просто нечего. Ты всё обсуждение сводишь к "в нормальных языках". А на самом деле ты хочешь сказать "в никем не используемых, никому не нужных поделках".

Добавлено
Цитата korvin @
В нормальных же операционных системах

В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue...

Автор: D_KEY 10.12.15, 22:43
Цитата korvin @
Цитата D_KEY @
В общем, мало видов скобочек :(
Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно.

А может наплевать на всех, и заюзать символы вне ASCII диапазона? =)

Это не слишком удобно :D

Проще добавить в язык 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 @
В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue...
А что есть в нормальных ОС вместо epoll/kqueue? IOCP?

Автор: MyNameIsIgor 11.12.15, 08:54
Цитата applegame @
Цитата MyNameIsIgor @
В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue...
А что есть в нормальных ОС вместо epoll/kqueue? IOCP?

Да, 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
Цитата applegame @
Типа надо под линупсом компилять проги дл вянды

Ага. Автор LDC пиняет на "несовершенство" библиотек. Пошел уже 3-й год, как это было выявлено.

Автор: applegame 25.06.17, 04:09
Задача достаточно экзотическая, поэтому, видимо, никто не возится с ней.

Добавлено
Возвращаясь к противостоянию с C++.
Произвольную лямбду можно хранить в std::function. Если у лямбды есть замыкания, то std::function будет делать аллокацию памяти из кучи, верно? И при каждом копировании тоже хапает память из кучи?

Автор: JoeUser 26.06.17, 14:52
Цитата applegame @
Задача достаточно экзотическая, поэтому, видимо, никто не возится с ней.

Не экзотичнее из под линуха для мак оса - и это работает.

Автор: applegame 04.07.17, 13:38
Цитата applegame @
Возвращаясь к противостоянию с C++.
Произвольную лямбду можно хранить в std::function. Если у лямбды есть замыкания, то std::function будет делать аллокацию памяти из кучи, верно? И при каждом копировании тоже хапает память из кучи?
Короче таки да, при каждом копировании std::function происходит аллокация, а значит плюсы сливают в этом плане дешке, так как дешные лямбды копируются без аллоцирования и состоят фактически из двух указателей.

Автор: JoeUser 04.07.17, 14:08
Цитата applegame @
Компилятор D gdc утвержден для включения в состав GCC.

Я вот задумался :-? Рано или поздно "новый" GCC (с поддержкой DLang) перекочует в mingw32. Сейчас в библиотеках runtime и phobos есть ошибки, приводящие к невозможности кросс-компиляции. На сколько я правильно разобрался - ошибки из-за неверно расставленных условий компиляции (нет понятия "целевой платформы", есть понятие используемой платформы, т.е. где компилируем/собираем - та и цель). Вопрос ... ну и кто будет (и вообще будет ли) разбираться с этой проблемой?

Автор: D_KEY 04.07.17, 14:20
Цитата applegame @
плюсы сливают в этом плане дешке

Показывай тесты производительности и расхода памяти. Чего зря болтаешь? :D

Автор: OpenGL 04.07.17, 14:23
Цитата applegame @
Короче таки да, при каждом копировании std::function происходит аллокация, а значит плюсы сливают в этом плане дешке, так как дешные лямбды копируются без аллоцирования и состоят фактически из двух указателей.

Не понял. А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли?

Автор: negram 04.07.17, 15:17
Цитата JoeUser @
Вопрос ... ну и кто будет (и вообще будет ли) разбираться с этой проблемой?
Дык, как всегда в Open Source: разбираться будет тот, кого эта проблема больше е волнует :D

Автор: Qraizer 04.07.17, 20:06
Цитата OpenGL @
А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли?
У них же классы представлены ссылочной семантикой. Бред, конечно, но они привыкли. Пусть порадуются, чё.

Автор: applegame 05.07.17, 07:14
Цитата D_KEY @
Показывай тесты производительности и расхода памяти. Чего зря болтаешь? :D
Ну разве что синтетику какую-нибудь попробовать.
Цитата OpenGL @
Не понял. А если у тебя в захвате переменная, содержащая данные в куче - она не скопируется что ли?
Скопируется при создании лямбды, а при копировании этой лямбды (например при передаче в функцию или сохранении в переменной) замыкания копироваться не будут. А разве должны?
Цитата JoeUser @
Я вот задумался :-? Рано или поздно "новый" GCC (с поддержкой DLang) перекочует в mingw32. Сейчас в библиотеках runtime и phobos есть ошибки, приводящие к невозможности кросс-компиляции. На сколько я правильно разобрался - ошибки из-за неверно расставленных условий компиляции (нет понятия "целевой платформы", есть понятие используемой платформы, т.е. где компилируем/собираем - та и цель). Вопрос ... ну и кто будет (и вообще будет ли) разбираться с этой проблемой?
Вероятнее всего мейнтейнер GDC. Ты можешь попробовать спросить у него самого по поводу этой проблемы, а то и помочь с ней. Кстати, можно под линем компилять код для вянды через wine, говорят все работаэ. :crazy:
Цитата Qraizer @
У них же классы представлены ссылочной семантикой. Бред, конечно, но они привыкли.
Не забывай, что "у них" есть еще структуры, которые имеют семантику по значению.
А в передаче классов по ссылке есть некий смысл. Не могу точно утверждать, но лично у меня создалось впечатление, что большая часть объектов в плюсах обычно передается при помощи указателей/ссылок или же сами являются обертками вокруг указателей.
Но это немного не имеет отношения к обсуждаемой теме, так как лямбды в D это не класс, это встроенный в язык тип. Встроенность еще дает возможность компилятору проводить некоторые оптимизации, например в случае если время жизни переменных замыкания гарантированно больше, чем время жизни самой лямбды, то память не аллоцируется вообще, а просто передается указатель на стековый фрейм содержащий переменные замыкания.

Автор: Qraizer 05.07.17, 08:17
Цитата applegame @
А в передаче классов по ссылке есть некий смысл.
Та не, речь не об этом. Речь о том, что переменная-объект всегда является ссылкой, так что любые присваивания просто копирую ссылку. При необходимости получить копию объекта это нужно заказать явно.
Я не имею ничего против ссылочной семантики как таковой, но я категорически не приемлю смешанную семантику, когда в языке одни типы ссылочные, другие значения.

Автор: 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() просто провалится.

Добавлено
Цитата applegame @
Не готов говорить о Дельфи. D - не Дельфи.
За D я тут и не говорю. Говорю за Дельфи. У них там хренова туча типов строк, какие-то объекты, какие-то не объекты, кто-то по сути POD, кто-то объект с состоянием, кто-то сам собой владеет и подсчитывает свои экземпляры, за кем-то надо следить самому, иначе утекут ресурсы, кому-то явно нужно командовать подсчитывать, кому-то если скомандуешь, расфигачишь пол-программы неопределённым поведением. Та ну их нахрен.

Автор: applegame 05.07.17, 20:15
Цитата Qraizer @
Та обсуждалось уже мульён раз. Типичный пример: тебе нужна локальная копия объекта, и толи = писать, то ли .clone() заранее ты знать не можешь. Для объектов классов = не сделает тебе копию, в результате модификации будут отражены на оригинале, для объектов неклассов .clone() просто провалится.
Дак в плюсах тоже самое: для указателей нужно вызывать clone, а для неуказателей =. Можно представить, что класс D это что-то вроде shared_ptr.

Автор: 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 @
Зачем?
В твоем примере не указатель, а ссылка.

Добавлено
Цитата D_KEY @
Неужели в D нельзя написать аналог такого кода?
Для классов нет. Для структур можно.

Автор: D_KEY 05.07.17, 20:26
Цитата applegame @
Цитата D_KEY @
Зачем?
В твоем примере не указатель, а ссылка.

Мой пример будет работать для любого T, даже если этот T будет указателем.

Автор: applegame 05.07.17, 20:30
Код аналогичный твоему:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    void foo(T)(const ref T x) {
      T t = x;
    }

В случае указатели или класса будет сделана копия указателя / указателя на класс, в остальных случаях копия самого объекта.

Добавлено
Цитата D_KEY @
Мой пример будет работать для любого T, даже если этот T будет указателем.
Неправильно он будет работать, читай пост 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
Цитата applegame @
И? Ты как-то влез в наш разговор не разобрпвшись о чем речь

Думаю, что это ты неверно понял оппонента.

Цитата
Крайзер не хотел копию указателя, он хотел копию объекта

Ты C++ забыл? Указатель является самостоятельным типом и его объект содержит адрес.

Добавлено
В C++ у тебя везде семантика значений. В D одни типы обладают семантикой значений, а другие - ссылочные.

Добавлено
Цитата applegame @
Цитата D_KEY @
Вот и появляются исключения на ровном месте. Для обобщенного кода куда проще, когда поведение одинаковое(концептуально).
Какие исключения? Мой код делает ровно тоже самое, что и твой.

Мой код всегда создаёт копию значения типа T. Твой - нет.

Автор: Qraizer 05.07.17, 20:47
Цитата applegame @
Дак в плюсах тоже самое: для указателей нужно вызывать clone, а для неуказателей =.
Нет. Как уже сказал D_KEY, = скопирует указатель и будет прав. Если мне нужно скопировать его содержимое, то я и напишу соответственно, сразу же указав параметром не T, а T*, и копировать буду источником разыменованный аргумент, а не его самого.
Единая семантика – либо значений, либо ссылок – тем и хороша, что я всегда знаю, с чем работаю, и если мне требуется разное поведение для значений/ссылок/указателей, я это легко сделаю либо перегрузкой, либо специализацией. В Плюсах принята семантика значений, но при этом я любой тип легко могу объявить ссылочным простым &. Не всегда это может быть удобно, но альтернатива хуже. Если бы была принята семантика ссылок, то и тут проблемы бы не было, наверняка был бы единый способ явно разыменовать ссылку, чтобы достучаться до хранилища объекта. В случае смешанной семантики у меня нет иного выбора, кроме как ветвиться метакодом, т.к. под T может скрываться и значение, и ссылка, и что конкретно придёт в мой обобщённый код в некой конкретной точке его инстанцирования, я заранее знать никак не могу.

Автор: applegame 05.07.17, 21:01
Цитата D_KEY @
Думаю, что это ты неверно понял оппонента.
Ну тогда объясни, что хотел оппонент и зачем он упомянул clone().
Цитата D_KEY @
Мой код всегда создаёт копию значения типа T. Твой - нет.
Тоже самое в D. Для более легкого понимания, представь, что класс в D - это просто особый тип указателя, например shared_ptr.

Добавлено
Цитата Qraizer @
Нет. Как уже сказал D_KEY, = скопирует указатель и будет прав.
А clone() тогда зачем упомянул? То ли хотел сбить меня с толку, то ли решил мгновенно на другие рельсы перепрыгнуть.
Цитата Qraizer @
В случае смешанной семантики у меня нет иного выбора, кроме как ветвиться метакодом,
Я тебя не понимаю. Зачем ветвиться? Просто делай присваивание, скопируется обычный указатель или указатель на класс или значение. Никаких ветвлений.

Автор: D_KEY 05.07.17, 21:23
Цитата applegame @
Тоже самое в D. Для более легкого понимания, представь, что класс в D - это просто особый тип указателя, например shared_ptr.

Представить я могу все, что угодно. Но в системе типов D для классов сделано исключение :)

Автор: applegame 05.07.17, 21:30
Цитата D_KEY @
Но в системе типов D для классов сделано исключение
Это не исключение, это ещё один самостоятельный тип. Ты же не называешь указатели исключением. ;)

Единственная претензия, пожалуй, это то, что выглядит оно как передача по значению, а передается указатель.

Автор: D_KEY 05.07.17, 21:32
Цитата applegame @
скопируется обычный указатель или указатель на класс или значение.

Есть тип 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_KEY @
Но в системе типов D для классов сделано исключение
Это не исключение, это ещё один самостоятельный тип. Ты же не называешь указатели исключением. ;)

Так они и не являются исключением. А класс в D является.

Автор: applegame 05.07.17, 21:42
Цитата D_KEY @
В приведенном выше коде будет создана копия значения этого типа. Если мы хотим сделать указатель на этот тип, мы делаем T* или там shared_ptr<T>. В D же, если это класс, то поведение будет отличаться от поведения для всех остальных "видов" типа.
И чем же он будет отличаться? Будет создана копия значения этого типа, а именно типа класс такой-то.
Цитата D_KEY @
В частности, не будет иметь смысл T*
В D будет. Получится нечто похожее на плюсовой T**.

Автор: negram 05.07.17, 21:44
Цитата amk @
Qraizer, ну не понимает он, что ссылка на объект и сам объект это не одно и то же.

applegame, к примеру, иногда в функции, чтобы получить результат, необходимо "поиграться" с состоянием объекта. Например, объект у тебя притворяется числом (представляет дробь или является числом высокой точности, или ещё что-нибудь в этом роде). К при меру число это представляет собой угол (в градусах), и тебе необходимо загнать его в интервал ±180°. Простейший способ — прибавлять/вычитать 360, но чтобы не испортить состояние исходного объекта, ссылку на который ты передал, тебе лучше бы работать с копией.
Если ты передаёшь целое или вещественное (встроенный тип), то простое = создаёт тебе копию, с которой ты можешь спокойно манипулировать.
Если ты передаёшь числовой объект, то = просто создаёт ещё одну ссылку и все манипуляции отражаются на исходном объекте, портя его. Можно конечно вместо конструкции a += 360 использовать a = a + 360, каждый раз создавая новый объект, но это резко снижает эффективность, поскольку начинаются игры с распределением/освобождением памяти.
Поэтому хотелось бы иметь независимый от сущности способ получить её копию. В C++ такой способ есть (их даже несколько), в D, я так понял, нет.

В том же Python'е есть функция copy, которая возвращает копию объекта, независимо от того, встроенный это тип или объект, созданный пользователем. Там даже есть функция deepcopy, создающая независимые копии ещё и вложенных объектов. Правда она медленная.

В принципе, достаточно написать одну такую функцию и потом ей пользоваться, где понадобится копия.

Не то, чтобы я тут был за кого-то. Но в качестве примера, где мешает ссылочная семантика приведён пример говнокода :D
В данном сценарии я скорее за семантику, которая не одобряет такое поведение :)

Автор: applegame 05.07.17, 21:47
Цитата amk @
Qraizer, ну не понимает он, что ссылка на объект и сам объект это не одно и то же.
Ты издеваешься? Я тебе не Исмаил Прокопенко, я отлично разбираюсь и в указателях и ссылках и значениях. В 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 @
Согласен. Ссылки изначально были не логичны. Сейчас все стало совсем плохо.

По крайней мере там все было очевидно и предсказуемо, а теперь совсем беда. Особенно с универсальными ссылками.

Автор: D_KEY 05.07.17, 22:02
Не, ну оно понятно и юзабельно. Но через гланды.

Автор: applegame 05.07.17, 22:03
Если вы пишете обобщенную функцию, принимающий любой тип, включая указатели, то для создания копии экземпляра вам придется, как выразился Qraizer, ветвить код, например писать отдельные оверлоады или шаблоны для значений и для указателей. То же самое в D, вам придется ветвиться, но на один тип больше - классы. Важно заметить, что классы в D не похожи на ссылки в плюсах, они похожи именно на указатели.

Добавлено
Цитата D_KEY @
Так они и не являются исключением. А класс в 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
Цитата D_KEY @
Есть T, есть shared_ptr<T>.
Не только, T может сам по себе являться shared_ptr<U>. То есть сигнатура шаблона выглядит как будто она принимает значение, а на самом деле это может быть указатель или shared_ptr.

Автор: D_KEY 05.07.17, 22:43
Цитата applegame @
Цитата D_KEY @
Есть T, есть shared_ptr<T>.
Не только, T может сам по себе являться shared_ptr<U>.

Верно.

Цитата
То есть сигнатура шаблона выглядит как будто она принимает значение, а на самом деле это может быть указатель или shared_ptr.

Ну так они же тоже типы. Со своими значениями :)

Автор: applegame 06.07.17, 04:50
Цитата D_KEY @
Ну так они же тоже типы. Со своими значениями
Дык и дешный класс тоже тип, со своим значением. И это значение не сам объект (как вы наверное полагаете), а указатель на него.
Еще раз, класс в 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 @
И это значение не сам объект (как вы наверное полагаете), а указатель на него.

Какого типа указатель?

Автор: applegame 06.07.17, 08:47
Цитата D_KEY @
Какого типа указатель?
Название типа совпадает с названием класса, так как это все-таки не указатель. Разница во внешнем виде. Написано 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 А в D, в случае необходимости, можно легко решить проблему и действительно можно считать, что MyClass является просто неким smart_ptr<MyClass__internal>.

Вот ссылки в C++ мне совсем не нравятся. Иногда даже думаю, не лучше ли бы было, если бы они не являлись самостоятельными типами, а были просто спецификаторами для параметров функции/возвращаемого значения. А для ссылок можно иметь отдельный generic-тип, что-то вроде указателей без адресной арифметики. Как с этим в D?

Добавлено
Цитата Flex Ferrum @
В 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 @
Вот ссылки в C++ мне совсем не нравятся. Иногда даже думаю, не лучше ли бы было, если бы они не являлись самостоятельными типами, а были просто спецификаторами для параметров функции/возвращаемого значения.
Именно так сделано в D. Есть спецификатор ref указывающий, что значение передается по ссылке. Но тип "ссылка" отсутствует. В общем-то не велика беда, можно задействовать указатель, особенно если учесть, что в D указатели агрегатных типов автоматически разыменовываются при обращении к методам и полям. Но я все равно иногда скучаю по плюсовым ссылкам. Их можно с высокой степенью достоверности реализовать в виде структуры-обертки, но это все равно не то.

Автор: D_KEY 06.07.17, 09:28
Цитата applegame @
Но я все равно иногда скучаю по плюсовым ссылкам.

Можешь пример какой-нибудь привести показательный?

Автор: applegame 06.07.17, 09:35
Цитата D_KEY @
Можешь пример какой-нибудь привести показательный?
Вряд ли, не помню когда это было. А в последнее время как-то не возникало необходимости в ссылках. У ссылки в плюсах есть серьезное отличие от указателя: ссылка требует обязательной инициализации, то бишь без специальных ухищрений ссылка не может ссылаться на несуществующий объект (уничтожение объекта после создания ссылки не учитываем), а вот указатель может указывать на 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
Цитата Qraizer @
Угу. Счас набегут RAIIшники и будут смеяться над масштабом этой проблемы.

Да тут половина постов про то какое дерьмо этот самый 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
Цитата settler @
Причем GC тут на вскидку еще круче чем у явы, (могу и ошибаться)
Ошибаешся. Тут он намного хуже, чем у жабы.
Цитата D_KEY @
Как-то не очень себе представляю монолитную систему, где в одном месте GC используется, а в другом нет. Это же неудобно.
Не более неудобно, чем система, которая в одном месте использует shared_ptr, а в другом нет. RAII и GC ортогональные вещи.

Автор: korvin 07.04.18, 22:57
Цитата settler @
Причем GC тут на вскидку еще круче чем у явы, (могу и ошибаться)

Ха-ха-ха.

Автор: Qraizer 07.04.18, 23:23
Цитата settler @
Да тут половина постов про то какое дерьмо этот самый GC
Он не дерьмо. Он не детерминирован, вот это плохо. Цитата, что ты привёл, рассказывает только об одной проявляющейся проблеме этой недетерминированности, но у неё много сторон, и RAII – одна из них.
Я вот честно, не вижу вообще никакой ниши для GC в C++. C++ предлагает другой, более изящный метод решения проблемы lifetime of dynamic storage objects. Он имеет ровно тот же профит, что и GC – отсутствие утечек ресурсов из-за человеческих ошибок, – он детерминирован, чем выгодно отличается от GC, дёшев в эксплуатации и реализации и при сравнении с сырыми поинтерами архитектурно практически от них не отличается. Да, я о смарт-поинтерах. Выходит, что ни сырые поинтеры, ни GC в C++ просто не нужны. Их не к чему применить.

P.S. applegame, это не моя цитата.

Автор: settler 08.04.18, 05:28
Цитата Qraizer @
отсутствие утечек ресурсов из-за человеческих ошибок, – он детерминирован,

ну а если по ошибке или незнанию ты не тот тип возьмешь?
Наличие GC делает невозможным
1. создавать быстрый код,
2. Код где часто надо выделять много памяти есть новый обект , а старый GC eще не стер,
(графика например)
Я работаю вебом с 2007года , никакой проблемы c GC не вижу ,

Добавлено
Цитата applegame @
Цитата Qraizer @
Причем GC тут на вскидку еще круче чем у явы, (могу и ошибаться)
Ошибаешся. Тут он намного хуже, чем у жабы.

Как ты это проверял ?

Добавлено
Цитата Qraizer @
Он не детерминирован, вот это плохо.
Цитата settler @
Да тут половина постов про то какое дерьмо этот самый GC
Он не дерьмо.

Tы сам пару лет назад в другом холиваре, говорил что это не всегда
проблема.

Автор: applegame 08.04.18, 06:44
Цитата Qraizer @
Я вот честно, не вижу вообще никакой ниши для GC в C++. C++ предлагает другой, более изящный метод решения проблемы lifetime of dynamic storage objects. Он имеет ровно тот же профит, что и GC – отсутствие утечек ресурсов из-за человеческих ошибок, – он детерминирован, чем выгодно отличается от GC, дёшев в эксплуатации и реализации и при сравнении с сырыми поинтерами архитектурно практически от них не отличается. Да, я о смарт-поинтерах. Выходит, что ни сырые поинтеры, ни GC в C++ просто не нужны. Их не к чему применить.
Весь этот текст довольно бессмысленный, потому что по сути смарт-поинтеры - это одна из реализаций GC.
Цитата Qraizer @
P.S. applegame, это не моя цитата.
Да, с мобильного писал, не туда нажал. Исправил

Автор: 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?

Добавлено
Цитата applegame @
по сути смарт-поинтеры - это одна из реализаций GC.

Считаю, что такая классификация бессмысленна для современного состояния отрасли :)
Я бы RC к GC не относил.

Добавлено
А будущее, как мне кажется (или хотелось бы), за статическим анализом, за чем-то вроде region inference :)

Автор: applegame 08.04.18, 09:17
Цитата D_KEY @
Если там вместо shared_ptr используется какие-то другие владельцы ресурсов, то вполне удобно(и можно постепенно переводить на unique_ptr, shared_ptr+weak_ptr). Если же там вообще RAII не используется, то это немного странно, но тогда там есть пары функций выделения/освобождения, чем так же можно воспользоваться для перевода на умные указатели.
С GC же так не получится.
Получится, точно также. Не забываем, что умные указатели отличаются от скажем инкрементального GC только детерминированностью уничтожения объектов, а в многопоточных системах, даже с умными указателями нереально контролировать время освобождения ресурса, если одновременно несколько потоков совместно этим ресурсом владеют.
Как показывает практика, детерменированность освобождения ресурса нужна мягко говоря редко. И в этих случаях в GC-языках предусматривают соответствующие средства.
Цитата D_KEY @
Вот есть у меня объект, который сам владеет парой объектов(unique_ptr), а над несколькими объектами ещё разделяет владение(через shared_ptr).
Может ли такой объект контролироваться GC? Если да, то когда мы "отпустим" ресурсы, которыми объект владеет? Может ли такой объект быть полем объекта, который контролируется GC?
Может. Зависит от кода, ресурсы можно отпустить и вручную, если нужно. Может. Все эти uniq_ptr и shared_ptr - химеры плюсов, которые языку с GC не нужны, отлично живется без них, поверь.
Цитата D_KEY @
Считаю, что такая классификация бессмысленна для современного состояния отрасли :)
Я бы RC к GC не относил.
Ну и зря, потому что RC запросто может быть использован в некоторых реализациях GC. Например, GC эрланга исользует RC для некоторых видов ресурсов.

А 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 @
А GC плохо подходит для плюсов, потому что хороший и быстрый GC для подобных языков нереально сделать. Либо получается говно вроде дешного GC, либо очередной C#.
Не согласен. Даже сырые поинтеры вполне можно контролировать "под капотом" технологией, похожей на C++EH. Напомню, что реализация C++EH никак не затрагивает классы и полностью обходится внешними по отношению к охраняемым им объектам структурами данных. Так что вполне можно представить себе реализацию компилятора, который на каждый поинтер заводит счётчик, аддрефит и декрефит его при копировании, присваивании итп и следит за областями видимости этих поинтеров. Это сделает их практически неотличимыми от shared_ptr<>. В итоге получим в общем-то тот самый GC, который хороший, детерминированный и незаметный.
Только цена подобного решения будет велика. Если 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

Но и там есть явные "слабые ссылки".

И без них (или какого-то детектора циклов) ты никак не обойдешься.

Добавлено
Цитата negram @
А RC - это сокращение для чего?

Reference Counting

Автор: applegame 08.04.18, 19:40
Цитата D_KEY @
Так я про это отличие и говорю :)
Оно весьма важно.
Оно важно, но не оно превращает GC в не-GC.
Цитата D_KEY @
Когда будет освобожден ресурс?
Когда приспичит GC.
Цитата D_KEY @
Тут же мы говорим о сочетании в одном языке, в одной системе.
Да. И вся аргументация сводится к "мне так кажется". Объективных причин как за смешивание так и против, я не вижу. И в D это не мешает. Мешает просто плохой GC.
Цитата D_KEY @
Без детектора циклов это не имеет смысл. А если он есть, то это уже не совсем RC. Это реализация сборщика через RC ;)
В эрланге нет никаких детекторов цикла. Там RC применяется к объектам, которые принципиально не могут содержать ссылки на другие объекты. Для остальных generational GC.
Цитата D_KEY @
Сам же RC сборкой мусора не является. Вернее, в современных системах лучше эти понятия разделять.
С чего ты взял?

Автор: D_KEY 08.04.18, 19:46
Цитата applegame @
Оно важно, но не оно превращает GC в не-GC.

Это является следствием работы того, что сейчас называют GC. Полноценная сборка мусора не в состоянии обеспечить детерминированное удаление.

Цитата
Объективных причин как за смешивание так и против, я не вижу


В таком случае лучше не смешивать, ибо так проще. Зачем усложнять, если ценность не ясна?

Добавлено
Цитата applegame @
Там RC применяется к объектам, которые принципиально не могут содержать ссылки на другие объекты

Тогда это можно рассматривать в качестве оптимизации GC для конкретных случаев. От программиста что-то требуется?

Цитата
Цитата D_KEY @
Сам же RC сборкой мусора не является. Вернее, в современных системах лучше эти понятия разделять.
С чего ты взял?

Это же просто классификация. Называя RC сборкой мусора легко ввести в заблуждение.

Добавлено
applegame, посмотри на статью про ARC в swift, что я выше привел. Как думаешь, удобно бы было, если бы они называли это сборкой мусора?

Автор: applegame 08.04.18, 19:51
Цитата Qraizer @
Не согласен. Даже сырые поинтеры вполне можно контролировать "под капотом" технологией, похожей на C++EH. Напомню, что реализация C++EH никак не затрагивает классы и полностью обходится внешними по отношению к охраняемым им объектам структурами данных. Так что вполне можно представить себе реализацию компилятора, который на каждый поинтер заводит счётчик, аддрефит и декрефит его при копировании, присваивании итп и следит за областями видимости этих поинтеров. Это сделает их практически неотличимыми от shared_ptr<>. В итоге получим в общем-то тот самый GC, который хороший, детерминированный и незаметный.
Только цена подобного решения будет велика. Если C++EH практически не сказывается на производительности кода, кроме собственно случаев, когда исключения выбрасываются, то такие поинтеры будут отнимать ресурсы ЦП постоянно. Т.к. принцип нулевой стоимости запрещает сие, поэтому и есть отдельные библиотечные типы, используя которые программер сознательно идёт на этот оверхед.
Неполноценный GC получится, чреват утечками из-за циклических ссылок.
Кроме того, почему-то считается, что такой GC будет медленнее современных incremental/generational GC.

Автор: Qraizer 08.04.18, 19:57
Цитата applegame @
Неполноценный GC получится, чреват утечками из-за циклических ссылок.
Почему это? Циклы аутоматично могут детектиться, кто мешает реализовать?

Автор: D_KEY 08.04.18, 20:03
Цитата Qraizer @
Циклы аутоматично могут детектиться, кто мешает реализовать?

Полноценно их можно детектить только в рантайме.
И что ты с ними будешь делать автоматически?

Автор: applegame 08.04.18, 20:05
Цитата D_KEY @
В таком случае лучше не смешивать, ибо так проще. Зачем усложнять, если ценность не ясна?
А что усложняется? Ты можешь полностью забить на RAII и писать так же как пишешь на шарпе или жабе. А ценность ясна - ты можешь применять D для низкоуровневого кода. Я например на D даже микроконтроллеры прогаю, не пользуясь GC.
Цитата D_KEY @
Тогда это можно рассматривать в качестве оптимизации GC для конкретных случаев. От программиста что-то требуется?
Как и в любом языке есть рекомендации в каких ситуациях как лучше поступать или наоборот не поступать.
Цитата D_KEY @
Это же просто классификация. Называя RC сборкой мусора легко ввести в заблуждение.
То есть это вопрос чисто терминологии. Так как мы оба прекрасно понимаем, о чем говорим, то не вижу смысла в дальнейшем споре.
Цитата D_KEY @
applegame, посмотри на статью про ARC в swift, что я выше привел. Как думаешь, удобно бы было, если бы они называли это сборкой мусора?
Да все равно, если честно. Написали бы, сборка мусора обеспечивается при помощи ARC, ничего бы не поменялось.

Автор: D_KEY 08.04.18, 20:08
Цитата applegame @
Кроме того, почему-то считается, что такой GC будет медленнее современных incremental/generational GC.

Ну тут комплекс факторов. Ты не сможешь на такой основе сделать быстрое выделение памяти(которое в случае полноценного GC может сводится почти что к инкременту указателя), ибо нет фазы сборки, нет фазы перемещения и уплотнения объектов. Так же у тебя появляется оверхед на каждое копирование ссылки.
Да и замеры какие-то вроде проводили, но тут у меня есть сомнения в корректности.

Автор: applegame 08.04.18, 20:09
Цитата Qraizer @
Почему это? Циклы аутоматично могут детектиться, кто мешает реализовать?
Реализовывали уже, в питоне и в Nim. Тормозно получается. Этож надо строить графы ссылок и искать в нем циклы. Поэтому этот детектор ссылок делают отключаемым.

Автор: D_KEY 08.04.18, 20:11
Цитата applegame @
Да все равно, если честно. Написали бы, сборка мусора обеспечивается при помощи ARC, ничего бы не поменялось.

Хм. Ну а как бы ты описывал необходимость в слабых ссылках? Ведь они в языках с нормальным GC есть, только совсем другие и для других целей используются.

Добавлено
Цитата applegame @
А что усложняется? Ты можешь полностью забить на RAII и писать так же как пишешь на шарпе или жабе.

Тогда зачем мне D? Есть же kotlin и scala :D

Добавлено
Цитата applegame @
А ценность ясна - ты можешь применять D для низкоуровневого кода. Я например на D даже микроконтроллеры прогаю, не пользуясь GC.

Но ведь ты сам выше писал, что D gc-ориентированный. Неужели удобнее получается, чем на крестах или rust?

Автор: applegame 08.04.18, 20:15
Цитата D_KEY @
Ну тут комплекс факторов. Ты не сможешь на такой основе сделать быстрое выделение памяти(которое в случае полноценного GC может сводится почти что к инкременту указателя), ибо нет фазы сборки, нет фазы перемещения и уплотнения объектов. Так же у тебя появляется оверхед на каждое копирование ссылки.
Да и замеры какие-то вроде проводили, но тут у меня есть сомнения в корректности.
Да, я в курсе аргументации противников ARC.
Несколько лет назад кто-то в D в свое время перехерачил весь рантайм на ARC и доложил о нехилом приросте скорости в какой-то там игре. Но это тоже не совсем корректный замер, так как дешный GC тормозной, и у него кто угодно выиграет.
Если бы все эти александрески не парили бы мозг и просто сделали бы те же плюсы, но с синтаксисом и шаблонами D, то очень вероятно, что сейчвс бы Qraizer топил бы за такой D.

Автор: Qraizer 08.04.18, 20:22
Цитата applegame @
Реализовывали уже, в питоне и в Nim. Тормозно получается. Этож надо строить графы ссылок и искать в нем циклы.
Ну так как напрограмили, так и работает. Оптимизацию никто не запрещал.

Автор: applegame 08.04.18, 20:23
Цитата D_KEY @
Хм. Ну а как бы ты описывал необходимость в слабых ссылках? Ведь они в языках с нормальным GC есть, только совсем другие и для других целей используются.
Да также бы и описывал. Мне неинтересно спорить на тему является ли ARC частным случаем GC или нет. В любом разговоре достаточно договориться о терминах, а там хоть горшком назови. Я твою точку зрения понял, и когда ты будешь писать GC я учту, что ты имеешь в виду "обычный" GC как в D, жабе и т. д.
Цитата D_KEY @
Тогда зачем мне D? Есть же kotlin и scala :D
Это риторический вопрос. Зачем kotlin и scala, когда есть D, Elixir и Haskell?
Цитата D_KEY @
Но ведь ты сам выше писал, что D gc-ориентированный. Неужели удобнее получается, чем на крестах или rust?
Да, удобнее, как ни странно. Фактически ты как бы пишешь на эдаких сильно прокачанных плюсах. Разве что библиотек нет вообще, поэтому чисто как хобби. Профессионально кодить МК на D - это безумие.
Цитата Qraizer @
Ну так как напрограмили, так и работает. Оптимизацию никто не запрещал.
Можно конечно предположить, что программисты в Apple криворукие, но я таки склонен полагать, что это не так просто как ты считаешь.

Автор: D_KEY 08.04.18, 20:28
Цитата Qraizer @
Оптимизацию никто не запрещал.

Расскажешь, как бы ты сделал детектор циклов?

Добавлено
Цитата applegame @
Зачем kotlin и scala, когда есть D, Elixir и Haskell?

Проще же(хотя про scala это вряд ли можно сказать).
По крайней мере в рассматриваемом вопросе управления памятью.

Добавлено
В остальном согласен, там действительно больше о терминологии речь.

Автор: applegame 08.04.18, 20:37
Цитата D_KEY @
Проще же(хотя про scala это вряд ли можно сказать).
По крайней мере в рассматриваемом вопросе управления памятью.
Не думаю, что проще. На D также легко писать как и на kotlin. Практически все дешные WAT-ы никак с GC не связаны.
Проблемы возникают, если в программе очень много GC-объектов болтающихся в памяти. У меня например в проекте их сотни тысяч. GC тормозит безбожно. Авторы D2 почему-то забили на опыт Apple. Насколько я помню, в Objective C долго пытались сделять полноценный GC. Мучались, пробовали и так и эдак, но в итоге забили и сделали ARC, потому, что в подобных языках полноценные GC получаются убогими.

Автор: korvin 09.04.18, 04:08
Цитата applegame @
в подобных языках полноценные GC получаются убогими

В «подобных» — это в каких? В смысле, какой критерий подобности?

Автор: applegame 09.04.18, 04:24
Цитата korvin @
Цитата applegame @
в подобных языках полноценные GC получаются убогими

В «подобных» — это в каких? В смысле, какой критерий подобности?

Возможность свободно работать с голыми указателями, приводить типы как вздумается, и прочими возможностями ковырять память на низком уровне.

Автор: settler 09.04.18, 20:19
Цитата applegame @
Проблемы возникают, если в программе очень много GC-объектов болтающихся в памяти. У меня например в проекте их сотни тысяч. GC тормозит безбожно.

Это не проблема GC , а скорее его неверного успользования,
запускать каждый раз чтобы убрать один обьект или сразу 50,
потом, что мешает создавать обьекты на стеке?

Вот, то что в Ди GC плохо документирован, не очень хорошо.

Автор: applegame 10.04.18, 05:21
Цитата settler @
Это не проблема GC , а скорее его неверного успользования,
запускать каждый раз чтобы убрать один обьект или сразу 50,
потом, что мешает создавать обьекты на стеке?
Эти объекты иммутабельные и расшариваются между потоками. GC запускается сам, когда ему вздумается.
Цитата settler @
Вот, то что в Ди GC плохо документирован, не очень хорошо.
Документации достаточно. Что именно в работе дешного сборщика тебя интересует?

Вот серия статей о работе с памятью в D:
https://dlang.org/blog/the-gc-series/

Автор: sergioK 29.11.18, 17:51
Цитата yuan @
Английский в программировании как-то уже утомил. Что можно сделать ?

Снег зимой утомил, есть альтернатива :D
Английский нужно знать, это часть профессии.

Добавлено
Цитата 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
Цитата Qraizer @
Ща applegame ещё подтянется.
А мне особо нечего сказать :)
Разве что сообщить, что компилятор D смерджен с GCC.

Автор: Qraizer 02.12.18, 03:32
Как нечего :o ? Тоже АОП не завезли? Тю, а sergioK так рассчитывал…

Автор: korvin 02.12.18, 15:56
Цитата Qraizer @
А за АОП чё ничего не задвинул?

А что АОП?

Автор: Qraizer 02.12.18, 20:17
Та чёта заглох ажиотаж касательно аспектов. А такие надежды подавал.

Автор: sergioK 03.12.18, 17:51
Цитата Qraizer @
Та чёта заглох ажиотаж касательно аспектов. А такие надежды подавал.

Ажиотаж создал в посте номер 3, показав какой ты швицер ;) и с одного раза
не понимаешь что тебе в красивой форме намекнули. Меньше пиши
категоричных высказываний. take it or leave it .

Теперь про C++ , главный недостаток - отсутствие интерфейсов, частное наследование,
и не безопасность кода,

Добавлено
Цитата korvin @
Цитата sergioK @
И отсутствие полиморфизма на уровне компайла, опровергает "скорее всего иначе было бы хуже."

А перегрузка? А шаблоны?

А что перегрузка ? Компайлер не понимает что функция должна быть витуальной.
Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь,
или в мордо книге свои компайлеры пишешь.

Добавлено
Цитата Qraizer @
Как нечего :o ? Тоже АОП не завезли? Тю, а sergioK так рассчитывал…

Ну так у вас два дня ушло, выяснить что обревиатура сия значит,

Автор: D_KEY 03.12.18, 18:34
Цитата sergioK @
главный недостаток - отсутствие интерфейсов

На практике не критично, ибо легко достигается просто через абстрактные классы без реализации и полей.

Цитата
частное наследование

Что ты имеешь в виду?

Цитата
и не безопасность кода

Если ты про отсутствие виртуальной машины, то это, в тоже время и достоинство, поскольку не мешает быстродействию и контролю.
java-машины тоже на чем-то писать надо ;)
Если же ты про сам язык, то да. Есть проблемы. Но развитие в сторону безопасности идет.

Цитата
А что перегрузка ? Компайлер не понимает что функция должна быть витуальной.

Чего ты хочешь? Сам же просил полиморфизм времени компиляции.

Цитата
Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь,
или в мордо книге свои компайлеры пишешь.

Да везде это хорошо. Не преувеличивай.
Вот исключения действительно не везде используют(есть в стандарт предложения новые на эту тему).

Автор: Qraizer 03.12.18, 20:09
Цитата sergioK @
Ажиотаж создал в посте номер 3, показав какой ты швицер с одного раза
не понимаешь что тебе в красивой форме намекнули
Читаю пост №3:
Цитата applegame @
Цитата D_KEY @
У меня дежавю? :)
Ну времени прошло много, многое поменялось. Пора снова просвещать массы :)
:huh: Ни ажиотажа, ни меня. Пукнул мимо лужи?
Цитата sergioK @
Меньше пиши
категоричных высказываний. take it or leave it .
На себя посмотри. Мои высказывания, во-первых, не категоричны, во-вторых, они не мои.

Добавлено
Цитата sergioK @
Теперь про C++ , главный недостаток - отсутствие интерфейсов, частное наследование,
и не безопасность кода
Интерфейсы есть ещё с конца 80-ых годов. Частное наследование есть ещё с начала 80-ых. Безопасность кода в твоих руках с вводом в язык исключений. Глазки-то разуй, научить-таки читать учебники.

Добавлено
Цитата sergioK @
А что перегрузка ? Компайлер не понимает что функция должна быть витуальной.
Темплайты это хорошо для интервью крутого строить, если не в сорс фоге работаешь,
или в мордо книге свои компайлеры пишешь.
Чё?? Статика в динамике? Второй раз спрашиваю: ты сам-то понял, что хотел сказать? Впрочем, если ты о мультиметодах, добро пожаловать, желаю приятно провести время в трёх темах, им посвящённым. Ну-ка изобрази на дженериках, хочу полюбоваться.

Добавлено
Цитата sergioK @
Ну так у вас два дня ушло, выяснить что обревиатура сия значит
А кому оно нужно было? Как идеология, это прикольная тема, практически же зайцу стоп-сигнал нужнее.

Автор: OpenGL 04.12.18, 04:19
Цитата D_KEY @
Вот исключения действительно не везде используют(есть в стандарт предложения новые на эту тему).

Что за предложения?

Цитата Qraizer @
Чё?? Статика в динамике?

Не путай - это динамика в статике! :rtfm:

Автор: applegame 05.12.18, 11:23
тут в уютненьком эликсировском чятике ФПшники яростно гнобят исключения для ожидаемых ошибок, ранний возврат из функции и прочие любимые зверушки поганых императивщиков. :lol:

Добавлено
Ну и еще новости о D:
Liran Zvibel of WekaIO on using D to Create the World’s Fastest File System

Автор: Астарот 05.12.18, 11:48
Цитата applegame @

тут в уютненьком эликсировском чятике ФПшники яростно гнобят исключения для ожидаемых ошибок, ранний возврат из функции и прочие любимые зверушки поганых императивщиков. :lol:

Так там еще и концепция "пусть оно упадет как можно раньше" :)

Автор: applegame 05.12.18, 12:35
Цитата Астарот @
Так там еще и концепция "пусть оно упадет как можно раньше"
Ну не такая конечно. Просто "дай ему упасть". :) Ну в каких-то случаях такая концепция помогает серверу работать даже с багами.

Автор: Астарот 05.12.18, 12:44
Цитата applegame @
Ну не такая конечно. Просто "дай ему упасть". :)

Не-не-не, именно "как можно раньше" :yes:

Цитата applegame @
Ну в каких-то случаях такая концепция помогает серверу работать даже с багами.

С хардкорными багами наврятли. Супервизор попробует поднять упавший процесс N раз, тот, если там баг, накернится на том же месте, и в конечном итоге супервизор решит прервать это мучение. А вот если там баг помяхше, типа нуля на который хочется поделить, пришедшего в процесс снаружи, то да процесс поднимется заново и побежит дальше :yes: И все будет хорошо, пока нулей не станет слишком много :D

Автор: 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
Цитата applegame @
но в моем случае крайне геморно

:blink: Это что за случай такой???

Автор: D_KEY 05.12.18, 13:37
Цитата applegame @
В моем проекте половина процессов имеют невосстановимый стейт

А это зачем нужно? Или так исторически сложилось? :D

Автор: Астарот 05.12.18, 13:52
Цитата D_KEY @
А это зачем нужно?

Зачем нужен стейт? :D Даже не знаю, что сказать...

Автор: applegame 05.12.18, 13:54
Цитата Астарот @
Это что за случай такой???
Долго объяснять, главная причина: абсолютно непредсказуемый сервис третьей стороны часто не соблюдающий собственные спецификации, и на который мы никак не можем повлиять.
Цитата D_KEY @
А это зачем нужно? Или так исторически сложилось?
Он невосстановимый не потому что так нужно, а потому что слишком сложно его восстановить в валидном состоянии.
Конечно ничего невосстановимого нет, но так как я уже вычистил практически все баги и эти процессы перестали падать от слова совсем, то исчезла необходимость городить восстановление :), ну и супервизить соответственно тоже не нужно.

Автор: Астарот 05.12.18, 14:12
Цитата applegame @
ну и супервизить соответственно тоже не нужно.

А завершаешь работу ты намертво грохая всю vm? :)

Добавлено
Кстати, супервизоры умеют не только супервизить и заверать дочерних супервизоров, но и динамически порождать новые процессы. В общем слишком полезная штука, что бы от нее отказываться.

Автор: Qraizer 05.12.18, 14:33
Цитата Астарот @
Но тут вопрос, скорее, про то, что лучше, если все же упал - воскрешать или не воскрешать?
А какая разница? Если можно не позволить упасть, почему бы этого не сделать? Исключения в жизнь! Если нельзя, то нужно переподнять. Исключения нафик! Это вопрос стоимости усилий. Независимо от реализации нужно логгить и исправлять причину падения. И логгить, и исправлять нужно в обоих вариантах.

Автор: Астарот 05.12.18, 14:44
Цитата Qraizer @
А какая разница? Если можно не позволить упасть, почему бы этого не сделать?

Я не вижу тут противоречия. Если можно не падать - нужно не падать. А воскрешать или не воскрешать это уже если упал.

Цитата Qraizer @
И логгить, и исправлять нужно в обоих вариантах.

Само-собой. Просто в одном варианте ты остановишься и будешь стоять пока не исправишь, в другом - будешь как-то бежать периодически спотыкаясь. Что лучше - зависит от каждого конкретного случая.

Автор: applegame 05.12.18, 14:55
Цитата Астарот @
А завершаешь работу ты намертво грохая всю vm?
Зачем? Обычно звоним в датацентр и просим обесточить всю стойку :)

Добавлено
Цитата Астарот @
Кстати, супервизоры умеют не только супервизить и заверать дочерних супервизоров, но и динамически порождать новые процессы. В общем слишком полезная штука, что бы от нее отказываться.
Я от них не отказываюсь, кое-где они используются. Например в хттп-сервере.

Автор: Астарот 05.12.18, 15:15
Цитата applegame @
Зачем? Обычно звоним в датацентр и просим обесточить всю стойку :)

В следующий раз попробуйте закинуть шашку тола! :)

Цитата applegame @
Я от них не отказываюсь, кое-где они используются. Например в хттп-сервере.

Вот чего я точно никогда не пойму, так это зачем на erlang/elixir городить свой хттп-сервант :D

Автор: applegame 05.12.18, 15:34
Цитата Астарот @
Вот чего я точно никогда не пойму, так это зачем на erlang/elixir городить свой хттп-сервант
А зачем его городить? Уже все нагорожено до нас :)

Автор: Астарот 05.12.18, 16:04
Цитата applegame @
А зачем его городить? Уже все нагорожено до нас :)

Так и я о том, все давно нагорожено до нас и без OTP :)

Автор: D_KEY 05.12.18, 16:52
Цитата Астарот @
Цитата D_KEY @
А это зачем нужно?

Зачем нужен стейт? :D Даже не знаю, что сказать...

Делать ноды с состоянием или без(всякие там кэши - это не состояние, если что) - тоже вопрос, да.
Но я спросил не об этом. Вроде автор процитированного меня понял ну и ладно :)

Автор: 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, по сути это интерапты на уровне аппликации.

Если они не нужны для твоих задач, это не значит что они не нужны никому.

Добавлено
Цитата applegame @
Цитата D_KEY @
Когда будет освобожден ресурс?
Когда приспичит GC.

вызывай его явно если есть необходимость,

Добавлено
Цитата D_KEY @
На практике не критично, ибо легко достигается просто через абстрактные классы без реализации и полей.

Ну вообщем то да, хотя зачем в большинстве языков есть и то и то?

Автор: korvin 05.12.18, 22:21
Цитата sergioK @
вызывай его явно если есть необходимость,

Явный вызов GC — моветон. А зачастую, вызов какой-нибудь System.gc() (или как там в Java) вовсе не означает, что он возьмёт и запустится.

Цитата sergioK @
Ну вообщем то да, хотя зачем в большинстве языков есть и то и то?

Потому что в этих языках интерфейсы и абстрактные классы имеют разную семантику. С тем же успехом можно спросить, почему в большинстве языков есть 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
Цитата korvin @
А если баг или какой другой фейл в нижележащем слое (ОС, железо, вот это всё)?
Помрет, предварительно пискнув в критлог. Помрет только этот процесс, остальные-то продолжат работу.

Автор: Астарот 06.12.18, 06:36
Цитата Qraizer @
Ежели так, то я против спотыканий. При спотыканиях оно хоть как-то, но пашет, а когда не пашет, то мотивация поправить багу выше

Это если бага у тебя, а не приходит со стороны :)

Автор: korvin 06.12.18, 06:37
Цитата sergioK @
Он для этого и сделан, и он 100% запуститися

Не 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
Цитата sergioK @
А вот зачем в С++ такое, и что с ним делать Я не понимаю.

Класс, который может отдавать себя как Person, но при этом то, что он является Person - деталь его реализации, а не его контракт. Сплошь и рядом такое может быть.

Цитата sergioK @
Я про прямой доступ памяти, через поинтер или ссылку.
Для одних целей это хорошо, для безопасности нет.

В расте есть прямой доступ к памяти, при этом язык даже более безопасен, пожалуй, чем все эти явошарпы.

Автор: JoeUser 06.12.18, 10:13
Цитата OpenGL @
В расте есть прямой доступ к памяти, при этом язык даже более безопасен, пожалуй, чем все эти явошарпы.


Зачет-логика!!! :lol: Прямой доступ к памяти оборачивается в unsafe-блоки. Наличие только одного такого блока в проге всю безопасность сводит на нет. А вот если бы прямого доступа не было, не было этих unsafe-блоков, тогда конечно, без вопросов.

Автор: OpenGL 06.12.18, 12:55
Цитата JoeUser @
Наличие только одного такого блока в проге всю безопасность сводит на нет.

Лол. А наличие монады Io в хаскеле, видимо, сводит на нет всю пользу чистых функций. А наличие типа Any в чём-нибудь а-ля TypeScript сводит на нет всю пользу от типизации :lool:

Автор: JoeUser 06.12.18, 16:23
OpenGL, безопасность - она из другого измерения, нежели польза :lol:
С хорошей или плохой пользой жить можно. А вот безопасность - это ... короче, там может произойти сигминтация фаульта! 8-)

Автор: sergioK 06.12.18, 17:41
Цитата OpenGL @
Цитата sergioK @
А вот зачем в С++ такое, и что с ним делать Я не понимаю.

Класс, который может отдавать себя как Person, но при этом то, что он является Person - деталь его реализации, а не его контракт. Сплошь и рядом такое может быть.

Это называется салат или каша ;) , a точее has a , тоесть Proxy или Decorator
ну так и пиши - этот Proxy/Decorator явно, зачем такие сложности ?

https://www.bogotobogo.com/cplusplus/private_inheritance.php

Автор: OpenGL 06.12.18, 18:47
Цитата JoeUser @
OpenGL, безопасность - она из другого измерения, нежели польза

О, началась казуистика :D Нивапрос, замени "сводит пользу от <something> на нет" на "сводит <something> на нет" - не поменяется ничего.

Цитата sergioK @
ну так и пиши - этот Proxy/Decorator явно, зачем такие сложности ?

Я хз, где ты сложности увидел.

Автор: JoeUser 07.12.18, 02:00
Цитата OpenGL @
Нивапрос, замени "сводит пользу от <something> на нет" на "сводит <something> на нет" - не поменяется ничего.

Юнит тестирование утверждения :lol: "Убить пользу человека на нет" vs "убить человека на нет". Ахтунт!!! Британские ученые заметили, что во втором случае происходит декремент человеческой популяции! :blink:

Автор: sergioK 07.12.18, 04:27
Цитата OpenGL @
Цитата sergioK @
ну так и пиши - этот Proxy/Decorator явно, зачем такие сложности ?

Я хз, где ты сложности увидел.

Я в смысле оверхед, юзать такое можно, но зачем ?
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
Цитата applegame @
Это наконец-то случилось. Вышел релиз GCC 9 с компилятором D:

Команду GCC возглавил Артас?

Автор: applegame 06.05.19, 06:06
Цитата korvin @
Команду GCC возглавил Артас?
хз кто это такой, подготовка к сему событию шла лет пять, не меньше.
Решение о включении было принято почти два года назад:
Цитата applegame @
Компилятор D gdc утвержден для включения в состав GCC.

Автор: D_KEY 06.05.19, 13:39
Цитата applegame @
хз кто это такой

Отсылка к warcraft 3 же, не?

Автор: applegame 06.05.19, 16:34
Цитата D_KEY @
Отсылка к warcraft 3 же, не?
Это надо у korvin спросить. Как-то он слишком тонко пошутил. :)

Автор: D_KEY 06.05.19, 18:10
Думаю, это как-то связано с некромантией :D

Автор: korvin 07.05.19, 15:56
Цитата applegame @
Это надо у korvin спросить. Как-то он слишком тонко пошутил.

D_KEY всё верно понял. Я просто не ожидал, что ты не знаком с этим персонажем. =)

Автор: applegame 07.05.19, 17:54
Цитата korvin @
Цитата applegame @
Это надо у korvin спросить. Как-то он слишком тонко пошутил.

D_KEY всё верно понял. Я просто не ожидал, что ты не знаком с этим персонажем. =)

Незнаком. Варя Крофт как-то мимо меня прошла.

Автор: OpenGL 22.07.19, 08:15
Владение и заимствование в D. Что-то растом запахло :)

Автор: D_KEY 22.07.19, 10:52
Если нормально все запилят, то D будет лучше rust. Но, боюсь, язык это не "спасет", в смысле массового использования.

Автор: Астарот 22.07.19, 10:54
Цитата D_KEY @
Если нормально все запилят, то D будет лучше rust

D уже 18 лет, а у него все пилят и пилят :D

Автор: OpenGL 22.07.19, 11:57
Цитата D_KEY @
Если нормально все запилят, то D будет лучше rust.

Хз. Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы, то может и смогут выехать на нормальном метапрограммировании. Всё-таки растовское в сравнении даже с плюсовым убогое.

Автор: D_KEY 22.07.19, 12:04
Цитата OpenGL @
Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы

Ну опциональный GC нормальная идея. Сейчас они выпиливают(или уже выпилили) зависимость от него во всех стандартных либах. В таком варианте будет ок.

Цитата
то может и смогут выехать на нормальном метапрограммировании

Если C++ к тому времени не догонит. Таки развитие плюсов идет очень хорошими темпами.

Автор: OpenGL 22.07.19, 12:33
Цитата D_KEY @
Ну опциональный GC нормальная идея.

Иногда да. Но мне не нравится из-за того, что непонятно, как GC должен сочетаться с нормальными деструкторами. Объекты, временем жизни которых предполагается управлять через GC, не должны содержать в себе поля, которым наличие детерминированного деструктора важно? Или пусть содержат, но тогда вызов и их деструкторов будет когда придётся? Оба решения выглядят по-дурацки как по мне.

Автор: Астарот 22.07.19, 12:47
Цитата OpenGL @
Или пусть содержат, но тогда вызов и их деструкторов будет когда придётся?

Это будет что-то типа метода 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
Цитата OpenGL @
никто не знает, откуда гифка в начале статьи? :)

https://www.youtube.com/watch?v=O9FNkrrG0tc

Автор: JoeUser 23.07.19, 16:05
Цитата D_KEY @
то D будет лучше rust

Ололо. Откуда инфа?
Я зык раст весьма специфичен и разнообразен. Вряд ли получится его оценить с любым другим в полной мере (я не говорю про ООП-поддерживающем). Частные тесты - тут да, будут интересны.
Цитата OpenGL @
метапрограммировании

Все на этом помешались. Раньше пилили чисто либы "под все", щя метапилют ... но выхлопа нуль как-то.

Автор: D_KEY 23.07.19, 16:46
Цитата JoeUser @
Цитата D_KEY @
то D будет лучше rust

Ололо. Откуда инфа?

Оттуда, что в нем будут все возможности раста, но без ограничений, а еще в нем уже есть нормальное ООП, отличные шаблоны и т.п.
И синтаксис у него неплох, в отличие от rust.

Добавлено
Цитата JoeUser @
Частные тесты - тут да, будут интересны

Ты про что? Про производительность? Тут за C++ вряд ли кто сможет угнаться.

Автор: OpenGL 24.07.19, 17:17
Цитата D_KEY @
Тут за C++ вряд ли кто сможет угнаться.

И всё же местами раст оказывается быстрее.

Автор: D_KEY 24.07.19, 17:25
Цитата OpenGL @
Цитата D_KEY @
Тут за C++ вряд ли кто сможет угнаться.

И всё же местами раст оказывается быстрее.

Мне лень смотреть, но скорее всего на крестах код написан так себе, а в коде на rust полно unsafe. Насколько я понимаю, сам раст мало делает оптимизаций и там она идет на уровне llvm. И если это так, то странно было бы ожидать от раста производительности си или крестов.

Добавлено
А там сравнивают с gcc. Это вообще может быть фактически тест gcc vs llvm :)
Честнее сравнить с clang на той же версии llvm.

Автор: OpenGL 24.07.19, 17:42
Цитата D_KEY @
Мне лень смотреть, но скорее всего на крестах код написан так себе, а в коде на rust полно unsafe.

Правильно, зачем бегло посмотреть в течение 10 секунд, если за пять можно сгенерировать глупое предположение? :D unsafe там только для использования gmp юзается в одном тесте.

Цитата D_KEY @
А там сравнивают с gcc. Это вообще может быть фактически тест gcc vs llvm

Вот это, вероятно, более состоятельный аргумент.

Автор: D_KEY 24.07.19, 17:51
Цитата OpenGL @
unsafe там только для использования gmp юзается в одном тесте.

gmp как бы сишная либа :) Даже с asm местами.
Или это норм? :)
Там ещё в коде почему-то делают "сишные" структуры через #[repr©]. Интересно, зачем?

Надо будет как-нибудь таки потакать палочкой.

Автор: OpenGL 24.07.19, 18:20
Цитата D_KEY @
Или это норм?

Я не знаю :-? Это вычисление цифр числа пи, и в сишных исходниках тоже юзается gmp. Странный какой-то тест.

Автор: D_KEY 24.07.19, 18:23
Александреску(перевод на Хабре)
Какой язык — D, Go или Rust имеет лучшие перспективы заменить C и почему?

Автор: OpenGL 24.07.19, 18:27
Оригинал 2015 года :D

Добавлено
Думаю, где я видел шутку про "день ног" в программировании. Оказывается, я уже читал перевод ответа на эту статью Александреску :D

Автор: 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
Цитата Wound @
Хотелось бы четко понимать, где Rust или D будут лучше, остальных.

Это слишком срачегенераторная формулировка вопроса :) Исходить надо из плюсов языка, и уже за их счёт определять, насколько они важны лично для тебя и в твоих проектах. Для раста, например, таковые это строгие статические проверки. В нём у тебя у каждой сущности есть своё время жизни, при взятии ссылок компилятор за всеми временами жизни следит и, если обнаруживается несоответствие, отказываться компилить. Это даёт возможность выражать в дизайне API условия навроде "вектор нельзя изменять пока есть итераторы на него". Также есть инструменты, позволяющие сказать, что некий класс нельзя юзать из другого потока. Например, класс Rc, который является аналогом плюсового shared_ptr, но без атомарного счётчика ссылок, очевидно, нельзя заюзать не в том потоке, в котором ты его создал, и не даст тебе сделать это именно компилятор, а не рантайм. Из минусов (хотя это и плюс тоже :) ) всего этого - необходимо лучше продумывать архитектуру и чётко понимать, кто кем у тебя должен владеть, так что для "херак и в продакшн" раст не годится совершенно. И в итоге всё это делает хаскелевский мем "программа либо компилится, либо работает как надо" в какой-то степени верным и для раста. За D не скажу подробно, это applegame надо звать, либо читать тему с самого начала.

Автор: korvin 26.07.19, 21:32
Цитата D_KEY @
а еще в нем уже есть нормальное ООП

Что такое «нормальное ООП»?

Добавлено
Цитата OpenGL @
хаскелевский мем "программа либо компилится, либо работает как надо"

В первый раз слышу. Откуда это?

Автор: Астарот 26.07.19, 21:47
Цитата korvin @
В первый раз слышу. Откуда это?

Есть подозрение, что это про Скалу. Ну, и, разумеется, там пропущено "не".

Автор: D_KEY 26.07.19, 23:41
Цитата korvin @
Цитата D_KEY @
а еще в нем уже есть нормальное ООП

Что такое «нормальное ООП»?

Как в мейнстрим языках. Классы, интерфейсы, наследование и т.п.

Автор: applegame 27.07.19, 08:56
Цитата OpenGL @
Владение и заимствование в D. Что-то растом запахло
Тут не запахло, они реально делают это под влиянием идей раста. Правда с вполне конкретной целью. Они хотят библиотечно реализовать всякие RC-контейнеры и хотят сделать это максимально безопасно. Вот и пыжатся, чтобы нельзя было так просто поломать RC.
Цитата OpenGL @
Хз. Если выпилят GC и пойдут по тому же пути, что и раст - управление всеми ресурсами, включая память, через деструкторы, то может и смогут выехать на нормальном метапрограммировании.
Выпиливать GC никто не будет. Программист сам может выпилить GC если он ему не нужен, или прицепить свой собственный GC. Я тут развлечения ради попиливаю на D мелкую RTOS для микроконтроллеров STM32 с кооперативной многозадачностью, никакого GC очевидно там нет. Другой вопрос, что без GC большая часть стандартной либы отваливается, также отваливается и часть фич самого языка. Они работают над этим, добились довольно серьезного прогресса, надо признать.
Цитата D_KEY @
Ты про что? Про производительность? Тут за C++ вряд ли кто сможет угнаться.
Странная фраза. Чего за ним угоняться-то? Компиляторы для эквивалентного кода в плюсах и D генерят абсолютно одинаковый асм. То же самое касается и сяшки и раста.
Цитата Qraizer @
Кстати, applegame, всё хочу спросить, но постоянно забываю, так, что даже не помню, спрашивал ли уже: реально ли на D напрограммить полноценные мультиметоды? По идее, его метафичи равноценны плюсовым, так что почему бы и нет.
Не знаю, что ты подразумеваешь под "полноценные". Но все, что можно наметапрограммить в плюсах, можно наметапрограммить в D.

Автор: korvin 27.07.19, 09:51
Цитата D_KEY @
Как в мейнстрим языках. Классы, интерфейсы, наследование и т.п.

Почему ты считаешь, что оно и только оно — нормальное?

Автор: D_KEY 27.07.19, 10:58
Цитата applegame @
Странная фраза. Чего за ним угоняться-то? Компиляторы для эквивалентного кода в плюсах и D генерят абсолютно одинаковый асм. То же самое касается и сяшки и раста.

Разница есть даже между разными компиляторами C++. Rust если и у гонится, то только за счет llvm, но, насколько мне известно, пока сам компилятор оптимизации на уровне языка особых не делает. В отличие от того же clang. Т.е. только llvm.
За D не скажу, но вроде тесты тоже не в его пользу попадались.

Добавлено
Цитата korvin @
Цитата D_KEY @
Как в мейнстрим языках. Классы, интерфейсы, наследование и т.п.

Почему ты считаешь, что оно и только оно — нормальное?

Нормальное не в смысле "правильное", а в смысле "привычное", "обыденное", как раз "мейнстримные"

Автор: OpenGL 27.07.19, 11:21
Цитата korvin @
В первый раз слышу. Откуда это?

Хз, собирательное мнение из пары статей по хаскелю. Личный опыт совсем небольшого говнокодинга на нём говорит, что глупые ошибки там сделать сложнее, т.е. в принципе притянуть за уши можно.

Цитата Астарот @
Ну, и, разумеется, там пропущено "не".

Фак. И правда :lol:

Автор: D_KEY 27.07.19, 11:26
Цитата applegame @
Выпиливать GC никто не будет. Программист сам может выпилить GC если он ему не нужен, или прицепить свой собственный GC. Я тут развлечения ради попиливаю на D мелкую RTOS для микроконтроллеров STM32 с кооперативной многозадачностью, никакого GC очевидно там нет. Другой вопрос, что без GC большая часть стандартной либы отваливается, также отваливается и часть фич самого языка. Они работают над этим, добились довольно серьезного прогресса, надо признать.

Это хорошо. Так они собираются убрать зависимость стандартной библиотеки от GC полностью или такой цели не стоит, а просто потихоньку убирают там, где можно обойтись?

Цитата
Не знаю, что ты подразумеваешь под "полноценные". Но все, что можно наметапрограммить в плюсах, можно наметапрограммить в D.

А наоборот?

Автор: OpenGL 27.07.19, 11:40
Цитата applegame @
RC-контейнеры

Что это за зверь?

Автор: korvin 27.07.19, 12:05
Цитата OpenGL @
Цитата Астарот @
Ну, и, разумеется, там пропущено "не".

Фак. И правда :lol:

С «не» да, слышал такой мем.

Добавлено
Цитата D_KEY @
Нормальное не в смысле "правильное", а в смысле "привычное", "обыденное", как раз "мейнстримные"

Тогда почему ты указываешь это как критерий какого-то положительного качества языка?

Автор: D_KEY 27.07.19, 13:46
Цитата korvin @
Тогда почему ты указываешь это как критерий какого-то положительного качества языка?

Потому, что будет легче на него перейти и переводить существующие системы на него.

Автор: JoeUser 27.07.19, 15:27
Цитата D_KEY @
Потому, что будет легче на него перейти и переводить существующие системы на него.

Не факт. Все зависит от привычек. Я вот тоже как только начал читать про Раст, сразу как-то воспринял в штыки, что в нем весь фарш ООП реализуется средствами синтаксиса частично. Остальное конечно тоже можно сделать, но чуть сложнее (если не ошибаюсь OpenGL показывал). Но если, к примеру, сравнить С++ и Раст, просто подход разный. У С++ основной подход - это реализация свойств путем объявления методов, наследования для расширения этого "набора свойств", виртуализации методов для переопределения свойств после наследования. У Раста другой подход - реализация поведений. Тоже подход, который имеет право на жысть, как основная концепция. Могу конечно ошибаться, пока только изучаю, но во многих статьях именно это ставят как особенность языка (не говоря конечно о заимствованиях и временах жизни).

Автор: D_KEY 27.07.19, 17:03
Цитата JoeUser @
Цитата D_KEY @
Потому, что будет легче на него перейти и переводить существующие системы на него.

Не факт. Все зависит от привычек.

Да, зависит от привычек. И если их не надо или не обязательно менять, то переход будет легче :)

Автор: JoeUser 27.07.19, 17:07
Цитата D_KEY @
И если их не надо или не обязательно менять, то переход будет легче

А если есть привычка не использовать ООП - переход будет труднее :)

Автор: applegame 27.07.19, 17:30
Цитата D_KEY @
За D не скажу, но вроде тесты тоже не в его пользу попадались.
Есть и обратные тесты, где D обгоняет плюсья. Но это все синтетика, в которых если порыться выясняется, что код нихрена не эквивалентный. Референсный компилятор dmd довольно паршиво оптимизирует, а вот gdc (который уже в gcc) и ldc оптимизируют не хуже соответственно g++ и clang. В моей Fedora и gdc и ldc ставится из стандартных реп.
Цитата D_KEY @
Так они собираются убрать зависимость стандартной библиотеки от GC полностью или такой цели не стоит, а просто потихоньку убирают там, где можно обойтись?
Там где можно обойтись убирают. Полностью отвязать в принципе невозможно, так как встроенные массивы и замыкания могут задействовать GC.
Цитата D_KEY @
А наоборот?
Наоборот нет. В 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
Цитата applegame @
Но все, что можно наметапрограммить в плюсах, можно наметапрограммить в D.
А насколько просто переносится туда метакод оттуда?

Автор: D_KEY 27.07.19, 17:44
Цитата JoeUser @
А если есть привычка не использовать ООП - переход будет труднее :)

Да, но людей с такой привычкой много, мейнстрим же.

Автор: Qraizer 27.07.19, 17:44
Цитата applegame @
Не знаю, что ты подразумеваешь под "полноценные".
На джитхабе есть их, но все неполноценные. Например, требующие предоставить полный набор перекрывающих сигнатур. Или всего лишь двупараметрические. Без статических параметров. ...итп. А для полноценности требуются мультиметоды, максимально похожие на обычные функции: произвольная -арность, отсутствие ограничений на типы параметров, лишь некоторые из которых, указывается в прототипе, должны связываться в рантайм, перекрывающие сигнатуры не должны обязательно покрывать полный перебор вариантов, для не предоставленных вариантов должны применяться стандартные правила перегрузки most viable. Как минимум.

Автор: applegame 27.07.19, 17:55
Цитата Qraizer @
А насколько просто переносится туда метакод оттуда?
Трудно сказать. Что-то простое переносится просто:
<{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 умудряется вызывать восторг и ненависть одновременно. :lol:
Ну и я бы не стал писать на D код для авионики. :)

Автор: D_KEY 27.07.19, 17:57
Цитата applegame @
а вот gdc (который уже в gcc) и ldc оптимизируют не хуже соответственно g++ и clang.

Ну круто, если так :)

Автор: applegame 27.07.19, 18:01
Цитата D_KEY @
Ну круто, если так
D очень похож на плюсы, так что это не удивительно.

Автор: D_KEY 27.07.19, 18:21
Цитата applegame @
Полностью отвязать в принципе невозможно, так как встроенные массивы и замыкания могут задействовать GC.

А этим можно как-то управлять?

Добавлено
Цитата applegame @
Цитата D_KEY @
Ну круто, если так
D очень похож на плюсы, так что это не удивительно.

Ну оптимизирующий компилятор - достаточно сложная штука, у C и C++ больше и ресурсов и наработок.

Автор: applegame 27.07.19, 18:51
Цитата D_KEY @
А этим можно как-то управлять?
Можно заставить компилятор запретить операции с GC в нужном скоупе и не пользоваться этими операциями, заменяя их на RAII, RC (счетчики ссылок), а то и на старое доброе ручное управление памятью.
Цитата D_KEY @
Ну оптимизирующий компилятор - достаточно сложная штука, у C и C++ больше и ресурсов и наработок.
Во-первых, автор D - Уолтер Брайт, который сам является разработчиком хорошо известного в прошлом C++ компилятора. Во-вторых, вероятно, ты недооцениваешь оптимизации llvm и бекенда gcc. Все три компилятора D: dmd, gcc и ldc используюут один и тот же фронтенд. А вот бекенды у них разные. Результаты весьма отличаются.

Автор: Wound 27.07.19, 19:14
D на какую область ориентирован? У него просто синтаксис с какой то встроенной библиотекой? Многопоточность, кросплатформенность на каком уровне? Какие библиотеки под него есть? Игры писать там? Веб? Десктоп? Или это просто какой то красивый синтаксис?

Автор: applegame 28.07.19, 07:28
Цитата Wound @
D на какую область ориентирован? У него просто синтаксис с какой то встроенной библиотекой? Многопоточность, кросплатформенность на каком уровне? Какие библиотеки под него есть? Игры писать там? Веб? Десктоп? Или это просто какой то красивый синтаксис?
Область у D приблизительно совпадает с C/C++, но из-за достаточно удобного синтаксиса и быстрой компиляции он неплохо зашел в web и даже в скриптинг. С многопоточностью все отлично, с библиотеками не ахти, но к D можно прибиндить сишные и плюсовые либки. Так что игры писать можно. Без рантайма (а значит без GC и большой части стандартной либы) поддерживает, в принципе, все что поддерживают gcc и llvm. Полноценно поддерживаются x86/x86_64 Linux/Windows/MacOS/FreeBSD. Существуют неофициальные билды для Android и Raspberry PI.
Короче, если отклонился от официально поддерживаемых платформ - готовся к танцам с бубном. Например: Как на D писать под ARM

Автор: Flex Ferrum 28.07.19, 11:33
Заканчивалась вторая декада 21-го века. Люди всё ещё придумывали, чем бы им заменить С++. Варианты с Java, C#, D, Go и Rust уже пробовали... Надо придумывать новые! :D

Автор: OpenGL 28.07.19, 11:42
Явошарпы и go разве претендовали на замену плюсам? По-моему максимум на что они претендовали это на какую-либо нишу.

Автор: JoeUser 28.07.19, 12:42
Цитата Flex Ferrum @
Надо придумывать новые!

Ну в нише мобильных устройств С++ таки подвинулся нехотя :lol:

Автор: D_KEY 28.07.19, 12:48
Цитата JoeUser @
Цитата Flex Ferrum @
Надо придумывать новые!

Ну в нише мобильных устройств С++ таки подвинулся нехотя :lol:

Да он много где подвинулся. Просто не все хотят это признавать.

Автор: 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
Цитата applegame @
Прямой плюсовой аналог однозначно просрет дешному во всем

Вот мне помнится, что по крайней мере в скорости вызовов не просирает, а чуть ли не выигрывает :)
Если не лень, можешь померить.

Добавлено
Цитата
__attribute((noinline))

Нахрена?

Автор: applegame 28.07.19, 14:26
Цитата D_KEY @
Вот мне помнится, что по крайней мере в скорости вызовов не просирает, а чуть ли не выигрывает
Скорость вызова одинакова, я зырил асм.
Цитата D_KEY @
Нахрена?
Затем же зачем и
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    pragma(inline, false)

Иначе и clang и ldc оптимизируют bar в нуль: вернуть 20. :lol:

Добавлено
Сравниваем шаблонные версии:
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
Цитата applegame @
void foo(std::function<void(int)> fn) {
Нахрена?

Добавлено
А, сорри, страничка новая.

Автор: amk 28.07.19, 20:26
Цитата applegame @
А вот можно ли в плюсах создать "типизированную" лямбду (std::function<void(int)> например) с замыканиями, но без аллокаций в куче?
Цитата D_KEY @
Ну если тебя не устроит auto f = ... или передача в шаблон функции, то нет.
Насколько я понимаю, нет синтаксиса, чтобы типизировать лямбду явно. А неявно компилятор в любом случае её типизирует (поскольку с нетипизированными объектами работать не умеет)
И, насколько понимаю, для замыкания всегда выделяется память в стеке.

Автор: Qraizer 29.07.19, 17:59
Цитата amk @
И, насколько понимаю, для замыкания всегда выделяется память в стеке.
Для замыканий память по любому нужна. Хоть какая-нибудь где-то там. Вопрос "можно ли без аллокаций", думаю, надо понимать как "можно ли без 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
Цитата Qraizer @
Для замыканий память по любому нужна. Хоть какая-нибудь где-то там.
Какая-нибудь нужна, но в D нередко можно обойтись без дополнительной памяти для замыканий. Ни стековой ни dynamic storage ни GC. Плюсы́ такого фокуса, ЕМНИП, не умеют.
Цитата Qraizer @
Но я-то за Плюсы. Динамический полиморфизм за интерфейсом скрывает информацию об исходном типе, однако её сохраняет статический полиморфизм. Так что да, где спасовал std::function<>, вывозит шаблон.
Ну этот подход работает и в D, так что здесь преимуществ нет.

Автор: Qraizer 30.07.19, 11:20
Цитата applegame @
Ни стековой ни dynamic storage ни GC.
Каким образом?
Цитата applegame @
Ну этот подход работает и в D, так что здесь преимуществ нет.
Причём тут преимущества? Я за недостатки. Просто иначе std::function<> не может быть устроен. Другое дело шаблон, он недостатка не имеет.

Автор: applegame 30.07.19, 13:22
Цитата Qraizer @
Каким образом?
Если время жизни лямбды меньше времени жизни переменных замыкания, то можно не резервировать дополнительную память, а обращаться напрямую к данным на стеке. 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<> не может быть устроен.
А, окай, я тебя неверно понял.
Цитата Qraizer @
Другое дело шаблон, он недостатка не имеет.
Но есть другой недостаток: например, нельзя сделать массив лямбд с одинаковой сигнатурой, но разными замыканиями.

Автор: D_KEY 30.07.19, 13:31
А какие преимущества перед шаблоном в данном случае?

Добавлено
Цитата applegame @
Но есть другой недостаток: например, нельзя сделать массив лямбд с одинаковой сигнатурой, но разными замыканиями.

А для такого случая эта штука со scope как будет работать?

Автор: Qraizer 30.07.19, 13:57
Цитата applegame @
Если время жизни лямбды меньше времени жизни переменных замыкания, то можно не резервировать дополнительную память, а обращаться напрямую к данным на стеке. D так умеет
Так это просто оптимизация. Оптимизировать и C++ умеет. Для общего-то случая такая оптимизация не гарантируется.

Автор: applegame 30.07.19, 23:43
Цитата D_KEY @
А какие преимущества перед шаблоном в данном случае?
Даже с шаблоном под замыкания в плюсовой лямбде будет выделена память как минимум на стеке. Например, на стеке лежит переменная, а в замыкании ссылка на эту переменную. Ну и template code bloat никто не отменял.
Цитата D_KEY @
А для такого случая эта штука со scope как будет работать?
К такой штуке scope не прикрутишь никак. Тут будут аллокации в GC. Либо можно как в плюсах хранить функторы аналогичные std::function.
Цитата Qraizer @
Так это просто оптимизация. Оптимизировать и C++ умеет. Для общего-то случая такая оптимизация не гарантируется.
Плюсы не смогут сделать такую оптимизацию в общем случае. В плюсах нет scope.

Но в целом это мелочь, я считаю. Но интересная, на мой взгляд.

Автор: Qraizer 31.07.19, 11:44
Цитата applegame @
Плюсы не смогут сделать такую оптимизацию в общем случае. В плюсах нет scope.
Во-первых, это сделано в твоём собственном листинге вверху. Я даже проверил, визуалка тоже так умеет. Во-вторых, в Плюсах нет и Cёвого restrict. По той же причине, подозреваю, почему нет scope.

Автор: korvin 02.08.19, 20:17
Цитата D_KEY @
Потому, что будет легче на него перейти и переводить существующие системы на него.

Ну вон в Go нет «нормального ООП» и вообще никакого параметрического полиморфизма, да и обработка ошибок не «нормальная» (привычна разве что для махровых Сишников). Каналы, опять же, для многих «программистов на мейнстримных языках» — не сильно привычный способ синхронизации. Но достаточно много людей его таки начали использовать.

Автор: applegame 04.08.19, 09:03
Цитата Qraizer @
Во-первых, это сделано в твоём собственном листинге вверху. Я даже проверил, визуалка тоже так умеет.
Визуалка видимо инлайнит. Если разнести эти функции, то такую оптимизацию в плюсах в принципе невозможно будет сделать.
Но в целом фигня. Мне бы плюсики с синтаксисом и метапрограммированием дешки и я, наверное, был бы счастлив.

Автор: D_KEY 04.08.19, 16:19
Цитата applegame @
Если разнести эти функции, то такую оптимизацию в плюсах в принципе невозможно будет сделать.

А с -flto?

Автор: Qraizer 05.08.19, 03:49
Цитата applegame @
Визуалка видимо инлайнит
Та не. Если её не одёрнуть __declspec(), она вообще в компайл-тайм константу 20 высчитывает.

Автор: applegame 05.08.19, 13:32
Цитата Qraizer @
Та не. Если её не одёрнуть __declspec(), она вообще в компайл-тайм константу 20 высчитывает.
Ну поэтому я и одергивал, компилятор D тоже так делает.

Автор: 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
Цитата applegame @
Сравните ассемблерный выхлоп функции bar и самой лямбды.

Я ничего не понимаю в ассемблере.

Ocaml, Go.

Автор: D_KEY 14.08.21, 14:33
applegame, поясни за scope в данном кейсе, плиз.

Автор: applegame 14.08.21, 18:11
Цитата D_KEY @
applegame, поясни за scope в данном кейсе, плиз.
Это чит :)
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 безбожно сливает встроенным дешным лямбдам:
...
:huh:

Добавлено
Удивили козла капустой. :D Нефик в ГНУсных портах работать:
<{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, 13:52
Цитата Qraizer @

P.S. Это VS2022, если что. Банальный ключик-O2

Кто людям помогает - тот тратит время зря!!! Хорошими делами прославиццо незя!!! (С)

Добавлено
Цитата Qraizer @
P.S. Это VS2022, если что. Банальный ключик-O2

Ой, отлегло от души ... 12 мин искал, где можно Qraizer'а попытаться обидеть, и вот настал момент!!! :lol:

user posted image

Автор: Majestio 21.05.26, 15:09
Не, посоны!!! По-чесноку ... я знаю поговорку "На дураков не обижаются" ... Но я хотя бы попытался :lol:

Автор: Qraizer 21.05.26, 18:23
Это ты кого... э-э-э... кем обозвал-то? А то был тут у нас один "посетитель":
Цитата
— О, привет. А чё ты тут делаешь?
— Та вот, денег вам надо заплатить.
:blink:
Я так и не понял, кто кому.

P.S. Честно пытался вспомнить, почему тогда замолчал. Не вспомнил. То ли МС-21 заканчивался, то ли SuperJet начинался.

Автор: Majestio 22.05.26, 02:18
Цитата Qraizer @
Это ты кого... э-э-э... кем обозвал-то?

Я нечяянно, по синьке - а это щетай не щетается! :lol: Просто фильм вспомнился клёвый, ретро.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)