Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 20.11.07 09:28
Оценка:
Подскажите, пожалуйста, где в исходном коде компилятора можно найти пример (образец) для subj'а?
Re: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.07 13:42
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>Подскажите, пожалуйста, где в исходном коде компилятора можно найти пример (образец) для subj'а?


А что за задача? Что нужно сделать?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 20.11.07 14:13
Оценка:
Здравствуйте, VladD2, Вы писали:

...

VD>А что за задача? Что нужно сделать?


Есть множество бизнес классов, с которыми пользователь будет работать через интерфейс на WinForms — отображение в GridView, биндинг свойств в контролы, с возможностью отменять ввод с показом значения свойства до его изменения (что и предоставляет этот интерфейс). Реализовывать интерфейс в каждом классе не хочется по причине лени, а как решить задачу без макросов — не знаю, с макросами, впрочем, тоже .
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[3]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.07 14:51
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>Есть множество бизнес классов, с которыми пользователь будет работать через интерфейс на WinForms — отображение в GridView, биндинг свойств в контролы, с возможностью отменять ввод с показом значения свойства до его изменения (что и предоставляет этот интерфейс). Реализовывать интерфейс в каждом классе не хочется по причине лени, а как решить задачу без макросов — не знаю, с макросами, впрочем, тоже .


Ясно. Тогда советую посмотреть на две вещи.
1. В файле http://nemerle.org/svn/nemerle/trunk/macros/DesignPatterns.n есть макрос ProxyPublicMembers. Он позволяет "перемапить" реализацию из внешнего объекта на некий другой. По стуи реализация паттерна Прокси.
2. Посмотреть на то как похожая на твою задача решается в коде компилятора. Напеример, макрос ManagerAccess из файла http://nemerle.org/svn/nemerle/trunk/macros/compiler.n добавляет некий набор методов (причем гибко, так как в него передается код и в зависимости от его наличия генерируется разная раелизация свойства Manager) к классам к которым применяется данный макро-атрибут. Просто сделай поиск слова ManagerAccess по файлам компилятора и увидишь как он применяется.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 22.11.07 09:36
Оценка:
Здравствуйте, VladD2, Вы писали:

...

Вот что вышло:

[Nemerle.MacroUsage (Nemerle.MacroPhase.WithTypedMembers,
                       Nemerle.MacroTargets.Class,
                       Inherited = false, AllowMultiple = false)]
    public macro Editable(par : TypeBuilder) 
    {
      EditableHelper.Do(par);
    }
    
    internal module EditableHelper
    {
      internal Do(par : TypeBuilder) : void
      {
        def isIField(x)                    
        {
          | _ : IField => true
          | _ => false 
        }
        
        def fields = $[ x | x in par.GetFields (BindingFlags.Instance | BindingFlags.Public |
                            BindingFlags.NonPublic | BindingFlags.DeclaredOnly),
                        x.IsMutable, isIField(x)];                    
        mutable prs = [];                    
        foreach (x in fields) 
        {
          def n = Macros.UseSiteSymbol (x.Name);
          prs = <[ decl: public mutable $(n : name) : $(x.GetMemType () : typed); ]>
            :: prs;
        }
             
        def st = par.DefineNestedType (<[ 
          decl:
          struct Storage 
          {
            ..$prs
          }
          ]>);
        st.Compile();
          
        par.Define (<[ 
            decl:
            mutable _st : Storage;
        ]>);
        
        par.Define (<[ 
          decl:
          mutable _inTxn : bool = false;
        ]>);
      
        mutable move2st = [];
        foreach(x in fields)
        {
          def n = Macros.UseSiteSymbol (x.Name);
          move2st = <[ _st.$(n : name) = this.$(n : name) ]> :: move2st;
        }
      
        par.Define (<[ 
          decl:
          public BeginEdit() : void 
          {   
             when (!_inTxn)
             {
               _st = Storage();
               {.. $move2st};
              _inTxn = true;
             }
            ()     
           }
        ]>);
     
        mutable move2obj = [];
        foreach(x in fields)
        {
          def n = Macros.UseSiteSymbol (x.Name);
          move2obj = <[ this.$(n : name) = _st.$(n : name) ]> :: move2obj;
        }
        
        par.Define (<[ 
          decl:
          public CancelEdit() : void
          {
            when (_inTxn)
            {
               {.. $move2obj};
             _inTxn = false;
            }
          }
        ]>); 
     
       par.Define (<[ 
         decl:
         public EndEdit() : void 
         {
           when (_inTxn)
           {
             _inTxn = false;
           }
           ()
         }
       ]>);
      }
    }


Тест:

[Editable()]
public class A
{
  mutable code : string;
  public rn : long;
  public Code : string {get {code} set {code = value} }
  public Name : string {get; set;  }
  public this( Rn : long )
  {
    this.rn = Rn;
  }
  
