Круто! В следующий разп попробуй тупо: ft — st. Тебе наверняка понравится .
А вообще для этих целей есть класс System.Diagnostics.Stopwatch:
using System;
using System.Diagnostics;
class Program
{
static int Ack(int m, int n)
{
if (m == 0) return n + 1;
else if (n == 0) return Ack(m - 1, 1);
else return Ack(m - 1, Ack(m, n - 1));
}
static void Main(string[] args)
{
Stopwatch timer = Stopwatch.StartNew();
int a = Ack(3, 11);
Console.WriteLine("Ack(3, 11) = {0} time = {1}", a, timer.Elapsed);
}
}
На моей машине выводит:
Ack(3, 11) = 16381 time = 00:00:00.8839232
Что до твоих тестов, то я не специалист в развороте рекурсии, но что-то мне говорит, что если это сделать, то С/С++ в версии MS VC и/или Intel C++ как всегда порвут всех. Хотя конечно не сильно.
Тот факт что F#, т.е. энергичный язык хостящийся на дотнете показал почти такое же время как ленивые языки говорит только о том, что скорость в этом тесте определяется не ленивостью (которая тут на фиг не упала), а качеством оптимизации концевой рекурсии. Если сделать скидку на то, что F# еще вынужден JIT-ить метод в момент его первого выполнени, то становится очевидным, что приемуществ у ленивых языков нет.
Так вот подобные тесты никак не показывают скорость код в общем. Это частный случай на котором как раз в первую очередь тестируются ФЯ и который осовсем не характерен для реального кода.
В реальном же коде Хаскелевский компилятор часто уходит в глубокий аут от казалось бы обыйденных ситуаций.
На последок, вот тебе Немерлевый вариант. Думаю, он должен отработать примерно так же как F#-ый:
using System;
using System.Diagnostics;
static int Ack(int m, int n)
{
if (m == 0) return n + 1;
else if (n == 0) return Ack(m - 1, 1);
else return Ack(m - 1, Ack(m, n - 1));
}
Stopwatch timer = Stopwatch.StartNew();
int a = Ack(3, 11);
Console.WriteLine("Ack(3, 11) = {0} time = {1}", a, timer.Elapsed);
У меня он отрабатывает за:
Ack(3, 11) = 16381 time = 00:00:00.4611239
G>С программой на Scheme вообще-то в данном примере не совсем короректная ситуация — я не знаю, как указать компилятору использовать тип int32. Боюсь, здесь используется стандартный подход — пока результат влезает в определённую машинную разрядность (в DrScheme, по-моему, 64 бита), числа хранятся и оперируются в этом виде (int64), а как только выходит за пределы этих 64 бит, вычисления идут уже с BigInt. G>Даже если разрядность компилятором в данном случае ограничена типом int64, то вот уже как минимум полуторократное замедление программы по сравнению с другими — ведь там везде расчёты с типом int32... То есть производительность получается примерно на уровне C#...
Это все домыслы. От чего тормозит C# известно. Его компилятор не оптимизирует концевую рекурсию.
G>В программах на С# и Scheme ещё идёт и проверка на выход за пределы диапазона целых чисел, тогда как в других языках её нет — это тоже замедляет расчёты.
Опять домыслы. В С# по умолчанию выход за границы диапазовно не контролируются. Это надо включать отдельной опцией компилятора или оборачивать код в блок checked. Такая проверка идет по умолчанию в Немерле, но как показал мой тест она ровным счетом ничего не меняет (по крайней мере на моем Core 2 Duo).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, geniepro, Вы писали:
А>>> Я в сторону Nemerle не шуганусь ни за какие коврижки,
K>>Почему?
G>Эх, не хотелось бы мне участвовать в очередном флейме, но не могу удержаться от цитаты: G>______________________
G>Алан Перлис однажды заметил: “Язык, освоение которого не позволяет найти новые подходы к программированию, не заслуживает изучения”. G>______________________
G>Разве Немерле даёт что-то новое, чего не давал бы какой-нибудь другой язык? Он только комбинирует в себе кучу разных идей...
Вот их комбинацию и дает. Лисп не дает. Хаскель не дает. А он дает. В Хаскеле тоже ничего по сути нового. И не надо по классы типов и монады рассказывать. Калссы типов под именем интерфейс были в Яве. Монады — это извращение для борьбы с собственной чистотой. Так и тут вывод типов из использоания для в сложной и не приспособленной для этого системе типов. Макросы кучи новых видов которые ранее в природе не всречались. Раздельная компиляция макросов. Информация о типах в них. Да море всего.
G>Есть ли в Немерле своя "национальная идея"?
Ясно начинается демогогия. Что и следовало ожидать.
Ответом в той же манере будет: А зачем изучать Лисп? Все что в нем есть, есть в Немерле. Даже больше.
Ты ведь говоришь о языке для работы? Хаскель тебе явно не подходит. Видимо то ли скорость не удовлетворяет, то ли императивщинка нужна кое где, то ли макросы. Судя по тому, что ОКамл тоже не очень удовлетворяет, раз шугаешся, то значит нужны макросы. Вот Немерле и есть тот ОКамл с полноценными макросами превосходящими те же Лисповские (за счет доступности информации о типах внутри макроса).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Я все же справился с разворотом рекусрии на C#, так что думю, что он сейчас станет победятлом :
using System;
using System.Diagnostics;
class Program
{
static int Ack(int m, int n)
{
while (m != 0)
{
if (n == 0)
n = 1;
else
n = Ack(m, n - 1);
m--;
}
return n + 1;
}
static void Main(string[] args)
{
Stopwatch timer = Stopwatch.StartNew();
int a = Ack(3, 11);
Console.WriteLine("Ack(3, 11) = {0} time = {1}", a, timer.Elapsed);
}
}
Ну, пока этот код не перепишут на С.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>>Ну и что? Расширения — только функции; минимальная интеграция с внешним миром, так сказать. Переменные неизменяемые. Как следствие — возможны ленивые вычисления (уж не знаю, реализованы ли они на самом деле). Каждый шаблон можно вполне рассматривать как функцию result-tree-fragment = f (nodeset, nodeset, ...). С использованием EXSLT брюки превращаются: nodeset = exslt:node-set(result-tree-fragment). Насколько я успел понять из здешних флеймов (гы, нехилый у меня источник самообразования ), всего этого достаточно, чтобы обозвать язык чисто функциональным. Да, кстати, ООП там также не пахнет.
VD>Ну, и как быть с циклами? Разве в чистых ФЯ они могут быть?
В XSLT 1.0 циклов нет. Только через рекурсию. Или через извраты типа "находим или создаём какое-нить множество узлов подходящего размера и сканируем его". Учитывая запредельную "компактность" синтаксиса, это просто рай на земле. Ненавижу...
Явно изменяемой переменной "текущий узел" тут нет, эту конструкцию вполне можно реализовать через рекурсию (типа прологовского L := (A | L) или как-то так). Фиг знает, как оно реализовано на самом деле в том же libxslt.
и ищешь по "8 Repetition" или "xsl:for-each".
ДГ> Только через рекурсию. Или через извраты типа "находим или создаём какое-нить множество узлов подходящего размера и сканируем его". Учитывая запредельную "компактность" синтаксиса, это просто рай на земле. Ненавижу...
Незнаю. Если бы в XSLT не было идиотского, основанного на XML синтаксиса, то был бы очень ничего себе язычек генерации текста. А вот в перемешку с генерируемым HTML этот XML-синтаксис выглядит просто ужасно. Идеологически же язык очень ничего себе. Идея шаблонов и паттерн-матчинга на базе XPath очень здравая.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
ДГ>Явно изменяемой переменной "текущий узел" тут нет, эту конструкцию вполне можно реализовать через рекурсию (типа прологовского L := (A | L) или как-то так). Фиг знает, как оно реализовано на самом деле в том же libxslt.
Какого к черту дерева? Это самый что ни наесть стандартный цикл.
Насколько я понимаю переменные в нем тоже без проблем присваиваются.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Это самый что ни наесть стандартный цикл. VD>Насколько я понимаю переменные в нем тоже без проблем присваиваются.
Присваиваются... Один раз. Вот тебе полный рекурсивный аналог for-each, только тело цикла вынесено в отдельный шаблон. Где здесь разрушающее присваивание?
Здравствуйте, VladD2, Вы писали:
ДГ>>Присваиваются... Один раз.
VD>Уверен? VD>Попробуй присвой переменную до цикла, измени ее значение в цикле, и используй его после цикла.
В указанной строчке генерируется ошибка "xsl:variable : redefining test", на выходе пусто (шаблон не прорабатывает). Тебе известны какие-либо другие способы "изменить значение" переменной в XSLT?
Здравствуйте, VladD2, Вы писали:
VD2> Ответом в той же манере будет: А зачем изучать Лисп? Все что в нем есть, есть в Немерле. Даже больше.
Просто Лисп — классика. Полувековая история компьютинга, всё-таки... ;о)
VD2> Ты ведь говоришь о языке для работы? Хаскель тебе явно не подходит. Видимо то ли скорость не удовлетворяет, то ли императивщинка нужна кое где, то ли макросы. Судя по тому, что ОКамл тоже не очень удовлетворяет, раз шугаешся, то значит нужны макросы. Вот Немерле и есть тот ОКамл с полноценными макросами превосходящими те же Лисповские (за счет доступности информации о типах внутри макроса).
Нет-нет, Влад, это не ко мне. Я не тот Аноним 673, который шугается от Немерле... :о)
Мне Немерле любопытен, хотя и не настолько, что бы скачивать исходники компилятора из SVN или где они там хранятся, и билдить их вручную.
А та версия, что я скачал с их сайта (в виде инсталлятора), не может откомпилировать твой вариант Ack на Немерле...
Когда, кстати, немерлевцы обновят инсталлятор компилятора? А иначе о каком промышленном применении может идти речь, когда такие несовместимости даже в простейших случаях?
VD2> Круто! В следующий раз попробуй тупо: ft — st. Тебе наверняка понравится
О, пасип, понравилось! :о))
VD2> Я все же справился с разворотом рекусрии на C#, так что думю, что он сейчас станет победятлом :
Боюсь, эта версия стала дятлом, а не победятлом... :о)) Она работает ещё медленнее (немного), чем оригинальная...
Как мне известно, в этой функции нельзя обойтись одними итерациями, не сэмулировав при этом стек и "рекурсию для бедных"...
VD2> Короче крутость ленивых языков не подтвердилась.
О какой крутости ленивости шла речь? Я лишь заявил, что ленивость можно побороть анализатором строгости или ручным форсированием выполнения...
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, VladD2, Вы писали:
VD>> В Хаскеле тоже ничего по сути нового. И не надо по классы типов и монады рассказывать. Калссы типов под именем интерфейс были в Яве.
D>Сравнивать явовские интерфейсы и классы типов Хаскелла — всё равно, что сравнивать макросы C и Лиспа. Инструменты радикально разной мощности.
Мало того — Ява появилась существенно позже Хаскелла. Тогда уж правильнее было говорить об интерфейсах Objective C...
Здравствуйте, VladD2, Вы писали:
VD2> Ну, и как быть с циклами? Разве в чистых ФЯ они могут быть?
Ну... смотря в каких.
Вот SISAL — считается чистым ФЯ, но там есть конструкция, очень похожая на цикл, и даже называется циклом, но — это язык с однократным присванием, и этот "цикл" на самом деле распараллеливается на разные процессоры и выполняет все итерации одновременно (если есть свободные процессоры)...
Я просто хочу сказать, что динамичность или ленивость — не непреодолимые преграды, их можно обойти хорошими компиляторами.
Например, Stalin (компилер для Scheme) для той же функции Аккермана генерирует код в три раза более быстрый, чем GCC (правда, сразу признаюсь, я сам этого не проверял, мне показывали бенчмарки)...
Здравствуйте, geniepro, Вы писали:
G>Мне Немерле любопытен, хотя и не настолько, что бы скачивать исходники компилятора из SVN или где они там хранятся, и билдить их вручную. G>А та версия, что я скачал с их сайта (в виде инсталлятора), не может откомпилировать твой вариант Ack на Немерле...
Здравствуйте, geniepro, Вы писали:
G>Разве Немерле даёт что-то новое, чего не давал бы какой-нибудь другой язык? Он только комбинирует в себе кучу разных идей...
Вообще это вопрос личный, язык как женщина — мне не даёт, тебе не даёт, Владу даёт.