Здравствуйте, PhantomIvan, Вы писали:
PI>1. В какой форум писать вопросы по немерле?
В Декларативное программирование. Ну или сюда
если speak English или mowie po polsku.
Здравствуйте, PhantomIvan, Вы писали:
PI>макрос $"..." очевидно, раскрывается в момент компиляции PI>а есть ли возможность перенести это раскрытие в рантайм?
В Nemerle макрос — не более чем обычный класс, реализующий интерфейс IMacro. Этот класс принимает на вход кусок AST, а на выход выдаёт другой кусок AST. Соответственно, вызывать макрос в рантайме можно, но смысла в этом особого нет — что ты потом с этим куском AST делать будешь? "Всунуть" его куда-то в уже выполняемый код ты не сможешь...
Поэтому в Nemerle макросы используются (т.е. вызываются) только на этапе компиляции, когда на руках ещё есть код в виде AST, а не в виде инструкций CIL. В общем-то, вполне резонно для языка со статической типизацией.
Здравствуйте, Oyster, Вы писали:
O>В Nemerle макрос — не более чем обычный класс, реализующий интерфейс IMacro. Этот класс принимает на вход кусок AST, а на выход выдаёт другой кусок AST. Соответственно, вызывать макрос в рантайме можно, но смысла в этом особого нет — что ты потом с этим куском AST делать будешь? "Всунуть" его куда-то в уже выполняемый код ты не сможешь...
O>Поэтому в Nemerle макросы используются (т.е. вызываются) только на этапе компиляции, когда на руках ещё есть код в виде AST, а не в виде инструкций CIL. В общем-то, вполне резонно для языка со статической типизацией.
это все понятно, но давайте все-таки попробуем
я хочу переписать программу, скажем, так:
def l = '\\';
def q = '\"';
def b = '\$';
def n = '\n';
screw def s = " def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n screw def s = $q$s$q;$n$n def introspect()$n {$n System.Console.WriteLine(nut s);$n }$n$n introspect();";
def introspect()
{
System.Console.WriteLine(nut s);
}
introspect();
но он не хочет вставить такую простую вещь как sprint($"... bla bla bla ...") в код в месте вызова последнего макроса
ох уж эта гигиена... пишет вот что:
Screwing variable [ s ]
Nutting variable [ s ]
Screwing variable [ s ]
self3.n:5:2:5:7: [01;33mwarning[0m: variable has been already screwed!
Nutting variable [ s ]
self3.n:9:28:9:31: [01;31merror[0m: unbound name `l'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `l'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `l'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `q'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `l'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `b'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:29: [01;31merror[0m: unbound name `l'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `q'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `s'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `q'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
self3.n:9:28:9:31: [01;31merror[0m: unbound name `n'
ну допустим гигиена, ладно, ну а как тогда все же извратиться
Здравствуйте, PhantomIvan, Вы писали:
PI>ну допустим гигиена, ладно, ну а как тогда все же извратиться
Честно говоря, я в коде практически ничего не понял Зато могу сказать, как избавиться от гигиены:
// Наш макрос, который не любит гигиену
macro MeDontWashHands()
{
<[ $("x" : dyn) = 1; ]>
}
// ...
// Тут в x попадёт единичка
mutable x = 7;
MeDontWashHands();
System.Console.WriteLine(x);
Здравствуйте, Oyster, Вы писали:
O>Честно говоря, я в коде практически ничего не понял
так я объясню с удовольствием, а что непонятно
O>Ещё можно почитать Re[5]: Критика Nemerle
— там рассказывается, как можно во всём выражении сразу задавить гигиену.
тот способ не помог, зато я все же разобрался со встроенным sprint-ом
и сделал так:
это я его фактически переписал внутрь моего макра
а MyHelper.my_make_splice_distribution это из io.n один-в-один
в общем-то прога заработала на ура:
def l = '\\';
def q = '\"';
def b = '\$';
def n = '\n';
screw def s = " def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n screw def s = $q$s$q;$n$n def introspect()$n {$n System.Console.WriteLine(nut s);$n }$n$n introspect();";
def introspect()
{
System.Console.WriteLine(nut s);
}
introspect();
хотя конечно, т.к. я использовал макросы, за полноценное решение исходной задачи это засчитать нельзя
зато подразобрался с макросами
вот возник вопрос в связи с этим:
если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка)
то вроде как возникают проблемы с отключением гигиены...
на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя
он пишет, что мои переменные unbound...
вышеописанным действием я фактически удалил один уровень (stage)
так вот не будут ли с этим проблемы с применением многоуровневой макросистемы в проекте?
Здравствуйте, PhantomIvan, Вы писали:
PI>вот возник вопрос в связи с этим: PI>если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка) PI>то вроде как возникают проблемы с отключением гигиены...
У меня никогда никаких проблем не возникало.
PI>на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя PI>он пишет, что мои переменные unbound...
Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.
PI>вышеописанным действием я фактически удалил один уровень (stage)
Опять не понял но объяснять не надо — я не настроен сегодня на понимание
PI>так вот не будут ли с этим проблемы с применением многоуровневой макросистемы в проекте?
Здравствуйте, Oyster, Вы писали:
O>Здравствуйте, PhantomIvan, Вы писали:
PI>>вот возник вопрос в связи с этим: PI>>если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка) PI>>то вроде как возникают проблемы с отключением гигиены...
O>У меня никогда никаких проблем не возникало.
а сколько у тебя stage-ей было?
PI>>на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя PI>>он пишет, что мои переменные unbound...
O>Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.
нет, особо не улавливаю разницы пока...
вообще в условиях отсутствия нормальной документации, видимо придется изучать сорцы компилятора
чтобы понять как эффективно макросы писать... правда?
сначала хотелось верить что в компилятор особо лезть не нужно будет... впрочем так ведь и не нужно было... пока я до макросов не дошёл
Здравствуйте, PhantomIvan, Вы писали:
PI>а сколько у тебя stage-ей было?
Столько же было.
O>>Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.
PI>нет, особо не улавливаю разницы пока...
Разница очень простая и чёткая: "usesite" не нарушает гигиену (с чего ты взял обратное?), "dyn" нарушает.
PI>вообще в условиях отсутствия нормальной документации, видимо придется изучать сорцы компилятора PI>чтобы понять как эффективно макросы писать... правда?
Ну вообще-то так дела сейчас и обстоят — я очень часто заглядывал в сорцы, когда копался с Nemerle.
Здравствуйте, Oyster, Вы писали:
O>Разница очень простая и чёткая: "usesite" не нарушает гигиену (с чего ты взял обратное?), "dyn" нарушает.
Они оба нарушают гигиену, но с различной "разрушительной силой".
testHygiene(breakHygiene()); // не скомпилируется - unbound name 'n'
testHygiene(completelyBreakHygiene()); // выведет в консоль 1
def n = 2; breakHygiene(); // выведет 2
testHygiene2(); // выведет 3
В каких еще случаях проявляется разница между dyn и usesite я честно говоря не знаю. Но думаю, что они есть. Судя по всему usesite все таки подчиняется каким-то правилам, а вот dyn игнорирует все правила, которые можно игнорировать.
O>Ну вообще-то так дела сейчас и обстоят — я очень часто заглядывал в сорцы, когда копался с Nemerle.
Все зависит от сложности и специфики задачи. Очень часто вполне достаточно заглядывать в сорцы стандартных макросов(это не совсем одно и тоже, что сорцы компилятора ). Да и та документация по макросам, которая есть тоже не совсем бесполезна.