  public override ToString() : string
  {
    $"code:$(code); rn:$(rn): Name:$(Name)"
  }
  
  public static Main() : void
  {
   def a = A(1L);
   
   a.Code = "code";
   a.Name = "name";
   WriteLine($"BEGIN:\n $a");
   
   a.BeginEdit();
   a.Code = "___";
   a.Name = "++++";
   WriteLine($"After BeginEdit() and before CancelEdit():\n $a");
   
   a.CancelEdit();
   WriteLine($"After CancelEdit():\n $a");
   
   a.BeginEdit();
   a.Code = "___";
   a.Name = "++++";
   WriteLine($"After BeginEdit() and before CancelEdit():\n $a");   
   a.EndEdit();
   WriteLine($"After EndEdit():\n $a");
   
   WriteLine("END.\n");
   
   _ = ReadLine();
  }
}



Что не вышло — указать в макросе, что объект реализует интерфейс IEditableObject. Просьба, ревизировать код и указать способы его улучшения, и сказать, как же, все таки, "подмешать" в тип IEditableObject.
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[5]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 09:43
Оценка: 2 (1)
Здравствуйте, ecinunice, Вы писали:

E>Что не вышло — указать в макросе, что объект реализует интерфейс IEditableObject.


Это надо делать на шаге компиляции MacroPhase.BeforeInheritance. Так что просто объяви еще один макрос с тем же именем, но укажи у него MacroPhase.BeforeInheritance. В нем ты сможешь задать базовый интерфейс для класса.

E> Просьба, ревизировать код и указать способы его улучшения, и сказать, как же, все таки, "подмешать" в тип IEditableObject.


Это чуть позже. Времени нет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 10:26
Оценка: 3 (1)
Здравствуйте, ecinunice, Вы писали:

Не удержался и посмотрел .

В общем, все ОК. Могу только указать на два незначительных момента.

1. Смысла в функции isIField нет, так как тоже самое можно сделать выражением is, т.е. вместо:
isIField(x)

можно писать
x is IField

Так же (хотя это уже полнейшая вкусовщина) вместо лист-компрехеншон:
def fields = $[ x | x in par.GetFields (BindingFlags.Instance | BindingFlags.Public |
                                        BindingFlags.NonPublic | BindingFlags.DeclaredOnly),
                                        x.IsMutable, isIField(x)];

в таком простом случае использовал бы фунцию Filter:
def flags = BindingFlags.Instance | BindingFlags.Public 
            | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
def fields = par.GetFields(flags).Filter(x => x.IsMutable && x is IField);

Да, и вообще какой смысл проверять реализацию IField, если GetFields возвращает list[IField]?

Вместо конструкций foreach:
mutable prs = [];                    
foreach (x in fields) 
{
    def n = Macros.UseSiteSymbol (x.Name);
    prs = <[ decl: public mutable $(n : name) : $(x.GetMemType () : typed); ]>
        :: prs;
}

лучше применять фунцию Map, так как при этом с одной стороны более понятно что происходит, а с другой отсуствует изменяемые переменные, что сокращает количество моест в которых можно допустить ошибки:
def prs = fields.Map(fun(x) {
        def n = Macros.UseSiteSymbol (x.Name);
        <[ decl: public mutable $(n : name) : $(x.GetMemType () : typed); ]>
    });

Даже... более правильным было бы сделать более специализированню версию Map-а, так как похожий код используется многократно:
def makeExprs[T](fields, getExpr : Name -> T)
{
    fields.Map(x => getExpr(Macros.UseSiteSymbol(x.Name)))
}

def prs = makeExprs(fields, n => <[ decl: public mutable $(n : name) : $(x.GetMemType () : typed); ]>);
...
def move2st = makeExprs(fields, n => <[ _st.$(n : name) = this.$(n : name) ]>);

Не знаю какой точно тип у имени (я подставил Name, но возможно ParsedName). Это надо подсмотреть в компиляторе.
Обобщенной функцию makeExprs надо делать так как она должна работать с разными типами квази-цитирования. Это обуславливает и необходимость явно описывать функцию getExpr.

ЗЫ

Все это мелочи. Это хороший пример применения макросов!

Если не сикрет какой опыт работы с Nemerle? И что было прочитано перед началом работы?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 22.11.07 11:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, ecinunice, Вы писали:


VD>Не удержался и посмотрел .


Спасибо, буду впитывать правильную культуру разработки .

VD>в таком простом случае использовал бы фунцию Filter:

VD>
//...
VD>def fields = par.GetFields(flags).Filter(x => x.IsMutable && x is IField);
// Я пытался сделать подобное через list comprehension, но и там и здесь интеграция выдает 
// warning    -    using the ''is'' pattern here is redundant, please use '':'', 
// с  использованием которго компилятор уже ругается (ver 0:9:3:7840)  
VD>

