Re[32]: Язык D - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 27.04.14 17:37
Оценка:
Здравствуйте, 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>Я не очень понял где там два остальных метода.


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-ем случае отвечает программист.
Re[36]: Язык D - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 27.04.14 17:53
Оценка:
Здравствуйте, 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 Можно увидеть то же самое для С++?


http://www.boost.org/doc/libs/1_55_0/doc/html/xpressive.html
Re[37]: Язык D - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 02:44
Оценка:
Здравствуйте, 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";

Выносите.

Для сравнения:
fn main() {
    println!("Hello, world! {:d}\n", 13);
    println!("Hello, world! {:d}\n", "Hello");
}

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 делается только построение дерева выражения.

Пример:
#include <iostream>
#include <boost/xpressive/xpressive.hpp>
using namespace boost::xpressive;
int main()
{
    cregex test = *_s >> +_d >> "--" >> +_d >> *_s;
    cmatch what;
    for(int f=0;f<10000000;++f)
        regex_match("  123--541", what, test);
    return 0;
}

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 - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 02:46
Оценка: -1
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 28.04.14 04:37
Оценка:
Здравствуйте, 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"; Оно в таком стиле и работает собственно (выводит всё корректно, в соответствие с типом).

Причём это работает даже в древнем стандарте языка. Ну а если мы возьмём современный C++, то там вообще всё просто: http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf

Кстати, в языке 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 - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 28.04.14 04:43
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>В D точно так же.


Ещё раз повторяю:

1. Единственный оверхед в D относительно C++ может возникать от использования GC (в отличие от Java).
2. При этом использование GC в коде на D не обязательно, хотя и упрощает код для многих случаев.

_>>Хы, если говорить про C в сравнение с C++, то там не то что просто отдельные фичи отсутствую, а целые парадигмы! Нет ни нормального метапрограммирование, ни обобщённого программирование, ни ООП.

C>Вообще-то, там всё есть, кроме нормального метапрограммирования.

В таком смысле всё есть и в ассемблере.
Re[39]: Язык D - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 05:43
Оценка:
Здравствуйте, 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,
:
...

(часть результата вывода rustc --opt-level=3 --pretty expanded test.rs )

Кстати, код на Rust сразу корректно работает с UTF-8 и правильно определяет все диапазоны чисел в Unicode.
Sapienti sat!
Re[39]: Язык D - действительно красота и эффективность в одном ф
От: _NN_ www.nemerleweb.com
Дата: 28.04.14 06:25
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, Cyberax, Вы писали:


C>>Где "мощный"? Шаблоны — это самый медленный интерпретируемый язык, примерно в 100 раз медленнее Питона. С огромными ограничениями, типа максимального количества итераций в районе всего 30-50.


_>Ну да, претензий к нему не мало. Только надо сравнивать с аналогами, а не с языками общего назначения. Да, язык шаблонов D заметно мощнее и быстрее. В Nemerle кажется (я сам его так и не смотрел пока) ситуация ещё лучше. Кого ещё можем тут назвать, макросы лиспа? )


В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать.
Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь.
constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.
Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)

Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.

Макросы в Rust/Nemerle/Scala и т.п. имеют всю информацию о типах и могут сгенерировать наиболее оптимальный код.
Ну и читабельность намного выше, т.к. код макросов не более чем вызов API компилятора, что можно сравнить с вызовом функций библиотеки.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[36]: Язык D - действительно красота и эффективность в одном ф
От: DarkEld3r  
Дата: 28.04.14 08:19
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: FR  
Дата: 28.04.14 08:28
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 12:54
Оценка: -2
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 13:03
Оценка: -1
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: FR  
Дата: 28.04.14 13:19
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 28.04.14 13:33
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: FR  
Дата: 28.04.14 13:41
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>А без разницы, рекурсивный столько же ровно работает:


Ну он тоже на 1000 вылетит с переполнением стека.

Вот проверил D:

import std.stdio;

ulong tst(ulong m) pure
{
ulong result = 0;
while(m)
    result += m--;
return result;
}

void main()
{
enum {x = tst(1000000)};
writeln(x);
}


num = 0
for i in xrange(0, 1000001):
   num += i
print num



$time dmd  tst001.d

real    0m0.843s
user    0m0.779s
sys    0m0.064s
$
$time python -u "tst001.py"
500000500000

real    0m0.083s
user    0m0.082s
sys    0m0.000s
$


В 10 раз получается, в общем есть куда расти
Re[40]: Язык D - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 29.04.14 03:22
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: alex_public  
Дата: 29.04.14 03:33
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>В С++ нет итроспекции типов, в следствии чего постоянные ухищрения в виде has_*** , и то не все даже возможно сделать.

_NN>Где простейший has_method<T, SomeMethodName> ? Его просто так не сделаешь.
_NN>constepxr это шаг в направлении шаблонов D , но сейчас он довольно ограничен и ,кстати, не всегда гарантирует вызов функции во время компиляции.

Я бы сказал что дело далеко не только в интроспекции, хотя она действительно нужна (времени компиляции естественно). На мой взгляд одно из самых убийственных, это отсутствие возможности нормально работать с различными типа данных (и главное строками!) во время компиляции. Плюс ещё замечательная функция mixin в D, которая замешиваясь на различные другие нюансы язык (типа устройства перегрузки операторов через строковый параметр шаблона) позволяет творить чудеса... В общем даже если и дадут интроспекцию в C++, то до D всё равно будет ещё очень далеко.

_NN>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)


А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.

_NN>Посему на данный момент шаблоны в С++ не решают огромный спектр задач, или решают так, что никто не захочет это писать и читать.


Не спорю. ) Вопрос в том какие альтернативы у нас есть...
Re[41]: Язык D - действительно красота и эффективность в одном ф
От: FR  
Дата: 29.04.14 04:46
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: Cyberax Марс  
Дата: 29.04.14 04:48
Оценка:
Здравствуйте, 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 - действительно красота и эффективность в одном ф
От: _NN_ www.nemerleweb.com
Дата: 29.04.14 07:10
Оценка:
Здравствуйте, alex_public, Вы писали:

_NN>>Надеюсь к С++17 что-то будет, только неясно когда это будет в компиляторах =)


_>А вот с этим не вижу сейчас проблемы. Тот же gcc вообще опережает график, вводя фичи ещё до стандарта.

Все надеемся и ждем.
Правда боюсь представить что там будет

_>Не спорю. ) Вопрос в том какие альтернативы у нас есть...


Тут уже прозвучали известные альтернативы, мне кажется только Template Haskell еще не звучал
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.