в квази цитатах периодически встречаются такие кострукции:
def ftype = f.GetMemType();
def fobj = <[ this.$(f.Name : dyn) ]>;
или
match(arg) {
| <[ $(field : name) = $value ]> => (field, value) :: acc
что они означают ? или ли другие аналогичные конструкции??
Здравствуйте, Jack128, Вы писали:
J>в квази цитатах периодически встречаются такие кострукции:
J>J> def ftype = f.GetMemType();
J> def fobj = <[ this.$(f.Name : dyn) ]>;
J>
Конкретно эта цитата просто бредовая. Я даже не сразу это заметил. Переменная ftype в коде вообще не используется.
Чтобы сказать об этом коде большее нужно знать тип f. По всей видимости — это такой не очень красивый способ обратиться к полю или свойству ссылка на который лежит в f.
J>или
J>J> match(arg) {
J> | <[ $(field : name) = $value ]> => (field, value) :: acc
J>
С этим все проще. Здесь компилятору указывается, что field — это имя некой переменной или поля. Соответственно это вхождение сопоставится только, если в левой части выражения находится ссылка на имя, а field будет связано с этим именем (имя описывается типом Name). Уточнение " : name" как раз и подсказывает компилятору что программист хочет получить именно ссылку на переменную, а не какое-то иное выражение.
Чтобы было понятнее этот паттерн можно переписать так:
match(arg)
{
| <[ $(PExpr.Ref(field)) = $value ]> => (field, value) :: acc
или даже так:
match(arg)
{
| PExpr.Assign(PExpr.Ref(field), value) => (field, value) :: acc
это если вообще без квази-цитирования.
Если же сделать цитату без " : name":
match(arg)
{
| <[ $field = $value ]> => (field, value) :: acc
то она будет рассматриваться как:
match(arg)
{
| PExpr.Assign(field, value) => (field, value) :: acc
и соответственно field будет иметь тип PExpr, а выражение может быть любым допустимым выражением немерла.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Jack128, Вы писали:
J>>в квази цитатах периодически встречаются такие кострукции:
J>>J>> def ftype = f.GetMemType();
J>> def fobj = <[ this.$(f.Name : dyn) ]>;
J>>
VD>Конкретно эта цитата просто бредовая. Я даже не сразу это заметил. Переменная ftype в коде вообще не используется.
VD>Чтобы сказать об этом коде большее нужно знать тип f. По всей видимости — это такой не очень красивый способ обратиться к полю или свойству ссылка на который лежит в f.
Я откуда то из снипетов или из макросов стандартных выдрал.
Ну вот еще пример
http://code.google.com/p/nemerleonrails/source/browse/NRails.Macros/Mvc/ViewModel.n
def controller: string = ....
def build_code(model_ty) {
def ctor_args = args.Map( ((name, value)) => <[ $(name : name) = $value ]> );
<[
ViewModels.$(controller : dyn).$(model_ty.Name : dyn)( ..$ctor_args );
]>
}
еще есть usesite
http://code.google.com/p/nemerle/source/browse/nemerle/trunk/macros/AnonymousClass.n
def members = fields.Map(field => <[ decl :
[Nemerle.Utility.Accessor($(field.PropertyName : usesite))]
private $(field.FieldName : usesite) : $(field.GenericArg : name);
]>);
почему здесь используется usesite для поля, а не name ?
Здравствуйте, Jack128, Вы писали:
J>Я откуда то из снипетов или из макросов стандартных выдрал.
J>Ну вот еще пример http://code.google.com/p/nemerleonrails/source/browse/NRails.Macros/Mvc/ViewModel.n
J>J> def controller: string = ....
J> def build_code(model_ty) {
J> def ctor_args = args.Map( ((name, value)) => <[ $(name : name) = $value ]> );
J> <[
J> ViewModels.$(controller : dyn).$(model_ty.Name : dyn)( ..$ctor_args );
J> ]>
J> }
J>
Очевидно товарищу было в лом разбираться в тонкостях задания имен и он пошел по самому простому пути. Это может привести к конфликту имен.
Вообще. С именами в макрах немерла порой не просто разобраться. Ото одна из шероховатостей. В 2.0 попробуем сделать по проще (по внятнее).
А вообще — это формирование вызова конструктора.
"dyn" означает — программист просит компилятор подобрать имя так чтобы оно совпадало с таким же уже имеющимся именем. По идее вместо dyn обычно можно применять usesite. Это более правильный подход. Но бывает, так что это не прокатывает. Программист не может понять почему это происходит и чтобы не возиться использует dyn.
J>еще есть usesite http://code.google.com/p/nemerle/source/browse/nemerle/trunk/macros/AnonymousClass.n
J>J>def members = fields.Map(field => <[ decl :
J> [Nemerle.Utility.Accessor($(field.PropertyName : usesite))]
J> private $(field.FieldName : usesite) : $(field.GenericArg : name);
J> ]>);
J>
J>почему здесь используется usesite для поля, а не name ?
name (т.е. тип Name) хранит информацию о цветах. Плюс он еще может хранить информацию о местоположении. Здесь же генерируется поле. Ему нужно дать цвет такой же какой имеет остальной код в месте применения. Так что использование usesite, в данном случае, является правильным решением. Но в принципе здесь же прокатил бы и dyn.
Если есть выбор, то нужно использовать name. Если цвет в имени не подходит, то нужно использовать usesite. А если ничего не помогает, то dyn.
Здравствуйте, Jack128, Вы писали:
J>что такое "цвет имени" ??
Прочитай часть
макро-самоучителя посвященную гигиеничности макросов.
В двух словах, чтобы не иметь тех проблем с пересечением имен какие есть в препроцессоре С, в макросах немрела используется так называемая гигиеничность. Имя генерируемое в рамках макроса получает некий идентификатор (уникальный для всех раскрытий макросов в рамках одного процесса компиляции/сеанса работы в IDE). Этот идентификатор называется "цветом имени". Иногда нужно обойти эту гигиеничность, например, чтобы сгенерировать обращение к полую класса объявленного программистом или другим макросом. Вот тут и вступает в действие магические usesite, dyn и т.п.