VD>Да, и вообще какой смысл проверять реализацию IField, если GetFields возвращает list[IField]?
Безумно скопировано мной с http://nemerle.org:81/Macros_tutorial#Manipulating_type_declarations.

VD>ЗЫ


VD>Если не сикрет какой опыт работы с Nemerle? И что было прочитано перед началом работы?


Интерес к языку возник достаточно давно — с момента обсуждения языка на rsdn. В конце лета, начало осени была предпринята попытка конструктивного
ознакомления с языком через критическое рассмотрение статей с rsdn + nemerle.org в составе рабочей группы, что привело в условиях возникновения новых прикладных задач и наличия сентябрьского CTP интеграции к возможности практического применения языка , вылившиеся в маленькой утилите WinForms + БД + бизнесс логика, работы над которой заняли ~ 2 последние недели. Сейчас стоят задачи создания офлайнового клиента и сайта, обе будут делаться на N.

Если проще, то читал, думал, начал писать. Наличие автодополнения, списков и локальных функций само по себе дает огромный эффект, но всегда хочеться большего . От AOP я "вообще" в диком восторге — оно сразу дает легкий и прозрачный инструмент для решения целого ряда проблем.
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[7]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 12:34
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>От AOP я "вообще" в диком восторге — оно сразу дает легкий и прозрачный инструмент для решения целого ряда проблем.


Под AOP имеется в виду это?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 12:36
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>Интерес к языку возник достаточно давно — с момента обсуждения языка на rsdn. В конце лета, начало осени была предпринята попытка конструктивного

E>ознакомления с языком через критическое рассмотрение статей с rsdn + nemerle.org в составе рабочей группы, что привело в условиях возникновения новых прикладных задач и наличия сентябрьского CTP интеграции к возможности практического применения языка , вылившиеся в маленькой утилите WinForms + БД + бизнесс логика, работы над которой заняли ~ 2 последние недели. Сейчас стоят задачи создания офлайнового клиента и сайта, обе будут делаться на N.

А до этого какой опыт был?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 22.11.07 13:24
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, ecinunice, Вы писали:


E>>От AOP я "вообще" в диком восторге — оно сразу дает легкий и прозрачный инструмент для решения целого ряда проблем.


VD>Под AOP имеется в виду это?

Да.
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[8]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 22.11.07 13:24
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, ecinunice, Вы писали:


E>>Интерес к языку возник достаточно давно — с момента обсуждения языка на rsdn. В конце лета, начало осени была предпринята попытка конструктивного

E>>ознакомления с языком через критическое рассмотрение статей с rsdn + nemerle.org в составе рабочей группы, что привело в условиях возникновения новых прикладных задач и наличия сентябрьского CTP интеграции к возможности практического применения языка , вылившиеся в маленькой утилите WinForms + БД + бизнесс логика, работы над которой заняли ~ 2 последние недели. Сейчас стоят задачи создания офлайнового клиента и сайта, обе будут делаться на N.

VD>А до этого какой опыт был?

Полтора года на Delphi в рамках софтверной компании, затем столько же на C#.

PS: Есть способы обхождения вот таких препятсвий?
C:\Program Files\Nemerle\Nemerle.MSBuild.targets(173,9):Error: Internal compiler error, please report a bug to bugs.nemerle.org. You can try modifying program near this location.
C:\Program Files\Nemerle\Nemerle.MSBuild.targets(173,9):Error: internal compiler error: assertion failed in file ncc\external\LibrariesLoader.n, line 467:
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[9]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 14:49
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>PS: Есть способы обхождения вот таких препятсвий?

E>C:\Program Files\Nemerle\Nemerle.MSBuild.targets(173,9):Error: Internal compiler error, please report a bug to bugs.nemerle.org. You can try modifying program near this location.
E>C:\Program Files\Nemerle\Nemerle.MSBuild.targets(173,9):Error: internal compiler error: assertion failed in file ncc\external\LibrariesLoader.n, line 467:

Описываешь ошибку в багтрекере и ждешь когда ее пофиксят.
А что за ошибка, то?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Реализация IEditableObject через макросы?
От: ecinunice  
Дата: 22.11.07 15:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А что за ошибка, то?

К сожаленью, я не могу привести простой, воспроизводимый пример — в текущем проекте написал extension method для FirebirdSql.Data.FirebirdClient.FbCommand, которые возвращают bool * DbParameter, они и валят компилятор.
... << RSDN@Home 1.2.0 alpha rev. 737>>
Re[11]: Реализация IEditableObject через макросы?
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.07 16:13
Оценка:
Здравствуйте, ecinunice, Вы писали:

E>К сожаленью, я не могу привести простой, воспроизводимый пример — в текущем проекте написал extension method для FirebirdSql.Data.FirebirdClient.FbCommand, которые возвращают bool * DbParameter, они и валят компилятор.


Возможно это как-то связано с этим багом?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.