module Common
{
MakeForEachBody(Pattern : Pattern, body : Expr)
{
if (body is MatchBody) // если тело цикла содержит паттерны...
{
assert(Pattern is Identifier); // паттерн должен быть простым именем
<[ match (current)
..$body ]>
}
else
<[ match (current)
{
| $Pattern => $body
| _ => ()
} ]>;
}
}
где тут переменная current передается?
Re: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 09:10
Оценка:
Здравствуйте, Аноним, Вы писали:
А>где тут переменная current передается?
Нигде. Код, генерирующий ее объявление вы не привели.
Re[2]: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 10:51
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>где тут переменная current передается?
А>Нигде. Код, генерирующий ее объявление вы не привели.
Здравствуйте, Аноним, Вы писали:
А>тогда какой смысл передавать Pattern, Body?
Чтобы реализовать MakeForEachBody. Pattern и Body это переменные в коде макроса, а current в генерируемом коде.
Ce n'est que pour vous dire ce que je vous dis.
Re[6]: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 14:30
Оценка:
Здравствуйте, Don Reba, Вы писали:
DR>Здравствуйте, Аноним, Вы писали:
А>>тогда какой смысл передавать Pattern, Body?
DR>Чтобы реализовать MakeForEachBody. Pattern и Body это переменные в коде макроса, а current в генерируемом коде.
Гигиена в макросах это механизм предотвращающий случайное смешивание имён. В Немерле с этим всё в порядке. Для использования значений переменных макроса в сгенерированном коде используется особый синтакс, со знаком $; в то же время, переменная названная current в макросе будет иметь другое имя в сгенерированном коде, не создающее конфликтов с переменными в коде использующем макрос. К примеру, пишем простейший макрос, используем его в коде и смотрим на результат в дизассемблере:
using Nemerle.Compiler;
using System.Console;
macro TestMacro()
{
<[ def current = 5; WriteLine(current) ]>
}
TestMacro();
public class Test
{
public static void Main()
{
int value = 5;
Console.WriteLine(value);
}
}
Ce n'est que pour vous dire ce que je vous dis.
Re[8]: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 16:22
Оценка:
Здравствуйте, Don Reba, Вы писали:
С твоим примером нет проблемы. А вот такой? Немерли нет под рукой проверить.
using Nemerle.Compiler;
using System.Console;
macro TestMacro()
{
<[ WriteLine(current) ]>
}
Здравствуйте, Аноним, Вы писали:
А>С твоим примером нет проблемы. А вот такой? Немерли нет под рукой проверить.
А>
А>def current = 5;
А>TestMacro();
А>
Ошибка при вызове макроса:
error: unbound name `current'
Ce n'est que pour vous dire ce que je vous dis.
Re[10]: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 16:49
Оценка:
Здравствуйте, Don Reba, Вы писали:
DR>Здравствуйте, Аноним, Вы писали:
А>>С твоим примером нет проблемы. А вот такой? Немерли нет под рукой проверить.
А>>
Здравствуйте, Аноним, Вы писали:
А>Теперь понял о чем я????
Эта ошибка как раз показывает, что с гигиеной у нас всё в порядке. Если очень нужно, это можно обойти и обратиться к переменной в вызывающем коде прямо по имени.
Здравствуйте, Don Reba, Вы писали:
DR>Здравствуйте, Аноним, Вы писали:
А>>Теперь понял о чем я????
DR>Эта ошибка как раз показывает, что с гигиеной у нас всё в порядке. Если очень нужно, это можно обойти и обратиться к переменной в вызывающем коде прямо по имени.
Здравствуйте, Аноним, Вы писали:
А>Теперь понял я о чем? посмотри изначальный пост.
Тебе всё ещё что-то непонятно в изначальном посте?
Ce n'est que pour vous dire ce que je vous dis.
Re[14]: N2 – языковый фрeймворк(ошибка)
От:
Аноним
Дата:
09.09.12 17:22
Оценка:
Здравствуйте, Don Reba, Вы писали:
DR>Тебе всё ещё что-то непонятно в изначальном посте?
module Common
{
MakeForEachBody(Pattern : Pattern, body : Expr, current)
{
if (body is MatchBody) // если тело цикла содержит паттерны...
{
assert(Pattern is Identifier); // паттерн должен быть простым именем
<[ match (current)
..$body ]>
}
else
<[ match (current)
{
| $Pattern => $body
| _ => ()
} ]>;
}
}
А>module Common
А>{
А> MakeForEachBody(Pattern : Pattern, body : Expr, current)
А> {
А> <[ match (current)
А> ..$body ]>
...
А> }
А> else
А> <[ match (current)
...
А>
Смотри внимательно. Вот первая цитата:
<[
def arr = $Collection;
for (mutable i = 0; i < arr.Length; i++)
{
def current = arr[i];
$(Common.MakeForEachBody(Pattern, Body));
}
]>
она генерирует цикл внутри которого объявляется переменная current. Внутри этой цитаты вызывается функция MakeForEachBody, которая генерирует и возвращает оставшуюся часть кода тела цикла.
Так как обе цитаты раскрываются в одном контексте, то они оперируют именами с одинаковым цветом. Это позволяет "обращаться" из кода генерируемого одними цитатами к переменным генерируемым другими цитатами. В то же время если в коде будут присутствовать другие макросы, то имена сгенерированные в них не будет пересекаться с именами из текущего макроса. Это и называется гигиеной.
В Н2 будет использоваться система гигиены похожая на немерловую (но не факт, что аналогичная).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.