Комментарии 54
Где-то внутри меня живет идея, что D станет действительно популярным и востребованным языком, и я буду крайне рад, если именно он станет достойной заменой C++ (Знание мной которого автоматически становится ложным после инкремента версии)
+5
Ждём ответа от Rust'а…
+6
Уж лучше на D, чем на Rust. Попробовал на втором и понял, его синтаксис мои пальцы никак не впитают ((( Уж лучше Golang, хотя и у него есть минусы. Но не смотря на минусы все-таки мысли быстрее конвертятся в код и как это не парадоксально, но спустя время код читается не смотря на убогость синтаксиса!
+5
Насколько я понимаю, golang/rust всё таки идут с новыми идеями. Особенно rust, в районе promise'ов.
+1
Стесняюсь поинтересоваться в чём заключается «убогость» синтаксиса Go?
0
Ну к примеру часто возникающая задача это вывести на печать несколько полей типа. При решении этой задачи потребуются средства форматирования. Возьмем к примеру код на Java, цель которого распечатать три индекса и значение одного байта:
Перепишите его на Go и сравните с этим примером. Кстати на Python выглядит тоже убого, но куда приятнее!
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 выглядит тоже убого, но куда приятнее!
-1
Я не знаком с 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. Только вот зачем?
return fmt.Sprintf(«Byte: %q, int1: %d, int2: %d, int3: %d», self.byteField, self.intFieldOne, self.intFieldTwo, self.intFieldThree)
При желании, конечно, можно использовать и bytes.Buffer, и bufio.Writer. Только вот зачем?
0
Этот Java-кусок значительно удобнее Вашего, который немного отформатировал. То что Вы предложили в случае необходимости изменить\удалить что-либо надо будет сделать два действия: 1) поправить формат строку 2) добавить\удалить\изменить аргументы. В случае моего Java-куска надо лишь убрать\добавить очередной append() и на этом ВСЕ! Подобное в go тоже возможно, но выглядит очень убого!
Очень достаточно много раз ошибался при правке формат строки, поэтому вариант StringBuilder -> append() строки мне куда ближе и приятнее. Но опять же это же не единственный пример убогости синтаксиса в Go.
Очень достаточно много раз ошибался при правке формат строки, поэтому вариант StringBuilder -> append() строки мне куда ближе и приятнее. Но опять же это же не единственный пример убогости синтаксиса в Go.
-1
Отойду от темы обсуждаемой нами и добавлю, если вы пишите на Go и добавляете к типу метод toString(), то необязательно его звать! Можно просто указать объект типа.
Тогда toString() сам позовется!
func main() {
tmp := test{}
fmt.Println(tmp)
}
Тогда toString() сам позовется!
0
привет от любителей по-холоднее...
Если надо быстренько посмотреть внутренности струкруты, то это решается чрезвычайно просто
Примерно так: play.golang.org/p/ZAhhXrIOtA
Вообще, дядьки решали свои юз-кейсы и не заморачивались всякими ути-пути. Если посмотреть, через какие костыли некоторые стандартные библиотеки сделаны — спать потом не хочется.
После этих плясок говорить про удобство ситаксиса…
Если надо быстренько посмотреть внутренности струкруты, то это решается чрезвычайно просто
fmt.Printf("%v", someValue)
Примерно так: play.golang.org/p/ZAhhXrIOtA
Вообще, дядьки решали свои юз-кейсы и не заморачивались всякими ути-пути. Если посмотреть, через какие костыли некоторые стандартные библиотеки сделаны — спать потом не хочется.
Дабы не быть голословным. Конкретно ужасна библиотека форматирования fmt и вся подсекция encode/*.
Из-за отсутствия в языке системы обобщенных типов, неоднородности при работе с коллекциями, там всё мясо (обоже мой!) — в runtime-интроспекциях.
Весь код в этих библиотеках в виде лапши следующего типа.
— принимаем на вход interface{}
— проверяем, не nil-ли
— если к нам пришел int — направим его обработчику инта
— а если объект — распарсим в рекурсии
— а если hashmap с ключами не string — шлём всех лесом и выпадаем с panic(!!!)"
Хочу отметить, что проверяется именно строгий string, даже не интерфейс Stringer, который позволит toString. И при этом авторы прикрываются тем, что encoding/xml надо переписать, а в описании JSON явно сказано, что ключи должны быть строками. То, что ключи можно к строкам привести насильственно, авторы почему-то умалчивают.
Весь код в этих библиотеках в виде лапши следующего типа.
— принимаем на вход interface{}
— проверяем, не nil-ли
— если к нам пришел int — направим его обработчику инта
— а если объект — распарсим в рекурсии
— а если hashmap с ключами не string — шлём всех лесом и выпадаем с panic(!!!)"
Хочу отметить, что проверяется именно строгий string, даже не интерфейс Stringer, который позволит toString. И при этом авторы прикрываются тем, что encoding/xml надо переписать, а в описании JSON явно сказано, что ключи должны быть строками. То, что ключи можно к строкам привести насильственно, авторы почему-то умалчивают.
После этих плясок говорить про удобство ситаксиса…
+1
Скорее уж не заменой, а приятным дополнением. Я бы от С++ отказываться не стал.
0
А более развёрнуто расскажите, чем вас не устраивает С++ и почему D должен его заменить?
0
Вы уж простите, но писать совсем развернуто очень не хочется сейчас. И уж категорически не хочется отстаивать свою ТЗ, так что вот кратко:
Мои личные недовольства начались ровно тогда, когда вышел C++11, и в нем сразу нашлись вещи, которые обещали уже только в C++14 исправить. Я не считаю это нормальным ходом развития языка. В этом плане мне чрезвычайно нравится путь развития языка C# — чем дальше, тем проще для программиста, безопаснее и быстрее.
Более того, после выхода этого стандарта я фактически перестал знать львиную долю стандартной библиотеки. Это тоже огорчает. Еще огорчают огромные посты на StackOverflow, где осваивающие новый стандарт ребята бьются как титаны.
Множество известных персон в мире программирования недолюбливают C++, тот же Линус, например.
Чистый C++ доставляет мне в основном боль, если используется без Qt'a. Во всем практически.
В общем не хотелось мне особо сегодня писать вдумчиво, поэтому к концу вообще какая-то лапша) Понимайте как хотите!
Мои личные недовольства начались ровно тогда, когда вышел C++11, и в нем сразу нашлись вещи, которые обещали уже только в C++14 исправить. Я не считаю это нормальным ходом развития языка. В этом плане мне чрезвычайно нравится путь развития языка C# — чем дальше, тем проще для программиста, безопаснее и быстрее.
Более того, после выхода этого стандарта я фактически перестал знать львиную долю стандартной библиотеки. Это тоже огорчает. Еще огорчают огромные посты на StackOverflow, где осваивающие новый стандарт ребята бьются как титаны.
Множество известных персон в мире программирования недолюбливают C++, тот же Линус, например.
Чистый C++ доставляет мне в основном боль, если используется без Qt'a. Во всем практически.
В общем не хотелось мне особо сегодня писать вдумчиво, поэтому к концу вообще какая-то лапша) Понимайте как хотите!
+2
Ценю усилия, но для хабра это слишком жидковато. Целые параграфы про то, что такое комментарии и чем writeln отличается от write.
+12
Автор оригинала пытался охватить еще и новичков. Пока получается слишком verbose, но далее должно пойти интереснее, так как будут рассматриваться неочевидные моменты.
Может быть сделать кусочный перевод и пропустить совсем уж начальный материал?
Может быть сделать кусочный перевод и пропустить совсем уж начальный материал?
0
Да, я думаю, стоит сделать «реферат по первым главам» (просто сказать, что комментарий, это "//" и т.д.), и переходить к тому моменту, когда начинаются отличия.
0
Вы не думали предложить автору оригинала разместить всю книгу на github с возможностью форков и мгновенных исправлений? Ну или русскую версию так оформить.
0
Думаю не взлетит, покуда не будет чего то типа Qt'а, но для D.
И на нем, вообще, написано хоть чего нибудь?
Вы лучше, про его хваленое метапрограммирование напишите. Чем оно выгодно отличается от того что в C++14?
И на нем, вообще, написано хоть чего нибудь?
Вы лучше, про его хваленое метапрограммирование напишите. Чем оно выгодно отличается от того что в C++14?
+6
Node.js помоему не блещет производительностью. Если D рекомендуют как замену c++ то и сравнения следует приводить из той же весовой категории )
+1
Ну справедливости ради стоит сказать что в плане производительности с JavaScript могут спорить только компилируемые языки. В частности если сравнивать простые арифметические операции то он на немного медленнее Си (в 1,5-2 раза). Вопрос как писать. А если учитывать что под ноду есть решения дающие возможность писать многопоточные приложения с использованием lock-free структур, то соревноваться тут могут только языки типа D, Go или Rust.
-1
НЛО прилетело и опубликовало эту надпись здесь
Вот у меня автору статьи вопрос. (Уж совсем нет сил читать доку по D, стар я стал.)
Можно ли темплейтам передавать аргументом кастомный класс? Или как в С++, только типы класов да int'образные?
Можно ли темплейтам передавать аргументом кастомный класс? Или как в С++, только типы класов да int'образные?
0
Можно передавать как аргументы шаблона все что угодно (что можно посчитать в 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);
}
0
Книга предназначена для обучения языку D читателей — новичков в сфере программирования. Хотя наличие опыта в других языках программирования несомненно было бы полезным, эта книга начинает с самых основ
Введение вроде бы подтверждает. С другой стороны, встречался с утверждением, что D не подходит в качестве первого языка программирования. Интересно ваше мнение по этому поводу (безотносительно распространенности, перспектив и пр.)
0
Такое утверждение я видел в период перехода с D1 на D2, тогда, да, было обоснованно. Сейчас это хорошо продуманный язык с удобной стандартной библиотекой. Можно на нем писать как на Java или Python и никогда не опускаться на системный уровень. Учитывая очень быструю компиляцию, я уже давно использую D в скриптах.
+1
Немножко удивило dlang.org/pretod.html:
Эмм — мне что ж на милость компилятора полагаться что ли? Нельзя ему явно как то сказать что сиё есть compile-time/inline функция?
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 функция?
0
Логика такова: если функцию вызывать в контексте, когда она может быть выполнена только в compile-time, то она гарантированно выполнится в compile-time.
Т.е.:
А явно указать какие функции inline, какие нет — нельзя. Оптимизатор сам решает этот момент. Помню у GDC была специальная pragma для forceinline, но в общем случае такой фичи нет.
Т.е.:
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, но в общем случае такой фичи нет.
0
Ага, я этот forceinline по полной юзаю:
Он clang'ом тож поддерживается. В MSVC
#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мя основными компиляторами :) +1
_
0
Смелое начинание, книга у Али очень подробная и объёмная. Рекомендую держать весь переведённый материал перевода в каком-нибудь одном месте, чтобы потом его можно было легко оформить и добавить как один из официальных переводов.
+1
Хочется учебник для тех, кто хорошо знаком с C++ и готов перейти на D. Чтобы без воды вот этой всей.
0
Пока на написание такого труда я не готов. Из уже имеющихся книг могу порекомендовать:
1. D Cookbook — свежее собрание приемов, специфичных для D.
2. The D Programming Language (перевод), написана в 2010, поэтому многие примеры могут без пинка не заработать.
1. D Cookbook — свежее собрание приемов, специфичных для D.
2. The D Programming Language (перевод), написана в 2010, поэтому многие примеры могут без пинка не заработать.
+1
Ну конечно, кто ж еще мог быть автором этой статьи :D
+1
Поздний вопрос. Но вот интересно, если в D мы наследуемся от темплейтового класса, и параметры ему передаем на месте, чтобы обратится к нему (тобишь родителю) надо указывать полное имя специализированого родительского класса, аль нет?
Говоря короче:
В D можно без Base'а обойтись? А то не сколько наследования, сколько юзингов вокруг. Наследование должно упрощать читабельность, а тут огороды городишь.
Говоря короче:
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'а обойтись? А то не сколько наследования, сколько юзингов вокруг. Наследование должно упрощать читабельность, а тут огороды городишь.
0
Если я верно понимаю суть вопроса (уже изрядно подзабыл С++), то можно не указывать. В D было принято решение делать семантический анализ только после инстанциирования и нет грамматической неоднозначности между < > как операторами и как синтаксисом шаблонов.
0
Эхх… если б не его не убиваемый GC (стандартные библиотеки без него не работают) — круто было бы.
Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?
Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?
0
> Эхх… если б не его не убиваемый GC (стандартные библиотеки без него не работают) — круто было бы.
Не совсем так — отдельные модули работают, отдельные нет. В грядущем релизе появятся две очень важные возможности для тех, кто старается избежать GC: флаг компилятора
> Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?
Все проекты по трансляции D в C загнулись, потому что слишком мало кому нужно. Для использования в живом проекте это и не нужно — можно линковать напрямую через
Не совсем так — отдельные модули работают, отдельные нет. В грядущем релизе появятся две очень важные возможности для тех, кто старается избежать GC: флаг компилятора
-vgc
(печатает все места в модуле, которые выделяют память через GC) и новый атрибут @nogc
, гарантирующий, что функция транзитивно не использует GC (ошибка компиляции в противном случае).> Кстати, а D может в C скомпилироваться, чтоб его к живому проекту приаттачить?
Все проекты по трансляции D в C загнулись, потому что слишком мало кому нужно. Для использования в живом проекте это и не нужно — можно линковать напрямую через
extern(C)
. Вот, например, отчёт об интеграции D с существующими библиотеками на C++ в Facebook: www.youtube.com/watch?v=1JZNvKhA3mA +1
> Не совсем так — отдельные модули работают, отдельные нет.
Я ошибаюсь, или все листы/векторы/массивы в обеих «стандартных» библиотеках без GC не живут? А энтож квинтэссенция всего программирования, понимаешь ли…
> и новый атрибут @nogc, гарантирующий, что функция транзитивно не использует GC (ошибка компиляции в противном случае).
А как они в таком случае думают ситуацию с станартной либой разрулить? Она ж ляжет все и полностью (ну почти...).
Я ошибаюсь, или все листы/векторы/массивы в обеих «стандартных» библиотеках без GC не живут? А энтож квинтэссенция всего программирования, понимаешь ли…
> и новый атрибут @nogc, гарантирующий, что функция транзитивно не использует GC (ошибка компиляции в противном случае).
А как они в таком случае думают ситуацию с станартной либой разрулить? Она ж ляжет все и полностью (ну почти...).
0
> все листы/векторы/массивы
Массивы не живут в стандартной библиотеке, они встроены непосредственно в язык (а Phobos вообще беден на контейнеры в ожидании github.com/andralex/phobos/blob/allocator/std/allocator.d). Для встроенных массивов GC _необходим_ только для операции ~= (конкатенация). В целом же массив это просто указатель + длинна, а как выделена память — не критично. Обойти GC не так уж трудно, просто теряются гарантии по безопасности работы с памятью.
> Она ж ляжет все и полностью (ну почти...).
Большая часть std.algorithm, std.range и тому подобных модулей уже работают без аллокаций. Остальные модули понемногу вычищают — это долгий процесс.
Полностью отказаться от GC довольно трудно на нынешнем этапе, но для 99.99% приложений это и не нужно, достаточно держать количество мусора на минимуме.
Массивы не живут в стандартной библиотеке, они встроены непосредственно в язык (а Phobos вообще беден на контейнеры в ожидании github.com/andralex/phobos/blob/allocator/std/allocator.d). Для встроенных массивов GC _необходим_ только для операции ~= (конкатенация). В целом же массив это просто указатель + длинна, а как выделена память — не критично. Обойти GC не так уж трудно, просто теряются гарантии по безопасности работы с памятью.
> Она ж ляжет все и полностью (ну почти...).
Большая часть std.algorithm, std.range и тому подобных модулей уже работают без аллокаций. Остальные модули понемногу вычищают — это долгий процесс.
Полностью отказаться от GC довольно трудно на нынешнем этапе, но для 99.99% приложений это и не нужно, достаточно держать количество мусора на минимуме.
+1
Тоесть они отвязываются от GC? Где это написано?
> достаточно держать количество мусора на минимуме.
Мне, например не понятно, чего оно там с GC крутит (и скорее важны задержки на вызовы GC чем память которая занмается/освобождается). Если написали можно отключить — знач можно, а не как в С++ — можно, но со special rule's ;)
> достаточно держать количество мусора на минимуме.
Мне, например не понятно, чего оно там с GC крутит (и скорее важны задержки на вызовы GC чем память которая занмается/освобождается). Если написали можно отключить — знач можно, а не как в С++ — можно, но со special rule's ;)
0
Да что ж такое:
habrahabr.ru/post/226071/#comment_7787471
habrahabr.ru/post/226071/#comment_7787471
0
> Тоесть они отвязываются от GC? Где это написано?
Не понял вопроса :) Это легальный код использующий массивы без GC:
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.
Не понял вопроса :) Это легальный код использующий массивы без 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.
0
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Учебник по языку программирования D. Часть 1