Комментарии 31
Julia - очень экспериментальный язык с интересной концепцией. Описанные проблемы выглядят как раз как детские проблемы любой технологии, просто их больше из-за нового подхода к семантике кода.
Пробовал экспериментировать с этим языком и меня смутили более фундаментальные штуки. Например, логика работы с памятью (где выделять память: на стеке или куче) зависит от описания типов. Из-за этого изменения в структуре данных влияют на выделение памяти для всех структур, которые прямо или косвенно её используют. Как следствие, сложно предсказать (по крайней мере новичку) как изменение повлияет на производительность.
А так, Dynamic typing + Multiple dispatch + JIT рулит. Если забыть о семантике памяти, то писать код приятнее, чем на других ЯП.
Если интересно, у меня в блоге подробный рассказ о пробном заходе на Julia: https://tiendil.org/julia-experience/
Нет, это к сожалению не "детские" проблемы, а как раз проблемы, которые возникают при масштабировании. Это не отменяет того, что джулия весьма хороша в области прототипирования и изолированых научных задач. Но для больших многоцелевых фреймворков она вряд ли будет пригодна.
Например, в то время, когда экосистема машинного обучения Julia была ещё более незрелой, один из создателей языка с энтузиазмом рассказывал об использовании Julia в продакшене для беспилотных автомобилей
"Детские проблемы" в беспилотных автомобилях на дорогах общего пользования? Не, спасибо, а можно ТАМ что-то без детских проблем?
От части согласен, но дело наверное в том что Julia это что-то вроде попытки совместить язык программирования общего назначения и математический пакет наподобие Matlab. Потому возможно люди занимающиеся научными вычислениями его и полюбили.
Я пишу небольшие программы программы раз 3-5 лет. Каков порог вхождения в D ? Как и в Си? Тогда - мимо кассы. Julia, как и Бейсик (классический) имеет низкий порог вхождения. В первый же день можешь начать писать программу. В этом их плюс. А в Си мне не удалось. За три года почти все забудешь и заново по примерам будешь восстанавливать. Наука, однако. Писал в машинных кодах, Бейсике, Обероне, а теперь вот на Julia. Просто удобно в в ней писать программы. Для таких как, я, важна не красота кода и скорость исполнения программы, а результат.
Можете сами попробовать: https://tour.dlang.org/tour/ru/welcome/welcome-to-d
Ну и D - не единственная альтернатива. Nim, например, ещё есть: https://nim-lang.org/
Не нашёл там ужасного кода, куда смотреть?
https://github.com/dataPulverizer/KernelMatrixBenchmark
135 LOC для Julia и куча невнятного изобретения велосипедов на D
https://github.com/dataPulverizer/KernelMatrixBenchmark/blob/master/julia/KernelMatrix.jl 3.22 KB
https://github.com/dataPulverizer/KernelMatrixBenchmark/blob/master/d/kernel.d 3.94 KB
Где там "куча невнятных велосипедов"?
arrays.d +426 LOC
итого на D 229+426 LOC vs 135 Джулии
https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/symmetric.jl + 30 KB
https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/symmetriceigen.jl + 10 KB
Вы сравниваете тёплое с мягким.
arrays.d +426 LOCЭто же с учётом кучи скобочек на отдельных строках. Если убрать строки, в которых только пробелы и открывающая скобка — останется 357 строк.
Я это к чему: даже если у вас будет 2 абсолютно одинаковых по структуре куска кода (например набор базовых арифметических операций типа
fn sum(a, b) return a+b
, то D проиграет по LOC из-за одного форматирования.Поэтому LOC нет смысла сравнивать на голом месте, особенно для настолько разных языков (отступы vs скобочки), ну или хотя бы надо учитывать вот такие нечестные различия.
P.S. минифицированные JS-файлы имеют 1 LOC.
Есть же нормальные языки типа D, которые <...> и с мощным тайпчеком как Rust.
Извините, но сравнивать Rust с тайпчеком до мономорфизации и D с тайпчеком после инстанцирования шаблонов просто смешно. Rust уже за счёт этого на голову выше.
Полистал описание D, вполне нормальный язык, но не понятна его крайне низкая популярность в целом.. кмк, явно предпочтительнее Go, Rust, C++ и не менее мощен и выразителен. Или я не верно истолковал его описание? Язык, кмк, вполне достоин более широкого применения.
Потому что отрасль ещё не научилась в завтипы. Посмотреть сколько времени программисты учились в простые замыкания и first-class функции, до промышленных завтипов нам как до луны.
Даже без хардкорного кода бывают ещё те задачки. Например, поиск минимума в четырёхмерном овраге в резкими стенками и почти плоским дном. Для усложнения задачи: конец 80х и ДВК. Пока нашёл работающий поиск минимума, причём каждый надо было написать самому (алгоритмы были приведены в книге). Для науки, часто важен результат расчёта, а не скорость его получения. И чтобы совсем стало тоскливо - с использованием комплексных чисел. Это сейчас просто.
Вот кстати с завтипами в Julia все лучше чем в большинстве языков. Умножение в кольце вычетов, к примеру, выглядит так:
struct Quot{T, n}
v::T
end
function (*)(a::Quot{T,n}, b::Quot{T,n}) where {T,n}
Quot{T,n}(mod(a.v * b.v, n))
end
Тайпчекер сам проверит что вы ему скормили вычеты одного и того же типа по одному и тому же модулю, либо выкинет понятное исключение. Увы, в рантайме, это же скриптовый язык, зато никаких ручных проверок!
Но вот отсутствие интерфейсов - действительно беда. В коде выше прямо так и напрашивается указать трейты для T, а нельзя.
Где вы тут завтипы-то увидели? Это обычная типизация. На том же D этот код выглядит так:
struct Quot( alias Val, Val mod ) {
Val val;
alias Self = Quot!(Val,mod);
auto opBinary( string op )( Self other ) {
return Self( mixin( q{this.val} ~ op ~ q{other.val} ) % mod );
}
}
void main() {
import std.stdio: writeln;
auto left = 3.Quot!(uint,10);
auto right = 5.Quot!(uint,10);
writeln( left + right*left );
}
И типы чекаются компилятором.
О, интересно. А если я вместо uint воткну какой-нибудь многочлен, или bigint, оно это прожует? На Расте так нельзя. Пойти что-ли попробовать этот ваш D.
Где вы тут завтипы-то увидели?
Ну как же, это П-тип, оно становится обычным типом только после подставления переменной n. Разве нет?
Любой тип прожуёт, для которого определены соответствующие операции.
Так эта "переменная" не меняется в рантайме.
Что-то я тупанул, можно же ещё проще:
struct Quot( alias mod ) {
typeof(mod) val;
auto opBinary( string op )( Quot!mod other ) {
return Quot!mod( mixin( q{this.val} ~ op ~ q{other.val} ) % mod );
}
}
void main() {
import std.stdio: writeln;
auto left = 3.Quot!10;
auto right = 5.Quot!10;
writeln( left + right*left );
}
Почему я больше не рекомендую Julia