Уже использовал его в реальных проектах (сильно больше 1к строк), на серьезные баги не натыкался. Были проблемы с контрактами, они просто во многих случаях не вызывались, а должны были. Еще довольно жестокие грабли — __gshared модификатор, лучше его не использовать. Неаккуратное его использование может приводить к утечкам памяти и боли при синхронизации (ну это его назначение).
Можно написать две программы, по одной из задач benchmarksgame.alioth.debian.org/. Я пытаюсь специализироваться в D, нужен еще спец. по Rust. Тогда можем и сравнить.
Никто кстати не желает забабахать подобное сравнение про D?
Сохранил первичную структуру поста. habrahabr.ru/post/225507/
Сравнение получается не сильно честным, примеры подобраны под сильный статический анализатор, встроенный в Rust, а D в этой области слабее.
Идеал недостижим, это не означает, что не надо к нему двигаться. Заметили часто встречающиеся грабли — исправили, обратили внимание на следующие (которые могут появиться и из-за такого исправления). Вся полезность высокоуровневых языков очевидна при сравнении, например, асма и тех же плюсов.
Однако высокую квалификацию никто не отменял, без нее и грабли не классифицируешь и не уберешь их с дороги, чтобы другим больше не мешались.
Как я понимаю пока только есть поддержка чтения/записи BMP и записи PNG?
При загрузке через SDL_image (модуль ae.utils.graphics.sdlimage) поддерживаются след. форматы (из доков sdl_image):
ICO(Icon)/CUR(Cursor)/BMP, PNM (PPM/PGM/PBM), XPM,
LBM(IFF ILBM), PCX, GIF, JPEG, PNG, TGA, TIFF, and XV thumbnail formats.
Этот модуль я не тестировал, лучше спросить у автора.
Допустим, код поддерживает чтение PNG. И если main принимает в качестве аргумента имя файла, который является либо BMP, либо PNG — как реализовать чтение такого файла и его последующую обработку?
Скорей всего, я вопрос понял неправильно. Если использовать sdlimage, то часть определения формата дается на откуп либе, которая уже по расширению выбирает нужный декодер.
Если реализовывать самому, то полностью compile-time'a тут достичь нельзя. Итого все равно будет явный-неявный switch с вызовом нужного декодера. Но можно генерировать его через mixin'ы для всех поддерживаемых расширений. А получив View, уже все как в статье.
Появляется все больше и больше инструментов для финансирования открытого ПО. Но как это все оформить легально?
Допустим, у меня в голове вертится возможная схема разработки:
Весь код на github под copy-left лицензией, любой может собрать из исходников сам, поучаствовать в разработке, форкнуть.
Пользователи «покупают» продукт и получают регистрацию. На специальном разделе сайта зарегистрированные пользователи могут проголосовать за необходимые им фичи.
В каждый момент времени отображается текущий бюджет проекта.
На основе голосов пользователей бюджет проекта перераспределяется на Bountysource по каждой фиче. Любой, кто реализует фичу — получает это вознаграждение.
Скорей всего, эта схема ущербна, не подходит для большинства проектов и пр. Но вопрос в том, как такое реализовать и не наполучать от налоговой потом по голове?
А про D очень мало информации (в книге Александреску этого нет, на официальном сайте простейший пример). Конструкция mixin — там просто строки, в которых код. Непонятно, можно ли эти строки конструировать программно, если можно — какие операции разрешены для времени компиляции и т.д.
Можно, причем двумя разными способами. Первый — выполнение функций в compile time, второй — через шаблоны. Для примера рассмотрю первый вариант. Практически любые функции, которые не используют IO, указатели и другие низкоуровневые фичи языка можно выполнять на этапе компиляции. Для этого нужно просто использовать функцию в контексте, в котором у нее нет выбора, кроме как выполниться при компиляции (например, присвоить результат к константе enum).
Иллюстрация: есть два энума A и B, нужно сгененрировать switch по элементам первого энума, который поставит в соответствие каждому элементу A элемент в B.
import std.stdio;
enum A
{
a1,
a2,
a3
}
enum B
{
b1,
b2,
b3
}
// Берем два энума и название переменной, для которой будет
// сгенерирован switch
string genSwitch(E1, E2)(string var)
if(is(E1 == enum) && is(E2 == enum))
{
// Просим компилятор выдать нам tuple всех элементов типа
enum E1Members = __traits(allMembers, E1);
enum E2Members = __traits(allMembers, E2);
// Проверяем, чтобы их длинны совпадали, проверка во время компиляции
static assert(E1Members.length == E2Members.length);
// Используем все обычные средства для работы со строками
// для генерации свитча
string s = "final switch("~var~")\n{\n";
foreach(i, member; E1Members)
{
s ~= "\tcase("~E1.stringof~"."~member~"):\n\t{\n";
s ~= "\t\twriteln("~E2.stringof~"."~E2Members[i]~");\n";
s ~= "\t\tbreak;\n\t}\n";
}
return s~"}";
}
void main()
{
auto a = A.a2;
// Способ вывести что-нибудь во время компиляции в консоль
pragma(msg, genSwitch!(A, B)("a"));
// Встраиваем сгенеренный свитч
mixin(genSwitch!(A, B)("a"));
}
На самом деле я встречал очень мало проектов, где namespace использовали не в качестве имуляции модульной системы. Но в остальных случаях с открытыми namespace можно будет говорить уже об автоматичекой генерации байндингов.
Очень двоякое ощущение. С одной стороны — организация и защита «электронного правительства» должна быть именно такой. С другой стороны — белые списки программ, перепрошивка ОС (что автоматом снимает гарантии производителя), свой собственный сорм на каждый комп — это снова разделит мир железным зановесом и убьет местную коммерцию.
Предполагается, что это будет просто синтаксис для static struct (т.е. closed scope) или открытые namespace? В последнем случае это облегчит написание bindings к C++ либам.
Мелькали заявления, что маркетингом должно заниматься сообщество. Но оно все же еще очень маленькое, и пока в игру не вступили крупные компании, D будет сидеть в своей темной нише.
Этот язык с самого начала развивался стихийно, только силами небольшой кучки специалистов. Меня поражает проделанная на сей момент работа и предстоящие проблемы (например, дальнейшая разработка и адаптация инструментов).
Для дальнейших извращений рекомендую А.Александреску «Modern C++ Design», а если этого будет мало, то можно обратить взор на D (в который и ушел автор этой книги), в нем не проблема сделать compile-time raytracer, да и скорость компиляции на порядок выше C++.
Также можно в качестве ключей использовать свои типы, для этого нужно перегрузить операторы:
Полные доки: dlang.org/hash-map.html
Сохранил первичную структуру поста. habrahabr.ru/post/225507/
Сравнение получается не сильно честным, примеры подобраны под сильный статический анализатор, встроенный в Rust, а D в этой области слабее.
Однако высокую квалификацию никто не отменял, без нее и грабли не классифицируешь и не уберешь их с дороги, чтобы другим больше не мешались.
При загрузке через SDL_image (модуль ae.utils.graphics.sdlimage) поддерживаются след. форматы (из доков sdl_image):
ICO(Icon)/CUR(Cursor)/BMP, PNM (PPM/PGM/PBM), XPM, LBM(IFF ILBM), PCX, GIF, JPEG, PNG, TGA, TIFF, and XV thumbnail formats.
Этот модуль я не тестировал, лучше спросить у автора.
А сохранение идет в BMP и PNG
Скорей всего, я вопрос понял неправильно. Если использовать sdlimage, то часть определения формата дается на откуп либе, которая уже по расширению выбирает нужный декодер.
Если реализовывать самому, то полностью compile-time'a тут достичь нельзя. Итого все равно будет явный-неявный switch с вызовом нужного декодера. Но можно генерировать его через mixin'ы для всех поддерживаемых расширений. А получив View, уже все как в статье.
github.com/NCrashed
Производительный веб, игрострой, эволюционные алгоритмы.
Допустим, у меня в голове вертится возможная схема разработки:
Скорей всего, эта схема ущербна, не подходит для большинства проектов и пр. Но вопрос в том, как такое реализовать и не наполучать от налоговой потом по голове?
А хабы данного поста были проверены тулзой? Интересно увидеть диаграмму.Я просто слепой жук.Можно, причем двумя разными способами. Первый — выполнение функций в compile time, второй — через шаблоны. Для примера рассмотрю первый вариант. Практически любые функции, которые не используют IO, указатели и другие низкоуровневые фичи языка можно выполнять на этапе компиляции. Для этого нужно просто использовать функцию в контексте, в котором у нее нет выбора, кроме как выполниться при компиляции (например, присвоить результат к константе enum).
Иллюстрация: есть два энума A и B, нужно сгененрировать switch по элементам первого энума, который поставит в соответствие каждому элементу A элемент в B.
Во время компиляции увидим:
P.S. Это просто иллюстрация. Генерацию через шаблоны того же кода, если интересно, то тоже приведу.
Этот язык с самого начала развивался стихийно, только силами небольшой кучки специалистов. Меня поражает проделанная на сей момент работа и предстоящие проблемы (например, дальнейшая разработка и адаптация инструментов).