Как стать автором
Обновить

Комментарии 54

Где-то внутри меня живет идея, что D станет действительно популярным и востребованным языком, и я буду крайне рад, если именно он станет достойной заменой C++ (Знание мной которого автоматически становится ложным после инкремента версии)
Ждём ответа от Rust'а…
Уж лучше на D, чем на Rust. Попробовал на втором и понял, его синтаксис мои пальцы никак не впитают ((( Уж лучше Golang, хотя и у него есть минусы. Но не смотря на минусы все-таки мысли быстрее конвертятся в код и как это не парадоксально, но спустя время код читается не смотря на убогость синтаксиса!
Насколько я понимаю, golang/rust всё таки идут с новыми идеями. Особенно rust, в районе promise'ов.
Стесняюсь поинтересоваться в чём заключается «убогость» синтаксиса Go?
Ну к примеру часто возникающая задача это вывести на печать несколько полей типа. При решении этой задачи потребуются средства форматирования. Возьмем к примеру код на Java, цель которого распечатать три индекса и значение одного байта:
public String toString() {
    StringBuilder result = new StringBuilder().
            append(String.format("Byte: 0x%02X ; ", memoryByte)).
            append(String.format("II: 0x%04X ; ", instrIndex)).
            append(String.format("MI: 0x%04X ; ", memIndex)).
            append(String.format("SI: 0x%02X ; ", sourceIndex)).
            append(String.format("RI: 0x%02X", resultIndex));
    return result.toString();
}


Перепишите его на Go и сравните с этим примером. Кстати на Python выглядит тоже убого, но куда приятнее!
Я не знаком с Java, и с её форматтером в частности, но думаю что даже на ней этот кусок кода можно было сделать более изящным. Если мы имеем целью вывести несколько полей объекта (байт и три инта) то на Go это делается в одну строчку (http://play.golang.org/p/IqFJzkw6Qs):

return fmt.Sprintf(«Byte: %q, int1: %d, int2: %d, int3: %d», self.byteField, self.intFieldOne, self.intFieldTwo, self.intFieldThree)

При желании, конечно, можно использовать и bytes.Buffer, и bufio.Writer. Только вот зачем?
Этот Java-кусок значительно удобнее Вашего, который немного отформатировал. То что Вы предложили в случае необходимости изменить\удалить что-либо надо будет сделать два действия: 1) поправить формат строку 2) добавить\удалить\изменить аргументы. В случае моего Java-куска надо лишь убрать\добавить очередной append() и на этом ВСЕ! Подобное в go тоже возможно, но выглядит очень убого!

Очень достаточно много раз ошибался при правке формат строки, поэтому вариант StringBuilder -> append() строки мне куда ближе и приятнее. Но опять же это же не единственный пример убогости синтаксиса в Go.
Отойду от темы обсуждаемой нами и добавлю, если вы пишите на Go и добавляете к типу метод toString(), то необязательно его звать! Можно просто указать объект типа.
func main() {
	tmp := test{}
	fmt.Println(tmp)
}

Тогда toString() сам позовется!
привет от любителей по-холоднее...

Если надо быстренько посмотреть внутренности струкруты, то это решается чрезвычайно просто
fmt.Printf("%v", someValue)

Примерно так: play.golang.org/p/ZAhhXrIOtA

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

Дабы не быть голословным. Конкретно ужасна библиотека форматирования fmt и вся подсекция encode/*.
Из-за отсутствия в языке системы обобщенных типов, неоднородности при работе с коллекциями, там всё мясо (обоже мой!) — в runtime-интроспекциях.

Весь код в этих библиотеках в виде лапши следующего типа.
— принимаем на вход interface{}
— проверяем, не nil-ли
— если к нам пришел int — направим его обработчику инта
— а если объект — распарсим в рекурсии
— а если hashmap с ключами не string — шлём всех лесом и выпадаем с panic(!!!)"

Хочу отметить, что проверяется именно строгий string, даже не интерфейс Stringer, который позволит toString. И при этом авторы прикрываются тем, что encoding/xml надо переписать, а в описании JSON явно сказано, что ключи должны быть строками. То, что ключи можно к строкам привести насильственно, авторы почему-то умалчивают.

После этих плясок говорить про удобство ситаксиса…
Скорее уж не заменой, а приятным дополнением. Я бы от С++ отказываться не стал.
А более развёрнуто расскажите, чем вас не устраивает С++ и почему D должен его заменить?
Вы уж простите, но писать совсем развернуто очень не хочется сейчас. И уж категорически не хочется отстаивать свою ТЗ, так что вот кратко:

Мои личные недовольства начались ровно тогда, когда вышел C++11, и в нем сразу нашлись вещи, которые обещали уже только в C++14 исправить. Я не считаю это нормальным ходом развития языка. В этом плане мне чрезвычайно нравится путь развития языка C# — чем дальше, тем проще для программиста, безопаснее и быстрее.
Более того, после выхода этого стандарта я фактически перестал знать львиную долю стандартной библиотеки. Это тоже огорчает. Еще огорчают огромные посты на StackOverflow, где осваивающие новый стандарт ребята бьются как титаны.
Множество известных персон в мире программирования недолюбливают C++, тот же Линус, например.
Чистый C++ доставляет мне в основном боль, если используется без Qt'a. Во всем практически.

В общем не хотелось мне особо сегодня писать вдумчиво, поэтому к концу вообще какая-то лапша) Понимайте как хотите!
Ценю усилия, но для хабра это слишком жидковато. Целые параграфы про то, что такое комментарии и чем writeln отличается от write.
Автор оригинала пытался охватить еще и новичков. Пока получается слишком verbose, но далее должно пойти интереснее, так как будут рассматриваться неочевидные моменты.

Может быть сделать кусочный перевод и пропустить совсем уж начальный материал?
Да, я думаю, стоит сделать «реферат по первым главам» (просто сказать, что комментарий, это "//" и т.д.), и переходить к тому моменту, когда начинаются отличия.
Вы не думали предложить автору оригинала разместить всю книгу на github с возможностью форков и мгновенных исправлений? Ну или русскую версию так оформить.
Напрямую автора не спрашивал, но заметил его желание собирать все на ddili.org. Идеальным был бы вариант github + деплой на gh-pages или вики движок.
Думаю не взлетит, покуда не будет чего то типа Qt'а, но для D.
И на нем, вообще, написано хоть чего нибудь?

Вы лучше, про его хваленое метапрограммирование напишите. Чем оно выгодно отличается от того что в C++14?
Самый бурный проект — серверный фреймворк vibe.d, который по производительности обгоняет node.js.

Да, хорошая идея, пост о средствах метапрограммирования в D + небольшое сравнение с constexpr и выводом типов (оно различается с C++14).
Node.js помоему не блещет производительностью. Если D рекомендуют как замену c++ то и сравнения следует приводить из той же весовой категории )
Ну справедливости ради стоит сказать что в плане производительности с JavaScript могут спорить только компилируемые языки. В частности если сравнивать простые арифметические операции то он на немного медленнее Си (в 1,5-2 раза). Вопрос как писать. А если учитывать что под ноду есть решения дающие возможность писать многопоточные приложения с использованием lock-free структур, то соревноваться тут могут только языки типа D, Go или Rust.
Проводились бенчи и с другими веб-серверами, правда довольно давно.
PHP+Apache2 быстрее ноды? Подозреваю что приложением был обычный hello world.
НЛО прилетело и опубликовало эту надпись здесь
Вот у меня автору статьи вопрос. (Уж совсем нет сил читать доку по D, стар я стал.)

Можно ли темплейтам передавать аргументом кастомный класс? Или как в С++, только типы класов да int'образные?
Можно передавать как аргументы шаблона все что угодно (что можно посчитать в compile-time): POD типы, лямбды, функции, классы, структуры, шаблоны, и даже целиком expressions.

Аргумент — кастомный класс:
import std.stdio;

class A
{
    string field = "Hello";
}

class B(T)
{
    T sub = new T();
}

void main()
{
    auto b = new B!A();
    writeln(b.sub.field);
}
Книга предназначена для обучения языку D читателей — новичков в сфере программирования. Хотя наличие опыта в других языках программирования несомненно было бы полезным, эта книга начинает с самых основ

Введение вроде бы подтверждает. С другой стороны, встречался с утверждением, что D не подходит в качестве первого языка программирования. Интересно ваше мнение по этому поводу (безотносительно распространенности, перспектив и пр.)
Такое утверждение я видел в период перехода с D1 на D2, тогда, да, было обоснованно. Сейчас это хорошо продуманный язык с удобной стандартной библиотекой. Можно на нем писать как на Java или Python и никогда не опускаться на системный уровень. Учитывая очень быструю компиляцию, я уже давно использую D в скриптах.
Немножко удивило dlang.org/pretod.html:

The C Preprocessor Way

#define X(i) ((i) = (i) / 3)

The D Way

int X(ref int i) { return i = i / 3; }

The compiler optimizer will inline it; no efficiency is lost.


Эмм — мне что ж на милость компилятора полагаться что ли? Нельзя ему явно как то сказать что сиё есть compile-time/inline функция?
Логика такова: если функцию вызывать в контексте, когда она может быть выполнена только в compile-time, то она гарантированно выполнится в compile-time.

Т.е.:
int res = X(some_var);  // run-time
auto res = X(some_var); // run-time
enum res = X(some_var); // compile-time only
immutable res = X(some_var); // compile-time или run-time, если не может выполниться в compile-time
static res = X(some_var);    // compile-time или run-time, если не может выполниться в compile-time


А явно указать какие функции inline, какие нет — нельзя. Оптимизатор сам решает этот момент. Помню у GDC была специальная pragma для forceinline, но в общем случае такой фичи нет.
Ага, я этот forceinline по полной юзаю:

#ifndef ALWAYS_INLINE
    #if defined(_MSC_VER)
        #define ALWAYS_INLINE __forceinline
    #elif defined(__GNUC__) || defined(__MINGW32__)
        #define ALWAYS_INLINE inline __attribute__((__always_inline__))
    #else
        #define ALWAYS_INLINE inline
    #endif
#endif


Он clang'ом тож поддерживается. В MSVC __forceinline. Так что получается, по сути поддерживается всеми 3мя основными компиляторами :)
Радует, что в последние месяц-два пошла конкретная движуха на Хабре по обсуждению D, Rust и Go. Спасибо таким активистам как NCrashed за это.
Еще бы код свой выкладывали бы, чтобы было что почитать и чему поучиться. Тогда бы еще лучше было! ;)
Смелое начинание, книга у Али очень подробная и объёмная. Рекомендую держать весь переведённый материал перевода в каком-нибудь одном месте, чтобы потом его можно было легко оформить и добавить как один из официальных переводов.
Хочется учебник для тех, кто хорошо знаком с C++ и готов перейти на D. Чтобы без воды вот этой всей.
Пока на написание такого труда я не готов. Из уже имеющихся книг могу порекомендовать:
1. D Cookbook — свежее собрание приемов, специфичных для D.
2. The D Programming Language (перевод), написана в 2010, поэтому многие примеры могут без пинка не заработать.
Ну конечно, кто ж еще мог быть автором этой статьи :D
Поздний вопрос. Но вот интересно, если в D мы наследуемся от темплейтового класса, и параметры ему передаем на месте, чтобы обратится к нему (тобишь родителю) надо указывать полное имя специализированого родительского класса, аль нет?

Говоря короче:
template<class Args = PoolSettings<> >
struct Pool : SettingsHub<Pool, PoolSettings<Args> > {
    using Base = SettingsHub<Pool, PoolSettings<Args> >;                           // вот - указываем полное имя родителя
    void fire(){
        std::cout << Base::length;                                       // length  у родителя лежит
    }
};


В D можно без Base'а обойтись? А то не сколько наследования, сколько юзингов вокруг. Наследование должно упрощать читабельность, а тут огороды городишь.
Если я верно понимаю суть вопроса (уже изрядно подзабыл С++), то можно не указывать. В D было принято решение делать семантический анализ только после инстанциирования и нет грамматической неоднозначности между < > как операторами и как синтаксисом шаблонов.
Эхх… если б не его не убиваемый GC (стандартные библиотеки без него не работают) — круто было бы.
Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?
> Эхх… если б не его не убиваемый GC (стандартные библиотеки без него не работают) — круто было бы.

Не совсем так — отдельные модули работают, отдельные нет. В грядущем релизе появятся две очень важные возможности для тех, кто старается избежать GC: флаг компилятора -vgc (печатает все места в модуле, которые выделяют память через GC) и новый атрибут @nogc , гарантирующий, что функция транзитивно не использует GC (ошибка компиляции в противном случае).

> Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?

Все проекты по трансляции D в C загнулись, потому что слишком мало кому нужно. Для использования в живом проекте это и не нужно — можно линковать напрямую через extern(C). Вот, например, отчёт об интеграции D с существующими библиотеками на C++ в Facebook: www.youtube.com/watch?v=1JZNvKhA3mA
> Не совсем так — отдельные модули работают, отдельные нет.

Я ошибаюсь, или все листы/векторы/массивы в обеих «стандартных» библиотеках без GC не живут? А энтож квинтэссенция всего программирования, понимаешь ли…

> и новый атрибут @nogc, гарантирующий, что функция транзитивно не использует GC (ошибка компиляции в противном случае).

А как они в таком случае думают ситуацию с станартной либой разрулить? Она ж ляжет все и полностью (ну почти...).
> все листы/векторы/массивы

Массивы не живут в стандартной библиотеке, они встроены непосредственно в язык (а Phobos вообще беден на контейнеры в ожидании github.com/andralex/phobos/blob/allocator/std/allocator.d). Для встроенных массивов GC _необходим_ только для операции ~= (конкатенация). В целом же массив это просто указатель + длинна, а как выделена память — не критично. Обойти GC не так уж трудно, просто теряются гарантии по безопасности работы с памятью.

> Она ж ляжет все и полностью (ну почти...).

Большая часть std.algorithm, std.range и тому подобных модулей уже работают без аллокаций. Остальные модули понемногу вычищают — это долгий процесс.
Полностью отказаться от GC довольно трудно на нынешнем этапе, но для 99.99% приложений это и не нужно, достаточно держать количество мусора на минимуме.
Тоесть они отвязываются от GC? Где это написано?

> достаточно держать количество мусора на минимуме.
Мне, например не понятно, чего оно там с GC крутит (и скорее важны задержки на вызовы GC чем память которая занмается/освобождается). Если написали можно отключить — знач можно, а не как в С++ — можно, но со special rule's ;)
Кнопку ответить нажимай.
Без коронной-спящей аватарки тебя сложно узнать.
Вы ничего не докажете! :)
Мне и не нужно. :)
> Тоесть они отвязываются от GC? Где это написано?

Не понял вопроса :) Это легальный код использующий массивы без GC:
import core.stdc.stdlib;

auto mallocArr(T)(size_t size)
{
    auto chunk = malloc(T.sizeof * size);
    auto typed = cast(int[]) chunk[0..(T.sizeof * size)];
    typed[] = T.init;
    return typed;
}

void main() @nogc
{
    int[] arr = mallocArr!int(5);
    assert(arr.length == 5); 
    assert(arr[0] == 0); 
    arr[0] = 42; 
    assert(arr[0] == 42);
}


dlang.org/phobos/std_container.html#.Array реализует почти точный аналог std::vector из С++

> Мне, например не понятно, чего оно там с GC крутит (и скорее важны задержки на вызовы GC чем память которая занмается/освобождается). Если написали можно отключить — знач можно, а не как в С++ — можно, но со special rule's ;)

Всё очень просто — чем меньше мусора, тем меньше задержки на сканирование :) Явно запретить сканирование в критичных фреймах можно через GC.disable() / GC.enable(). Довольно удобный подход — использовать ручное управление памятью для основных данных программы (через свои аллокаторы), но оставлять GC для мелких полезностей — делегаты, долгоживущие ссылки и т.п.

Вот в этом выступлении (http://youtu.be/WmE7ZR1_YKs) мой коллега вкратце упоминает, как аккуратное выделение памяти позволило достигнуть приемлемых для soft real-time результатов с включенным GC.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории