Комментарии 63
>> Представте себе, что стоит такая задача, написать функции, первая будет применять ко всем элементам массива чисел с плавающей точкой такую формулу: «sin(X) + cos(X)», а вторая для массива целых чисел такую: "( X ^^ 3) + X * 2".
>> И небольшой сразу нюанс, что от релиза к релизу формулы будут меняться.
>> Могу ошибаться, но прямого аналога нет, во всяком случае в популярных, компилируемых языках.
В C# (и вообще .net) это (а) делается из коробки с помощью LINQ-операции select и (б) легко реализуется самостоятельно с помощью generics и делегатов.
>> И небольшой сразу нюанс, что от релиза к релизу формулы будут меняться.
>> Могу ошибаться, но прямого аналога нет, во всяком случае в популярных, компилируемых языках.
В C# (и вообще .net) это (а) делается из коробки с помощью LINQ-операции select и (б) легко реализуется самостоятельно с помощью generics и делегатов.
0
В C# (и вообще .net) это (а) делается из коробки с помощью LINQ-операции select и (б) легко реализуется самостоятельно с помощью generics и делегатов.
Когда я работал с С# такого еще не было. Это происходит в compile time? Приведите пример кстати, сравним элегантность решения.
-1
(пишу по памяти)
new [] {0, 1, 2, 3, 4, 5}.Select(x => Math.Pow(x, 3) + x*2);
new [] {0.0D, 0.5D, 1.0D, 1.5D, 2.0D, 2.5D}.Select(x => Math.Sin(x) + Math.Cos(x));
Ну и да, это строгий compile-time с поддержкой всеми инструментами.
new [] {0, 1, 2, 3, 4, 5}.Select(x => Math.Pow(x, 3) + x*2);
new [] {0.0D, 0.5D, 1.0D, 1.5D, 2.0D, 2.5D}.Select(x => Math.Sin(x) + Math.Cos(x));
Ну и да, это строгий compile-time с поддержкой всеми инструментами.
+1
И тут вспоминаем про haskell…
Весьма элегантно, не правда ли?
map (^2) [0, 1, 2, 3]
map (\a -> sin a + cos a) [0, 1, 2, 3]
Весьма элегантно, не правда ли?
0
Не хочу себя рекламировать (хотя кого я обманываю, хочу конечно :), но статьи про D появляются на хабре уже много лет (вот мой цикл: habrahabr.ru/post/135720/), и на мой взгляд тема вводных статей про фишечки себя уже давно исчерпала.
Гораздо интереснее было бы почитать статьи от гуру про современные best practices и дизайн языка.
Так что, хоть я и рад популяризации языка, статья ничего нового не рассказала.
Гораздо интереснее было бы почитать статьи от гуру про современные best practices и дизайн языка.
Так что, хоть я и рад популяризации языка, статья ничего нового не рассказала.
+2
Неплохие статьи, почему забросили это дело?
Цели рассказать что-то новое хорошо знакомому с языком D разработчику и не ставилось. В интро конкретно написано, что статья направлена на популяризацию языка.
статья ничего нового не рассказала
Цели рассказать что-то новое хорошо знакомому с языком D разработчику и не ставилось. В интро конкретно написано, что статья направлена на популяризацию языка.
+3
почему забросили это дело?
Я не забросил, я подошел к логическому завершению. Рассказывать дальше — уже не вводный цикл, а подробное описание. К сожалению, я не чувствую себя настолько большим спецом по D, чтобы учить людей паттернам, стилям и идеям языка.
статья направлена на популяризацию языка.
Я имел ввиду именно то, что уже интро-статей было полно, и не только мой цикл, были и еще.
0
Ну пока язык не станет популярен хотя бы на уровне, Ruby, популяризирующие статьи не помешают. Цель то, не достигнута.
+1
После долгих лет слежения за языком я все больше убеждаюсь в необходимости централизованной популяризации. Как у Rust, Java, C#, Go. Должна быть группа людей, очень яростно спамящая фултайм во все щели про свой язык. D-сообщество такого не делает, а в вин без этого я не верю.
0
От D немного отпугивает личность Александреску, избравшего этот язык в качестве полигона для обкатки своих безумных фантазий.
+1
А меня наоборот он и привлек =)
Его фантазии кажутся безумными только когда они выражены на C++, который не предназначен. А в D они как раз хорошо вписаны, мне очень понравилось.
Его фантазии кажутся безумными только когда они выражены на C++, который не предназначен. А в D они как раз хорошо вписаны, мне очень понравилось.
+1
avoid success at all costs — это девиз Haskell популярность которого растет))
0
Мне вот в этой связи интересны ответы на 2 вопроса:
- Какие существуют крупные проекты, написанные преимущественно на D, которые можно применить при развертывании реальных приложений (веб-сервера, сервера очередей, MTA и т.п.)?
- В связи с растущей популярностью Go и Rust — как языков для системного программирования на замену C, является ли D языком из той же самой ниши или же это что-то более высокоуровневое ближе к Java \ C#? Если является, то в чем могут заключаться его конкурентные преимущества по сравнению с Rust \ Go?
+4
В каждой статье по Rust его сравнивают с Go. А теперь еще и в статьях про D.
Нельзя эти языки сравнивать, у них совершенно разные ниши. Это как сравнивать си и эрланг.
А D еще не определился с нишей. Официальная позиция — хорош для всего, но он совершенно точно хуже, чем раст для системного программирования и совершенно точно хуже, чем го для асинхронных серверов. Я бы сказал, что D — это улучшенная нативная Java.
Нельзя эти языки сравнивать, у них совершенно разные ниши. Это как сравнивать си и эрланг.
А D еще не определился с нишей. Официальная позиция — хорош для всего, но он совершенно точно хуже, чем раст для системного программирования и совершенно точно хуже, чем го для асинхронных серверов. Я бы сказал, что D — это улучшенная нативная Java.
+3
и совершенно точно хуже, чем го для асинхронных серверов.
Почему?
0
Я писал на обоих и такое мое впечатление.
Обьективно потому, что у Go все, что нужно, встроено в рантайм, а в D нужно использовать фреймворк vibe.d, который не встроен в язык, и поэтому doesn't feel native, по сравнению с Go. Плюс, в Go весь сторонний код оформлен, как библиотеки, а не как фреймворк, а фреймворки я терпеть не могу, мне кажется, что меня загоняют в рамки, и это противно :)
Плюс, go get, ах, как я его обожаю! dub для D появился не так давно и он несколько сложнее в использовании и слегка с багами (как и vibe.d сам, да и как и D тоже).
Обьективно потому, что у Go все, что нужно, встроено в рантайм, а в D нужно использовать фреймворк vibe.d, который не встроен в язык, и поэтому doesn't feel native, по сравнению с Go. Плюс, в Go весь сторонний код оформлен, как библиотеки, а не как фреймворк, а фреймворки я терпеть не могу, мне кажется, что меня загоняют в рамки, и это противно :)
Плюс, go get, ах, как я его обожаю! dub для D появился не так давно и он несколько сложнее в использовании и слегка с багами (как и vibe.d сам, да и как и D тоже).
+2
хз, я тут рискнул нечто подобное (асинхронные сетевые сервисы) пилить, правда это скорее event-driven движок. А асинхронные сетевые сервисы он дает в комплекте с генераторами питона. И в принципе уже кое-что работает, и без vibe.d, что характерно. Хотя и не вижу препятствий с помощью фиберов похожее полностью на D сделать. Если есть акк на битбакете дал бы доступ на репу, почитать мнение.
0
НЛО прилетело и опубликовало эту надпись здесь
А в чем разница между двумя синтаксисами?
int delegate(int x) d = ...
int function(int x) f = ...
+1
Функция — это просто функция: sizeof(function) == sizeof(void*). Делегат — это функция + контекст. Фактически, замыкание.
+1
В первом случае определение типа делегата, во втором определение типа функции, похожее на то как определяется ссылка ну функцию в C.
Например: int function(int x) func;
Аналог: typedef inf(*func)(int);
Например: int function(int x) func;
Аналог: typedef inf(*func)(int);
-2
Идея миксинов очень правильная, но реализация (строки в кавычках) мне концептуально не нравится — так как теряется возможность подсветки синтаксиса в IDE (нет возможности отличить обычную строку от фрагмента кода). Лучше как в Nemerle — в специальных скобках для квазицитирования.
Хотя в данном случае и квазицитирования не надо, достаточно разрешить передачу в шаблоны блоков кода в фигурных скобках. Такое кстати можно и в С++ ввести с минимальными изменениями в синтаксисе.
Хотя в данном случае и квазицитирования не надо, достаточно разрешить передачу в шаблоны блоков кода в фигурных скобках. Такое кстати можно и в С++ ввести с минимальными изменениями в синтаксисе.
+1
Считайте, что mixin(" и ") — специальные скобки.
Это не правда. У миксинов не только то применение, что указано в статье. Оно, кстати, глупое и уже неофициально deprecated — никто так не пишет. Теперь для целей, который в статье используют именно то, что вы сказали — лямбды.
А миксины совсем для другого, почитайте мою статью: habrahabr.ru/post/135720/.
достаточно разрешить передачу в шаблоны блоков кода в фигурных скобках.
Это не правда. У миксинов не только то применение, что указано в статье. Оно, кстати, глупое и уже неофициально deprecated — никто так не пишет. Теперь для целей, который в статье используют именно то, что вы сказали — лямбды.
А миксины совсем для другого, почитайте мою статью: habrahabr.ru/post/135720/.
0
Оно, кстати, глупое и уже неофициально deprecated — никто так не пишет
Читал что хотят заменить чем то более продвинутым, но пока не вижу, как собственно и глупости такого подхода.
0
Уже года два с половиной как передают лямбды вместо строк. А строки оставили для обратной совместимости.
А глупость описал оригинальный комментарий: никакой подсветки и поддержки тулзами.
map!(x => x^^2)([1,2,3]);
А глупость описал оригинальный комментарий: никакой подсветки и поддержки тулзами.
0
Да это выглядит более правильно, но теряется фишка миксинов — вычисление подставляемой строки во время компиляции. Хотя не приходит на ум где это реально может пригодиться.
0
Я кстати имел в виду кстати не лямбды, а именно блоки кода, включаемые на этапе компиляции. Отличие в том, что лямбды вызываются (то есть генерируется код вызова функции), а при прямой подстановке никаких вызовов не происходит. Я занимался embedded программированием, там в условиях очень ограниченных ресурсов приходилось писать такие вещи с помощью обычных макросов.
Например, в шаблоны С++ можно передавать целые числа; они передаются не через стек в рантайме, а напрямую встраиваются в код во время компиляции. Я считаю, что совершенно аналогично можно сделать передачу произвольных сущностей времени компиляции, в частности блоков кода
Да, там будут проблемы с «гигиеничностью» (смешиванием имен из блока B и имен из самой функции foo), но все вполне решаемо.
Например, в шаблоны С++ можно передавать целые числа; они передаются не через стек в рантайме, а напрямую встраиваются в код во время компиляции. Я считаю, что совершенно аналогично можно сделать передачу произвольных сущностей времени компиляции, в частности блоков кода
template<block B>
void foo()
{
// do something
B; // это не вызов, а именно подстановка кода напрямую
// do something
}
// ...
foo<{ bar1(); }>();
Да, там будут проблемы с «гигиеничностью» (смешиванием имен из блока B и имен из самой функции foo), но все вполне решаемо.
0
Для этого есть литералы токенов q{}. Всё что в кавычках станет стокой. Идеально для кода в миксинах. dlang.org/lex.html Token Strings
0
Какие существуют большие проекты (не библиотеки) на D и кто его использует, кроме Facebook и Digital Mars?
+ Какие есть учебные курсы, основной язык которых — D?
+ Какие есть учебные курсы, основной язык которых — D?
0
Пока не густо, здесь небольшой список wiki.dlang.org/Current_D_Use
Курсов похоже нет, как и альтернативе книге Александреску.
Курсов похоже нет, как и альтернативе книге Александреску.
0
Да ладно. Есть как минимум две платные книги по D и одна бесплатная.
Платные:
Andrei Alexandrescu — The D Programming Language (в том числе перевод на русский)
Adam D. Ruppe — D Cookbook
Бесплатная:
Ali Çehreli — Programming in D
Платные:
Andrei Alexandrescu — The D Programming Language (в том числе перевод на русский)
Adam D. Ruppe — D Cookbook
Бесплатная:
Ali Çehreli — Programming in D
0
НЛО прилетело и опубликовало эту надпись здесь
Я так понял речь идет о последнем разделе. В этом языке функцию тоже можно передавать не только в map, но и в любую другую, в первых двух разделах это как раз и использовано. В третьем же просто хотелось привести пример с одним из вариантов использования mixin. Вариант с передачей в map лямбды есть в комменте habrahabr.ru/post/246623/#comment_8194283.
1) Функция map в примере может быть использована для разных типов, в примере показан int и double, поэтому применен темплейт и тип указан, что бы компилятор знал для каких типов построить версии темплейтированной функции в данном случае для int и double.
2) Да странный, одна из особенностей, и наверно будет заменена на что-то более однозначное.
3) Это и есть миксин :) Компилятор просто вместо строки mixin(Op); подставит то что было передано как Op. То есть результирующая строка, которая пойдет на компиляцию для Op = «sin(X) + cos(X)» будет выглядеть например так:
Какие в этом проблемы? Да не вижу особых, если есть понимание как это работает.
map в примере чисто моя отсебятина лишь для илюстрации статьи. Реализация настоящего map и много чего из этой оперы выполнена господином Александреску на самом высоком уровне :) dlang.org/phobos/std_algorithm.html#map
1) Функция map в примере может быть использована для разных типов, в примере показан int и double, поэтому применен темплейт и тип указан, что бы компилятор знал для каких типов построить версии темплейтированной функции в данном случае для int и double.
2) Да странный, одна из особенностей, и наверно будет заменена на что-то более однозначное.
3) Это и есть миксин :) Компилятор просто вместо строки mixin(Op); подставит то что было передано как Op. То есть результирующая строка, которая пойдет на компиляцию для Op = «sin(X) + cos(X)» будет выглядеть например так:
foreach(X; in_array) {
X = sin(X) + cos(X);
out_array ~= X;
}
Какие в этом проблемы? Да не вижу особых, если есть понимание как это работает.
Да и map тут какой-то не очень обобщённый — работает только для массивов.
map в примере чисто моя отсебятина лишь для илюстрации статьи. Реализация настоящего map и много чего из этой оперы выполнена господином Александреску на самом высоком уровне :) dlang.org/phobos/std_algorithm.html#map
0
А есть ли в D аналог rvalue-ссылок как в C++11? Актуально для случая, когда внутри map вызываются вложенные функции f(g(x)), а сам x имеет составной тип. Хотелось бы для g(x) не создавать временный объект.
0
Ссылки есть, есть и спецификаторы параметров функции, определяющие, что параметр rvalue. Приведите пример, попробуем его переписать в синтаксисе D.
0
Вот пример где g переводит скаляр в вектор, а f — вектор в скаляр.
double f(double [] x) {
return x[0] + x[1];
}
double [] g(double x) {
return [x, x];
}
int main()
{
double y = f(g(1));
}
0
Это вы на С++ или на D написали? :) Если на C++, то на D этот же код вернет тот же результат 2, что и на С++. И я не вижу в нем r-value передаваемое в функцию. Может мы друг друга не правильно поняли, я ожидал нечто такое, чему эквивалент на D был бы такой:
void sqr(ref int x)
{
x = x * x;
}
void main()
{
int x = 2;
sqr(x);
assert (x == 4);
}
0
Я хотел, чтобы D удивил и сам развернул вычисление y=f(g(1)) в y = 1+1 во время компиляции.
0
Темплейтом это можно сделать полагаю, но зачем, это будет не гибко?
0
Сформулирую вопрос по другому: если есть два массива — X, Y, то можно ли отдельно определить свою функцию f так, чтобы затем в коде писать Y = f(X) (без foreach c вызовом Y[i] = f(X[i]). Хочется максимально приблизиться к математической нотации.
0
Оно?
import std.algorithm;
auto Sqr(int[] a)
{
return map!(x => x * x)(a);
}
void main()
{
int[] X = [0, 1, 2, 3, 4];
auto Y = Sqr(X); // ... так, чтобы затем в коде писать Y = f(X)
assert(equal(Y, [0, 1, 4, 9, 16]));
}
+1
Принцип «лишь бы не как у всех», разработчиков D не заботит и это хорошо.
int delegate(int X) power2 = delegate(int X) { return X * X; };
Как раз и получилось «лишь бы не как у всех». Большая избыточность определения.
Сравните со Scala:
val power2 = (x: Int) => x*x
0
А если так?
auto power2 = delegate(int X) { return X * X; };
0
Большая избыточность определения.
Конечно, если сравнивать полную форму запись с короткой.
Сравнивайте короткую с короткой, пример вам привели.
0
Оффтоп, но надеюсь, что кому-нибудь будет интересно.
Я разрабатываю GUI библиотеку на D — DlangUI
Демо, нужны GIT, DUB и DMD:
Я разрабатываю GUI библиотеку на D — DlangUI
- Кроссплатформенная, с поддержкой ускорения отрисовки с помощью OpenGL.
- API напоминает Android UI.
- Не враппер — написано на D, поэтому легко расширять, добавлять новые виджеты.
- Внешний вид можно значительно изменять с помощью тем (похожи на темы Android).
- Unicode и поддержка нескольких языков интерфейса.
- Адаптация интерфейса под разные размеры и разрешения экрана.
Демо, нужны GIT, DUB и DMD:
# Скачать исходники с GitHub
git clone https://github.com/buggins/dlangui.git
cd dlangui
# example 1 - демо, в котором используется большинство виджетов
dub run dlangui:example1 --build=release
# tetris - демо, игра TETRIS
dub run dlangui:tetris --build=release
+2
С тех пор как я с товарищами писали статьи правда ничего не изменилось? Вроде это всё уже было лет пять назад. habrahabr.ru/post/75451/
> Могу ошибаться, но прямого аналога нет, во всяком случае в популярных, компилируемых языках.
В копилку Common Lisp. Не популярный, да. Компилирется в некоторых реализациях, например самой популярной — SBCL. Вообще map уже есть, но у вас он шаблонный, а не функциональный (с лямбдой), так что вот тоже шаблонный:
(defmacro tmap (op array)
`(loop for x in ,array collect ,op)
(defun main ()
(format t "#1 ~A~%" (tmap (* x 3) '(0 1 2 3 4 5)))
(format t "#2 ~A~%" (tmap (expt x 3) '(0 1 2 3 4 5)))
(format t "#3 ~A~%" (tmap (* x 3) '(0.0 0.5 1.0 1.5 2.0 2.5)))
(format t "#4 ~A~%" (tmap (expt x 3) '(0.0 0.5 1.0 1.5 2.0 2.5))))
В SBCL есть кое какой решатель типов. Если он сообразит какого типа списки (на буквальные не реагирует, должно быть объявление типа хоть где-нибудь), то в скомпилированном коде окажутся вызовы машинных команд для * и expt (где есть), если не сообразит — то вызовы функций для произвольных типов.
Конечно, D старается следовать принципу zero overhead, но пока это у C++ получается всё же лучше. Компромисс.: ) Помню, в своё время он мне и нравился как золотая середина между перформансом и удобством, потом обнаружил себя либо за задачами где перформанс не важен, тогда годится Common Lisp (с перформансом всё равно на уровне компилируемых), либо за энтерпрайзнутыми серверными кластерами, где лучше Erlang.
> Могу ошибаться, но прямого аналога нет, во всяком случае в популярных, компилируемых языках.
В копилку Common Lisp. Не популярный, да. Компилирется в некоторых реализациях, например самой популярной — SBCL. Вообще map уже есть, но у вас он шаблонный, а не функциональный (с лямбдой), так что вот тоже шаблонный:
(defmacro tmap (op array)
`(loop for x in ,array collect ,op)
(defun main ()
(format t "#1 ~A~%" (tmap (* x 3) '(0 1 2 3 4 5)))
(format t "#2 ~A~%" (tmap (expt x 3) '(0 1 2 3 4 5)))
(format t "#3 ~A~%" (tmap (* x 3) '(0.0 0.5 1.0 1.5 2.0 2.5)))
(format t "#4 ~A~%" (tmap (expt x 3) '(0.0 0.5 1.0 1.5 2.0 2.5))))
В SBCL есть кое какой решатель типов. Если он сообразит какого типа списки (на буквальные не реагирует, должно быть объявление типа хоть где-нибудь), то в скомпилированном коде окажутся вызовы машинных команд для * и expt (где есть), если не сообразит — то вызовы функций для произвольных типов.
Конечно, D старается следовать принципу zero overhead, но пока это у C++ получается всё же лучше. Компромисс.: ) Помню, в своё время он мне и нравился как золотая середина между перформансом и удобством, потом обнаружил себя либо за задачами где перформанс не важен, тогда годится Common Lisp (с перформансом всё равно на уровне компилируемых), либо за энтерпрайзнутыми серверными кластерами, где лучше Erlang.
0
Lisp это Lisp. На нем можно все, но для интерпрайса не годится. Весь интерпрайс закончится с уходом ведущих программистов :) Фактический каждый Липс программист уровнем выше среднего пишет на своем собственном языке, не согласны? :) Erlang — да, но специфика узкая.
Ну если у вас инфа более двух годичной давности, советую опять посмотреть на D, ситуация на мой взгляд изменилась в лучшую для D сторону.
D старается следовать принципу zero overhead, но пока это у C++ получается всё же лучше
Ну если у вас инфа более двух годичной давности, советую опять посмотреть на D, ситуация на мой взгляд изменилась в лучшую для D сторону.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Публикации
Изменить настройки темы
Фишки языка D