Здравствуйте, Cyberax, Вы писали:
C>В Java по факту делается escape analysis, так что значительная часть объектов располагается на стеке. Автоматически. И это работает.
Это всё равно не сравнимо с прямым указанием. Не говоря уже о лишнем расходе памяти на заголовки.
C>Я не очень понял что они измеряли, но точно не память.
Как раз память, но суммарную. Т.е. в случае массивов объектов там идёт двойной расход (на сам массив и отдельно на объекты). И всё это с лишними заголовками...
Я помнится видел разные выкладки на эту тему. Типа таких http://habrahabr.ru/post/134102/ — для C++'ка это всё конечно же дико выглядит. Ну а D в этом смысле ближе к C++...
C>Каких конкретно фич у него нет?
Я сейчас не готов выдать подробный анализ по Rust'у (в отличие от C/C++/D и т.д), т.к. давно не смотрел его и собственно уже даже забыл подробности. Но я точно помню, что когда первый раз глянул на него, то у меня было абсолютно ясное ощущение, что я вижу "C без ужасов". Точно так же как при взгляде на D возникает ощущение "C++ без ужасов".
C>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка.
Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП. Уже одно это является полным приговором. Но кроме этого есть ещё и отдельные фичи: исключения, пространства имён, строгая типизация. Ну и в дополнение ко всему этому из плюсов доступны как все C библиотеки, так и с++ библиотеки (а там же есть сильнейшие вещи, начиная от стандартной STL и заканчивая Boost'ом), а в обратную сторону совместимости обычно нет.
C>Я не очень понял где там два остальных метода.
Здравствуйте, Cyberax, Вы писали:
C>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень.
Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. Причём именно этот нюанс определил направление развитие современного C++, который уже абсолютно не похож на "C с классами". Правда синтаксис подобного метапрограммирования конечно места ужасен и как раз это во многом исправлено в языке D, сохранив при этом (и даже увеличив) всю мощь шаблонов.
DE>>Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять. C>А можно его увидеть?
Например вот http://www.boost.org/doc/libs/1_55_0/libs/format/doc/format.html. И кроме этого есть ещё варианты.
C>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки.
Вообще то обычно ошибки в шаблонах выводятся как раз в первой же строке сообщения об ошибке. Просто обычно после этого ещё может следовать несколько страниц всякого мусора. )))
Да, и кстати аналог концептов в шаблонах C++ давным давно есть (см. например enable_if), просто т.к. оно не обязательно к использованию, то и далеко не все тратят время на добавление подобного (тем более что на быстродействие или надёжность кода это никак не влияет).
C>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++?
Здравствуйте, alex_public, Вы писали:
C>>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень. _>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования.
Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
DE>>>Типобезопасный принтф в С++ тоже возможен, не говоря уже о том, что компиляторы уже научились форматную строку и обычного принтфа проверять. C>>А можно его увидеть? _>Например вот http://www.boost.org/doc/libs/1_55_0/libs/format/doc/format.html. И кроме этого есть ещё варианты.
Небезопасен.
cout << format("Hello, are you feeling lucky, punk? %d\n") % "Nope";
cyberax@cybmac:~/some$ rustc test.rs
test.rs:3:38: 3:45 error: failed to find an implementation of trait std::fmt::Signed for &'static str
test.rs:3 println!("Hello, world! {:d}\n", "Hello");
^~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
test.rs:3:5: 3:47 note: expansion site
Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е.
C>>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки. _>Вообще то обычно ошибки в шаблонах выводятся как раз в первой же строке сообщения об ошибке. Просто обычно после этого ещё может следовать несколько страниц всякого мусора. )))
Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода.
_>Да, и кстати аналог концептов в шаблонах C++ давным давно есть (см. например enable_if), просто т.к. оно не обязательно к использованию, то и далеко не все тратят время на добавление подобного (тем более что на быстродействие или надёжность кода это никак не влияет).
Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно.
C>>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++? _>http://www.boost.org/doc/libs/1_55_0/doc/html/xpressive.html
Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения.
cyberax@cybmac:~/some$ time clang++ -O2 -I /opt/local/include/ regtest.cpp
real 0m2.584s
user 0m2.334s
sys 0m0.210s
cyberax@cybmac:~/some$ time ./a.out
real 0m9.922s
user 0m9.873s
sys 0m0.017s
На Расте:
#![feature(phase)]
#[phase(syntax)]
extern crate regex_macros;
extern crate regex;
static tst: &'static str = " 123-451";
fn main() {
let re = regex!(r"\s+\d+--\d+\s*");
for r in range(0,10000000) {
re.is_match(tst);
}
}
cyberax@cybmac:~/some$ time rustc -O test.rs
test.rs:10:9: 10:10 warning: unused variable: `r`, #[warn(unused_variable)] on by default
test.rs:10 for r in range(0,10000000) {
^
real 0m0.118s
user 0m0.071s
sys 0m0.027s
cyberax@cybmac:~/some$ time ./test
real 0m4.459s
user 0m4.436s
sys 0m0.011s
Итак, имеем — регэкспы на Rust работают быстрее С++, при том, что компиляция примерно в 20 раз быстрее. И не нужно учить другой синтаксис.
Sapienti sat!
Re[33]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>В Java по факту делается escape analysis, так что значительная часть объектов располагается на стеке. Автоматически. И это работает. _>Это всё равно не сравнимо с прямым указанием. Не говоря уже о лишнем расходе памяти на заголовки.
Для escape'нутых объектов заголовок становится меньше, там остаётся только hashcode и слово для флагов и монитора.
C>>Я не очень понял что они измеряли, но точно не память. _>Как раз память, но суммарную. Т.е. в случае массивов объектов там идёт двойной расход (на сам массив и отдельно на объекты). И всё это с лишними заголовками...
В D точно так же.
C>>Я серьёзно. Единственная реальная отсутствующая фича — это исключения. Всё остальное есть, даже RAII в виде расширений языка. _>Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП.
Вообще-то, там всё есть, кроме нормального метапрограммирования.
C>>Я не очень понял где там два остальных метода. _>1. immutable int[] i=[1, 2, 3]; _>2. int[] m=[1, 2, 3]; immutable int[] i=m.idup; _>3. int[] m=[1, 2, 3]; immutable int[] i= cast(immutable)m; _>Первые два метода очевидно безопасные по построению. А за отсутствие ошибок в 3-ем случае отвечает программист.
Ну то есть, вариантов нет — только небезопасный код. О чём я и говорил.
Sapienti sat!
Re[38]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
C>Небезопасен. C>
C>cout << format("Hello, are you feeling lucky, punk? %d\n") % "Nope";
C>
C>Выносите.
Ну так здесь же подразумевается использовать в виде cout << format("Hello, are you feeling lucky, punk? %1\n") % "Nope"; Оно в таком стиле и работает собственно (выводит всё корректно, в соответствие с типом).
Кстати, в языке D встроенная writef работает аналогично (на шаблонах), только там всё намного удобнее.
C>Для сравнения: C>... C>Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е.
Ну так а если строка форматирования определяется в рантайме (что чаще всего и происходит, если в программу встроена поддержка многих языков)?
C>Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода.
В глубине кода относительно определения шаблона, но не "на пятой странице листинга ошибки".
C>Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно.
Причём тут концепты и printf, если проверка соответствия строки форматирования входным типам происходит в рантайме?
C>Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения.
А что подразумевается под предкомпиляцией тогда? )
C>real 0m9.922s
C>user 0m9.873s
C>sys 0m0.017s
C>real 0m4.459s
C>user 0m4.436s
C>sys 0m0.011s
О, вот это интересно. Любопытно глянуть за генерируемый код, чтобы понять за счёт чего такая разница.
Re[34]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>В D точно так же.
Ещё раз повторяю:
1. Единственный оверхед в D относительно C++ может возникать от использования GC (в отличие от Java).
2. При этом использование GC в коде на D не обязательно, хотя и упрощает код для многих случаев.
_>>Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП. C>Вообще-то, там всё есть, кроме нормального метапрограммирования.
В таком смысле всё есть и в ассемблере.
Re[39]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности.
_>Ну так здесь же подразумевается использовать в виде cout << format("Hello, are you feeling lucky, punk? %1\n") % "Nope"; Оно в таком стиле и работает собственно (выводит всё корректно, в соответствие с типом).
Не подразумевается. Так как может быть, например, и "%02d".
Но даже если и так:
cout << format("Hello, are you feeling %2, punk? %1\n") % "Nope";
Упс.
_>Причём это работает даже в древнем стандарте языка. Ну а если мы возьмём современный C++, то там вообще всё просто: http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf
Ну так где безопасный printf?
C>>Ещё раз замечу, что для println! никакой магии компилятора не использовалось. Это простой код на Rust'е. _>Ну так а если строка форматирования определяется в рантайме (что чаще всего и происходит, если в программу встроена поддержка многих языков)?
Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой.
C>>Вот уж не надо. Ошибки выводятся при инстанцировании шаблона, где-то в глубине кода. _>В глубине кода относительно определения шаблона, но не "на пятой странице листинга ошибки".
Ну вот как будто я не знаю. Пишу какой-нибудь: "std::vector<thread> blah(thread(...))", и он падает внутри кода вектора из-за того, что у std::thread нет конструктора копирования, а перемещение по каким-то причинам не сработало.
C>>Можно для примера повторить на С++ сообщение об ошибке в примере с println? Чтобы было так же понятно. _>Причём тут концепты и printf, если проверка соответствия строки форматирования входным типам происходит в рантайме?
А в Rust оно может быть в compile-time. Хочу такое же в С++.
C>>Мимо. Там нет предкомпиляции. За счёт ET делается только построение дерева выражения. _>А что подразумевается под предкомпиляцией тогда? )
Создание КА.
_>О, вот это интересно. Любопытно глянуть за генерируемый код, чтобы понять за счёт чего такая разница.
Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения. Т.е. оно превращается в:
...
#[allow(unused_variable)]
#[inline]
fn step(&self, groups: &mut Captures, nlist: &mut Threads,
caps: &mut Captures, pc: uint) -> StepState {
match pc {
0u => { },
1u => {
if self.chars.prev.is_some() {
let c = self.chars.prev.unwrap();
let found =
match c {
'\t' ..'\n' => true,
'\x0c' ..'\r' => true,
' ' ..' ' => true,
'\xa0' ..'\xa0' => true,
'\u1680' ..'\u1680' => true,
'\u2000' ..'\u200a' => true,
'\u2028' ..'\u2029' => true,
'\u202f' ..'\u202f' => true,
'\u205f' ..'\u205f' => true,
'\u3000' ..'\u3000' => true,
_ => false
};
if found { self.add(nlist, 2u, caps); }
}
},
2u => { },
3u => {
if self.chars.prev.is_some() {
let c = self.chars.prev.unwrap();
let found =
match c {
'0' ..'9' => true,
'\u0660' ..'\u0669' => true,
'\u06f0' ..'\u06f9' => true,
'\u07c0' ..'\u07c9' => true,
:
...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Cyberax, Вы писали:
C>>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
_>Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )
В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать.
Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь.
constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.
Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.
Макросы в Rust/Nemerle/Scala и т.п. имеют всю информацию о типах и могут сгенерировать наиболее оптимальный код.
Ну и читабельность намного выше, т.к. код макросов не более чем вызов API компилятора, что можно сравнить с вызовом функций библиотеки.
Здравствуйте, Cyberax, Вы писали:
C>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень.
Нужны для большей гибкости. В расте ведь необходимо указывать все необходимые "трейты", так? Тут сразу шарп вспоминается, где уже хз сколько времени нет арифметических операций для генериков. В С++ оно же просто работает, если для типа нужные операции определены, независимо от того реализует ли он указанные трейты/"интерфейсы".
C>А можно его увидеть?
Да хотя бы типа такого.
C>1) Пример с факториалом — в Расте делается с помощью макроса. Намного прямее, чем в С++.
Ага, читаем:
They exist in a separate, global namespace.
Exporting macros feels like a hack.
Importing macros feels like a hack.
Насчёт "выглядит как хак" ничего не скажу, то невозможность в неймспейс засунуть — уже нефига не "намного прямее".
C>2) Генерики в Расте используют аналог концептов, которые в С++ так и ниасилили. Из-за этого, в частности, ошибки выводятся в месте инстанцирования генерика, а не "во глубине сибирских руд" на пятой странице листинга ошибки.
Ну дык, я и говорю — проблема только с ошибками. А концепты пытаются осилить — прогресс, вроде, есть. Разумеется, концепты — это удобно и хорошо. Но зачем их делать обязательными?
C>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++?
Возможно, на constexpr что-то и можно нагородить. Но что это доказывает? Я где-то заявлял, что в С++ вычисления на этапе компиляции удобнее/лучше?
C>Ну и если очень хочется, то есть обёртка try!, которая внутри создаёт задачу.
Не знал. Ну тогда эта "претензия" снимается.
C>Вот тут: http://static.rust-lang.org/doc/master/std/any/index.html
Это нашел, но не понял как оно применяется для обработки ошибок.
C>Какие плюсы от перегрузки функций?
Удобство для обобщённого программирования. Например, begin/end в С++ существуют и в виде свободных функций перегруженных отдельно для массивов. Ну и таких примеров не так уж мало.
А недостатки какие?
DE>>А можно функции типа min/max так изобразить? C>Можно.
Правильно я понимаю, что функция будет "членом" одного из объектов? То есть вызываться так: а.min(b)?
C>А зачем она нужна? Ну вот реально, какие use-case'ы?
Понимаешь, так спорить можно долго и неконструктивно. Я буду приводить какие-то примеры, ты — заявлять, что это "не нужно" и можно сделать иначе. Да, можно. Это справедливо для 90% возможностей. Но иногда удобнее их иметь.И если аргументы против "не нужно, потому что я (создатели языка) так решил", то это очень уныло. Тем более, что у любой фичи найдутся противники.
C>Rust во многом содран с OCaml'а, где перегрузки тоже не было отродясь. И таки прекрасно всё и без неё работает, во вполне реальных программах.
Ага, есть куча языков без перегрузки. И без макросов. И без темплейтов/генериков.
C>Что непереносимо? GNOME — вон весь написан в таком стиле, и ничего.
Издеваешься что ли? (Нестандартные) расширения языка — это всегда непереносимо. Да, иногда пофиг.
C>Линксовый VFS с указателями на функции, например, читается сильно лучше, чем 100500 интерфейсов из одной функции.
Ну-ну.
Тогда сишные макросы ничем не уступают растовым. Аргумент одного порядка. Да и откуда взялись "100500 интерфейсов из одной функции"?
Re[38]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
_>>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. C>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял:
#include <iostream>
using namespace std;
template <int m, int n>
struct ack
{
enum {value = ack<m - 1, ack<m, n - 1>::value>::value};
};
template <int n>
struct ack<0, n>
{
enum {value = n + 1};
};
template <int m>
struct ack<m, 0>
{
enum {value = ack<m - 1, 1>::value};
};
int main()
{
constexpr int x = ack<3, 6>::value;
cout << x << endl;
}
def ack(m, n):
if m == 0:
return n + 1
if(m > 0 and n == 0):
return ack(m - 1, 1)
if(m > 0 and n > 0):
return ack(m - 1, ack(m, n - 1))
assert(0)
print ack(3, 6)
$time g++-4.8 -pedantic -Os -std=c++0x ack_template_cpp.cpp -o ack_template_cpp
real 0m0.199s
user 0m0.176s
sys 0m0.023s
$time clang++ -std=c++1y -pthread ack_template_cpp.cpp -o ack_template_cpp
real 0m0.195s
user 0m0.162s
sys 0m0.032s
$
$
$time python -u "ack_py.py"
509
real 0m0.045s
user 0m0.036s
sys 0m0.011s
Всего около пяти раз разница.
Да и по рекурсии что питон что компиляторы с++ вылетают на ack(4, 1) с переполнением стека,
хотя для gcc это лечится ключами компилятора.
Re[37]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, DarkEld3r, Вы писали:
C>>Тут вопрос — а нафиг нужны темплейты в стиле C++? Необходимость generic'ов абсолютно понятна, а вот необходимость темплейтов с частичной типизацией уже не очень. DE>Нужны для большей гибкости.
Если мне хотелось бы изгибаться — я бы взял динамический язык.
DE>В расте ведь необходимо указывать все необходимые "трейты", так? Тут сразу шарп вспоминается, где уже хз сколько времени нет арифметических операций для генериков. В С++ оно же просто работает, если для типа нужные операции определены, независимо от того реализует ли он указанные трейты/"интерфейсы".
В Расте есть перегрузка операторов. А явное указание трейтов позволяет, например, разделять публичный интерфейс и реализацию. Так что не нужно включать в каждый файл пару миллионов строк Буста.
В результате, код на Rust'е строится что-то в 20 раз быстрее С++-ного.
C>>А можно его увидеть? DE>Да хотя бы типа такого.
Это игрушка, где настоящее-то? С поддержкой полной форматной строки. В теории оно возможно, но что-то мне подсказывает, что компиляторы это пока ниасиливают.
DE>Насчёт "выглядит как хак" ничего не скажу, то невозможность в неймспейс засунуть — уже нефига не "намного прямее".
Уже можно. Хотя не очень понятно зачем. Ну и макросы действуют только в пределах файла при явном их импорте, так что не стоит преувеличивать их глобальность.
DE>Ну дык, я и говорю — проблема только с ошибками. А концепты пытаются осилить — прогресс, вроде, есть. Разумеется, концепты — это удобно и хорошо. Но зачем их делать обязательными?
А какие реальные плюсы от их необязательности?
C>>3) Вычисления во времени компиляции. Раст разрывает "убогий недоязычок" (tm) С++ на мелкие куски. Вот тут пример предкомпиляции регексов: http://blog.burntsushi.net/rust-regex-syntax-extensions Можно увидеть то же самое для С++? DE>Возможно, на constexpr что-то и можно нагородить. Но что это доказывает? Я где-то заявлял, что в С++ вычисления на этапе компиляции удобнее/лучше?
Нет, высказвалось мнение, что шаблоны С++ лучше за счёт того, что делают вычисления во времени компиляции. В С++ это единственный метод.
C>>Вот тут: http://static.rust-lang.org/doc/master/std/any/index.html DE>Это нашел, но не понял как оно применяется для обработки ошибок.
Можно по нему делать PM и практически повторить стандартный механизм исключений. На практике, опять же, практически никогда не нужен.
C>>Какие плюсы от перегрузки функций? DE>Удобство для обобщённого программирования. Например, begin/end в С++ существуют и в виде свободных функций перегруженных отдельно для массивов. Ну и таких примеров не так уж мало.
Но и не особо много.
DE>А недостатки какие?
Возможная неоднозначность и изменение поведения. Т.е.:
//int frob(int a);int frob(float a);
int frob(double a);
int res = frob(11);
Какая функция вызовется? А если раскомментировать первую (в одном из включаемых файлов)?
Rust стараются делать так, чтобы поведение существующего кода не менялось при добавлении нового.
DE>>>А можно функции типа min/max так изобразить? C>>Можно. DE>Правильно я понимаю, что функция будет "членом" одного из объектов? То есть вызываться так: а.min(b)?
Необязательно. Первый параметр в Rust может указываться вручную, как и в Питоне. Так что этот вызов будет аналогичен: Ord::min(a, b). Если нужна конкретная спецификация, то можно так: f64::min(11, 12).
C>>А зачем она нужна? Ну вот реально, какие use-case'ы? DE>Понимаешь, так спорить можно долго и неконструктивно. Я буду приводить какие-то примеры, ты — заявлять, что это "не нужно" и можно сделать иначе. Да, можно. Это справедливо для 90% возможностей.
Именно так. И потому 90% возможностей С++ стоит выкинуть нафиг, оставив только то, что реально нужно.
DE>Но иногда удобнее их иметь.И если аргументы против "не нужно, потому что я (создатели языка) так решил", то это очень уныло. Тем более, что у любой фичи найдутся противники.
С каждой фичей матрица их взаимодействий растёт квадратично. В результате, сейчас С++ полностью не может знать никто.
C>>Rust во многом содран с OCaml'а, где перегрузки тоже не было отродясь. И таки прекрасно всё и без неё работает, во вполне реальных программах. DE>Ага, есть куча языков без перегрузки. И без макросов. И без темплейтов/генериков.
И тех, которые могут заменить С++? Таких не знаю.
C>>Что непереносимо? GNOME — вон весь написан в таком стиле, и ничего. DE>Издеваешься что ли? (Нестандартные) расширения языка — это всегда непереносимо. Да, иногда пофиг.
То есть? GNOME написан на стандартном чистом C. Там объектная модель сделана полностью на ручных vtbl.
C>>Линксовый VFS с указателями на функции, например, читается сильно лучше, чем 100500 интерфейсов из одной функции. DE>Ну-ну.
Что "ну-ну"? ООП на чистом С делается без проблем — это совершенно неоспоримый факт.
Sapienti sat!
Re[39]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Cyberax, Вы писали:
_>>>Во-первых надо понимать что такое шаблоны C++. Возникли они как реализация обобщённого программирования для C++ (для тех же целей, что и generic в java), но со временем обнаружилось, что на их основе мы в дополнение получаем ещё и мощный инструмент метапрограммирования. C>>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.
FR>Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял:
Аккерман — это немного нечестно. Он уходит в стороны, а не вглубь.
#include <iostream>
using namespace std;
template <int m>
struct ack
{
enum {value = ack<m-1>::value+m};
};
template <>
struct ack<0>
{
enum {value = 0};
};
int main()
{
constexpr int x = ack<256>::value;
cout << x << endl;
}
Так оно отваливается на 258 штуках. Что уже сильно лучше, чем 32 уровня несколько лет назад, но уровень ZX-Spectrum'а всё ещё не достигнут.
По времени да, стало лучше.
cyberax@cybmac:~/some$ time clang++ -std=c++1y -pthread test2.cpp
real 0m0.407s
user 0m0.372s
sys 0m0.031s
cyberax@cybmac:~/some$ cat test.py
num = 0
for i in range(0, 256):
num += i
cyberax@cybmac:~/some$ time python test.py
real 0m0.025s
user 0m0.013s
sys 0m0.010s
Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск.
Sapienti sat!
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
FR>>Сейчас прилично подтянули и производительность интерпретатора шаблонов и число итераций. Вот недавно мерял: C>Аккерман — это немного нечестно. Он уходит в стороны, а не вглубь.
Ну почему вполне нормально, скорость мерить.
....
C>Так оно отваливается на 258 штуках. Что уже сильно лучше, чем 32 уровня несколько лет назад, но уровень ZX-Spectrum'а всё ещё не достигнут.
gcc 4.8 на >900 отваливается и есть ключик -fconstexpr-depth можно хоть миллион задать.
Для шланга наверно тоже есть ключик.
C>По времени да, стало лучше. C>
C>cyberax@cybmac:~/some$ time clang++ -std=c++1y -pthread test2.cpp
C>real 0m0.407s
C>user 0m0.372s
C>sys 0m0.031s
C>cyberax@cybmac:~/some$ cat test.py
C>num = 0
C>for i in range(0, 256):
C> num += i
C>cyberax@cybmac:~/some$ time python test.py
C>real 0m0.025s
C>user 0m0.013s
C>sys 0m0.010s
C>
C>Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск.
Ну тоже чуть мухлюешь , итеративный конечно шустрее будет, надо на D попробовать, там и итеративный
можно сделать.
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, FR, Вы писали:
C>>Но таки разница в 20 раз осталась. Ещё тут осложняется временем на запуск. FR>Ну тоже чуть мухлюешь , итеративный конечно шустрее будет, надо на D попробовать, там и итеративный FR>можно сделать.
А без разницы, рекурсивный столько же ровно работает:
cyberax@cybmac:~/some$ cat test.py
def summer(num):
if num == 0:
return 0
return num+summer(num-1)
summer(256)
cyberax@cybmac:~/some$ time python test.py
real 0m0.025s
user 0m0.013s
sys 0m0.010s
Sapienti sat!
Re[42]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, Cyberax, Вы писали:
C>Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности.
Ну я с этим собственно и не спорил, хотя бы уже потому, что не претендую на какие-то знания макросов Rust'a. Более того, если это действительно так, то для меня это является очень существенным аргументом в пользу использования этого языка. Естественно если и остальные возможности языка не подведут (на фоне C++/D).
_>>Причём это работает даже в древнем стандарте языка. Ну а если мы возьмём современный C++, то там вообще всё просто: http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf C>Ну так где безопасный printf?
Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
C>Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой.
Не очень понятно как это сделать, ведь gettext будет возращать обычную строку, а не что-то вроде constexpr.
C>А в Rust оно может быть в compile-time. Хочу такое же в С++.
Теоретически возможно и на C++, но практике это будет очень извращённо в связи с кривизной работы со строками во время компиляции. Соответственно на D это без проблем.
C>Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения.
Аааа, понял как это на Rust'е сделано. Если подобное может препроцессор, то понятно почему такая разница в быстродействие. Интересные в Rust'е макросы конечно...
Re[40]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, _NN_, Вы писали:
_NN>В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать. _NN>Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь. _NN>constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.
Я бы сказал что дело далеко не только в интроспекции, хотя она действительно нужна (времени компиляции естественно). На мой взгляд одно из самых убийственных, это отсутствие возможности нормально работать с различными типа данных (и главное строками!) во время компиляции. Плюс ещё замечательная функция mixin в D, которая замешиваясь на различные другие нюансы язык (типа устройства перегрузки операторов через строковый параметр шаблона) позволяет творить чудеса... В общем даже если и дадут интроспекцию в C++, то до D всё равно будет ещё очень далеко.
_NN>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.
_NN>Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.
Не спорю. ) Вопрос в том какие альтернативы у нас есть...
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
Это не то настоящий суровый printf должен практически все ошибки отлавливать во время компиляции, например как в OCaml:
open Printf
let _ = printf "%d" "compile time fail"
File "printf_tst.ml", line 3, characters 20-39:
Error: This expression has type string but an expression was expected of type
int
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
C>>Ну вот в Rust'е тоже всё лучше с метапрограммированием, чем в С++. О чём я и говорил, собственно. Если сравнивать с D или Nemerle, то они будут примерно одинаковы по мощности. _>Ну я с этим собственно и не спорил, хотя бы уже потому, что не претендую на какие-то знания макросов Rust'a.
Ну вот как раз кто-то спорил
C>>Ну так где безопасный printf? _>Так в pdf'ке же вроде весь код есть. Там описан printf, который кидает исключения в случае любых несоответствий строки форматирования аргументам.
Там описано, что так сделать можно, но конкретного кода нет. Я в целом вполне верю, что это возможно, но вот на constexpr и шаблонах сделать полный разбор строки printf — совсем нетривиально.
C>>Если в рантайме, то придётся использовать только runtime-проверки, конечно же. Однако, если код делается в стиле gettext, то никаких проблем — начальная английская строка будет проверяться в compile-time. А для транслированных строк просто надо будет проверить совместимость с начальной строкой. _>Не очень понятно как это сделать, ведь gettext будет возращать обычную строку, а не что-то вроде constexpr.
Будет специальная функция, назовём её "T" с такой сигнатурой: "fn T(initial: str) -> &'static str". Т.е. в программе будет что-то типа: "println!(T("Hello, world"), ...)". Макрос println! будет знать про то, что T будет возвращать исходную строку и для проверки валидности форматной строки просто возьмёт её аргумент. Ну а во время исполнения оно будет работать всё как обычно.
Ещё, вместо hard-coded имени T можно сделать специальную аннотацию на функцию.
C>>Большой он. В Rust в compile-time сразу создаётся оптимизированный КА для сравнения. _>Аааа, понял как это на Rust'е сделано. Если подобное может препроцессор, то понятно почему такая разница в быстродействие. Интересные в Rust'е макросы конечно...
Я его ускорил ещё на 20%, кстати. Там внутри всегда считается, что для regexp'а нужно будет получать результирующие capture groups, из-за чего делаются ненужные динамические аллокации, я их просто убрал для простого is_match. Ещё можно вместо новых строк возвращать slice'ы. Да и в целом код регэкспов в Rust пока не очень оптимизировали.
Sapienti sat!
Re[41]: Язык D - действительно красота и эффективность в одном ф
Здравствуйте, alex_public, Вы писали:
_NN>>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)
_>А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.
Все надеемся и ждем.
Правда боюсь представить что там будет
_>Не спорю. ) Вопрос в том какие альтернативы у нас есть...
Тут уже прозвучали известные альтернативы, мне кажется только Template Haskell еще не звучал