Здравствуйте, Nuzhny, Вы писали:
N>И это простой и понятный пример? Множество скобок и др. символов лично для меня не вполне читабельны. Все программы на Немерле так выглядят?
Ну, давай сравним с оригиналом.
Возмем саму функцию (на D):
template factorial(int n : 1)
{
enum { factorial = 1 }
}
template factorial(int n)
{
enum { factorial = n* factorial!(n-1) }
}
и на Nemerle:
Factorial(n : uint) : ulong
{
| 0 | 1 => 1
| _ => n * Factorial(n - 1)
}
Могу переписать ее более "понятно" для тех кто привык только к С++:
Factorial(n : uint) : ulong
{
if (n == 0 || n == 1) 1
else n * Factorial(n - 1)
}
Она правда корректна по сравнению с оригиналом (где в случае n < 1 будет зацикливание), но все же.
Где здесь какие-то лишние скобочки или еще что-то?
Теперь думаем что мы получили и как можем использовать. А получили мы рекурсивый шаблон на D. Использовать этот шаблон мы может только во время компиляции. Вычисляться он будет в режиме интерпретации.
На Nemerle мы получили просто функцю. Мы можем вызвать ее в программе как любую другую. Теперь чтобы вычислить эту функцию во время компляции мы просто помещаем ее вызов в макрос:
macro CompileTimeFactorial(n : uint)
{
def res = Util.Factorial(n);
<[ $(res : ulong) ]>
}
в котором мы производим вычисление и помещаем результат вычисления код генерируемый макросом.
В обличии от D или C++ мы вольны произвести в макросе вычисления любой сложности. Так если у нас уже есть нужная функция которую нужно вычислить во время компиляции, то мы просто вызваем ее в макросе и получаем требуемый результатм.
То есть для нас нет разницы между кодом программы и метакодом. В D же и в С++ мы вынждены писать метакод на птичьех языках которые сильно отличаются от того языка что мы вынуждены применять в реальной программе.
Что тут непонятного? Возможно:
<[ $(res : ulong) ]>
да, это новое для D/C++-программиста. Но объяснить это не так то и сложно.
Это способ сгенерировать код. Подобных средств в D и С++ попросту нет. Потому и сравнивать тут нечего.
<[ ]> — это аналог строкового литерала в C++, но в отличии от С++ внутри этого литерала получается не страка, а выражение которое можно подставить в программу. Другими словами <[ ]> выделяет участки кода которые интерпретируются компилятором не как исполняемый код, а как заготовка для генерации кода.
$ — позвляет состалься в этой заготовке на переменные из внешнего кода. Так что мы, например, может написат так:
<[
if ($x)
SomeCall();
else
$x
]>
и значение "x" будет подставлено в те места где пы указали $x. Толко значнеие "x" будет интерпретироваться как участок кода. Так что если мы подставляем некий литерал, то нам нужно указать компилятору, что его нужно преобразовать в код. Так $(res : ulong) говорит, что значение из внешней (мета-) программы нужно преобрзовать в литерал (в компилируемой программе).
... << RSDN@Home 1.2.0 alpha rev. 637>>