Здравствуйте, Дарней, Вы писали:
Д>Так почему бы не выяснить самому, и не рассказать другим?
Очень просто. Я изучаю C++ и рассказываю о нем (точне об инструментах для него). Изучаю Ruby и рассказываю о нем. Все, больше времени нет.
Поэтому о Немерле хотелось бы узнать из чужих рук.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Ты часом к науке не имел отношения?
Нет.
E>А то я наблюдал, как при передачи статей в журнал некоторые научные деятели намеренно в сложных формулах мелкие ошибки делали (например, кое-где плюсик на минус поменяют). Чтобы никто просто так результатами трудов не воспользовался
namespace Oyster
{
public module Math
{
// Просто метод, который просто считает факториал в рантаймеstatic public Fact(x : int) : int
{
| 1 => 1
| _ =>
if (x > 1)
x * Fact(x - 1)
else
throw ArgumentException("x")
}
}
}
Дарней wrote: > тогда расскажи хотя бы, какие принципиальные проблемы ты видишь в > реализации данной задачи на Немерле > очень просто, правда?
1. Интероперабельность с остальным кодом на C#.
2. Куда будет записываться информация о размерности типа?
O>namespace Oyster
O>{
O> public module Math
O> {
O> // Просто метод, который просто считает факториал в рантайме
O> static public Fact(x : int) : int
O> {
O> | 1 => 1
O> | _ =>
O> if (x > 1)
O> x * Fact(x - 1)
O> else
O> throw ArgumentException("x")
O> }
O> }
O>}
O>
Кстати, если сравнить реализацию compile-time вычисления факториала на C++:
template< int N >
struct Factorial {
enum { value = N * Factorial< N-1 >::value };
};
template<>
struct Factorial< 1 > {
enum { value = 1 };
};
template<>
struct Factorial< 0 > {};
то мне кажется, что она получается в более функциональном стиле, что ли И не на много длиннее в реализации.
Вот только синтаксический оверхэд в виде template<> struct под ногами путается
Зато компилятор не дает вычислять факториал нуля
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Кстати, если сравнить реализацию compile-time вычисления факториала на C++:
...
E>то мне кажется, что она получается в более функциональном стиле, что ли
Думаешь? В Nemerle я тоже заюзал матчинг, на самом деле. И какая разница, выглядит матчинг так:
fun(x)
{
| 0 => ...
| 1 => ...
| _ => ...
}
Или так:
fun(0) = ...
fun(1) = ...
fun(x) = ...
E>И не на много длиннее в реализации. E>Вот только синтаксический оверхэд в виде template<> struct под ногами путается E>Зато компилятор не дает вычислять факториал нуля
На Nemerle тоже не даст, естественно, — посмотри, что случится при вызове Oyster.Macro.Fact(0)
В общем-то, главное преимущество Nemerle тут в том, что можно проворачивать более сложные вычисления в compile-time, чем на шаблонах.
Ну и ещё преимущество _имхо_ в том, что фактически пишется тот же код на Nemerle, а не на каком-то другом подъязыке, — просто он выполнится во время компиляции.
Здравствуйте, eao197, Вы писали:
E>Вот только синтаксический оверхэд в виде template<> struct под ногами путается
А теперь вариант на D. Как говорится почувствуйте разницу.
import std.stdio;
// можно и специализацию использовать(или вообще тернарный оператор ? : )
// но я намеренно выбрал самый непохожий на C++ вариантtemplate fact(uint n)
{
static if (n <= 1)
const ulong fact = 1;
else
const ulong fact = n * fact!(n - 1);
}
void main()
{
auto x = fact!(6);
auto y = fact!(50);
// 720 15188249005818642432
writef("%d %d\n", x, y);
}
Правда и D, и C++ не позволяют достичь той же функциональности, что и Nemerle. Хотя D в принципе к этому чуть ближе, т.к. позволяет шаблонам принимать идентификаторы в качестве параметров(а вот выражения к сожалению нет).
E>Зато компилятор не дает вычислять факториал нуля
Это неправильно с точки зрения математики.
Самый близкий к истине вариант привел xbit. А вот полностью идеологически правильный и грамотный(имхо) вариант:
Здравствуйте, Oyster, Вы писали:
O>На Nemerle тоже не даст, естественно, — посмотри, что случится при вызове Oyster.Macro.Fact(0)
Какой именно из вариантов?
O>В общем-то, главное преимущество Nemerle тут в том, что можно проворачивать более сложные вычисления в compile-time, чем на шаблонах.
Ну дык это в Nemerle и подкупает. Т.к. в сложных случаях compile-time вычисления на шаблонах C++, имхо, лучше элементарной кодогенерацией заменять.
O>Ну и ещё преимущество _имхо_ в том, что фактически пишется тот же код на Nemerle, а не на каком-то другом подъязыке, — просто он выполнится во время компиляции.
Ну с виду так не скажешь Из-за <[, ]> и $(). При этом нужно помнить, к переменной из какого контекста ты обращаещься и что следует возвращать как результат макроса.
Кстати, я забыл, в результате работы макроса можно ли сгенерировать код, который внутри к другому макросу будет обращаться? Т.е. обращение к макросу не внутри тела макроса, в том коде который макрос производит? Что-то на эту тему было, но уже не помню где
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
O>>На Nemerle тоже не даст, естественно, — посмотри, что случится при вызове Oyster.Macro.Fact(0)
E>Какой именно из вариантов?
?
Ты сказал, что шаблон выдаст ошибку компиляции, если ноль. Так вот Nemerle сделает то же самое.
O>>Ну и ещё преимущество _имхо_ в том, что фактически пишется тот же код на Nemerle, а не на каком-то другом подъязыке, — просто он выполнится во время компиляции.
E>Ну с виду так не скажешь Из-за <[, ]> и $(). При этом нужно помнить, к переменной из какого контекста ты обращаещься и что следует возвращать как результат макроса.
Поэтому _имхо_ — не хочется об этом дискутировать.
E>Кстати, я забыл, в результате работы макроса можно ли сгенерировать код, который внутри к другому макросу будет обращаться? Т.е. обращение к макросу не внутри тела макроса, в том коде который макрос производит? Что-то на эту тему было, но уже не помню где
Макрос всегда развернётся внутри. А зачем такое надо? Ведь макрос всё равно развернётся в итоге — какая разница, внутри или снаружи это произойдёт?
Здравствуйте, WolfHound, Вы писали:
WH>...То никакой динамической памяти не понадобится. Болие того оптимизатор может это все разложить по регистрам. WH>Эта замена при компиляции на VC++8 разагнала boost::math::quaternion в 15 раз.
А нельзя ли просто воспользоваться отдельными переменными вместо массива?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
VD>>Мне вот интересно если Мэерс не описал этот прикол, то сколько бы программистов доперли до него?
FR>Достаточно того что он допер. Остальные могут использовать.
Это не ответ на мой вопрос.
VD>>Склько программистов используют подобные приколы в своем коде?
FR>Обычно подобный код сидит в библиотеках, а тот же boost уже достаточно массово используется.
Примеры, именно такого использования приведи, плиз.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Oyster, Вы писали:
O>Ты сказал, что шаблон выдаст ошибку компиляции, если ноль. Так вот Nemerle сделает то же самое.
По-моему, твой первый вариант выдал бы 0, но после длительных вычислений в compile-time. Не так?
E>>Кстати, я забыл, в результате работы макроса можно ли сгенерировать код, который внутри к другому макросу будет обращаться? Т.е. обращение к макросу не внутри тела макроса, в том коде который макрос производит? Что-то на эту тему было, но уже не помню где
O>Макрос всегда развернётся внутри. А зачем такое надо? Ведь макрос всё равно развернётся в итоге — какая разница, внутри или снаружи это произойдёт?
Да просто задумался о глубине вложенных в друг-друга макросов, из которых вызываются функции, из которых вызываются другие макросы и т.д. Но, собственно, не важно. Просто хотел уточнить.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Vermicious Knid, Вы писали:
VK>А теперь вариант на D. Как говорится почувствуйте разницу.
Ну очень мне нравится D. Вот только библиотеками он обеспечен пока очень мало
В этом плане у Nemerle очень выигрышная позиция -- он то предоставляет доступ к .NET Framework.
E>>Зато компилятор не дает вычислять факториал нуля VK>Это неправильно с точки зрения математики.
Да, действительно. Но это легко исправляется. Код даже меньше получится:
template< int N >
struct Factorial {
enum { value = N * Factorial< N-1 >::value };
};
Oyster wrote: > C>1. Интероперабельность с остальным кодом на C#. > А как насчёт интероперабельности решения на C++ с остальным кодом на Си?
В С++ с интероперабельностью все нормально.
> Всё-таки Nemerle — это не C#, это совсем другой язык.
Тем не менее, интероперабельность нужна.
> C>2. Куда будет записываться информация о размерности типа? > В код — куда же ещё?
Я понял. А где оно в скомпилированом виде будет храниться? Или как с
template'ами в С++ — при компиляции нужен исходный код?
Здравствуйте, eao197, Вы писали:
E>Кстати, я забыл, в результате работы макроса можно ли сгенерировать код, который внутри к другому макросу будет обращаться? Т.е. обращение к макросу не внутри тела макроса, в том коде который макрос производит? Что-то на эту тему было, но уже не помню где
Как ни странно — легко. Вот вариация на тему макроса Oyster'а: