Автоматическая перегрузка функций в избранное  msdn  новое горячее всё    Оценить +1123x:) +-   подписка   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 15.03.08 23:20
Оценка:37 (2)
Как-то давно хотелось сделать макрос, который бы превращал функцию с аргументами по умолчанию в несколько функций.
Это очень удобно для содействия с C# в котором этой возможности нет.

Тест:
Nemerle
using System;
using System.Collections.Generic;
using System.Text;
using MacroLibrary1;
using Nemerle.Compiler;
using Nemerle.Compiler.Typedtree;
using Nemerle.Collections;

namespace ClassLibrary1
{
  public class Class1
  {
    [DefaultArguments]
    public F(x : int = 1, y : string = "a", z : double = 3.3) : void
    {
     System.Console.WriteLine("{0} - {1} - {2}", x, y, z);
    }
    
    [DefaultArguments]
    public F2(x : int = 1, y : string, z : double = 3.3) : void
    {
      System.Console.WriteLine("{0} - {1} - {2}", x, y, z);
    }
  }
}


C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ClassLibrary1;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            new Class1().F();
            new Class1().F(1);
            new Class1().F(2, "a");
            new Class1().F(3, "b", 5.5);

            new Class1().F2(5, "d");
            new Class1().F2(6, "e", 7.5);
        }
    }
}


Макрос:
using Nemerle.Compiler;
using PT = Nemerle.Compiler.Parsetree;
using TT = Nemerle.Compiler.Typedtree;

namespace MacroLibrary1
{
  internal module LiteralExtention
  {
    public ToLiteral(this value : bool)    : PT.PExpr { <[ $(value : bool) ]> }
    public ToLiteral(this value : char)    : PT.PExpr { <[ $(value : char) ]> }
    public ToLiteral(this value : byte)    : PT.PExpr { <[ $(value : byte) ]> }
    public ToLiteral(this value : sbyte)   : PT.PExpr { <[ $(value : sbyte) ]> }
    public ToLiteral(this value : short)   : PT.PExpr { <[ $(value : short) ]> }
    public ToLiteral(this value : ushort)  : PT.PExpr { <[ $(value : ushort) ]> }
    public ToLiteral(this value : int)     : PT.PExpr { <[ $(value : int) ]> }
    public ToLiteral(this value : uint)    : PT.PExpr { <[ $(value : uint) ]> }
    public ToLiteral(this value : long)    : PT.PExpr { <[ $(value : long) ]> }
    public ToLiteral(this value : ulong)   : PT.PExpr { <[ $(value : ulong) ]> }
    public ToLiteral(this value : float)   : PT.PExpr { <[ $(value : float) ]> }
    public ToLiteral(this value : double)  : PT.PExpr { <[ $(value : double) ]> }
    public ToLiteral(this value : decimal) : PT.PExpr { <[ $(value : decimal) ]> }
    public ToLiteral(this value : string)  : PT.PExpr { <[ $(value : string) ]> }
    
    public ToPExpr(this lit : Literal, arg : TT.Fun_parm) : PT.PExpr
    {
      match(lit)
      {
      | p is Literal.Bool => p.val.ToLiteral()
      | p is Literal.Char => p.val.ToLiteral()
      
      // HACK: Nemerle.Compiler.Literal.Integer.val has type of ulong !
      // HACK: Here we get the real literal's type.
      | p is Literal.Integer =>
        if(arg.SystemType.Equals(typeof(byte)))
          (p.val :> byte).ToLiteral();
        else
        if(arg.SystemType.Equals(typeof(sbyte)))
          (p.val :> sbyte).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(short)))
          (p.val :> short).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(ushort)))
          (p.val :> ushort).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(int)))
          (p.val :> int).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(uint)))
          (p.val :> uint).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(long)))
          (p.val :> long).ToLiteral()
        else
        if(arg.SystemType.Equals(typeof(ulong)))
          (p.val : ulong).ToLiteral()
        else
        {
          Message.Error("Unsupported integral type");
          <[ ]>
        }
      | p is Literal.Float => p.val.ToLiteral()
      | p is Literal.Double => p.val.ToLiteral()
      | p is Literal.Decimal => p.val.ToLiteral()
      | p is Literal.String => p.val.ToLiteral()
      | _ => Message.Error("Unsupported literal type"); <[ ]>
      }
    }
  }
  
  [Nemerle.MacroUsage(Nemerle.MacroPhase.WithTypedMembers
                    , Nemerle.MacroTargets.Method)]
  public macro DefaultArguments(tb : TypeBuilder, mb : MethodBuilder, params opts : list[PExpr])
  {
    DefaultArgumentsImpl.DefaultArguments(tb, mb, opts);
  }
        
  internal module DefaultArgumentsImpl
  {
    public DefaultArguments(tb : TypeBuilder, mb : MethodBuilder, _opts : list[Parsetree.PExpr]) : void
    {
      def newName(name) { tb.ParsedName.NewName(name) }
      
      def create(args, cur)
      {
        match(cur)
        {
        | x when x == -1 => ()
        | _ =>
          // Check for default value
          def curArg = args.Nth(cur);
          when(curArg.HasDefaultValue)
          {
            def mparms = args.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
            def fparms = mparms.Map(Parsetree.Fun_parm);

            def call = mparms + [(curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val.ToPExpr(curArg)];

            // Create a new method
            tb.Define
            (<[ decl:
                public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
                {
                    this.$(mb.Name : dyn)(..$call)
                }
            ]>);
            
            create(args, cur - 1);
          }
        }
      }
      
      // Create methods
      def parms = mb.GetParameters();
      create(parms, parms.Length - 1);
      
      // Remove the default arguments to avoid ambiguity
      parms.Iter(x => x.default_value = option[Nemerle.Compiler.Typedtree.TExpr].None());
    }
  }
}


Пока это предварительная версия, улучшения и пожелания принимаются.

P.S.
Спасибо всем, за поддержку
Re: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 16.03.08 10:17
Оценка:12 (1)
Здравствуйте, _nn_, Вы писали:

__>Пока это предварительная версия, улучшения и пожелания принимаются.


Для начала, вот эта конструкция какая-то не внятная:
      def create(args, cur)
      {
        match(cur)
        {
        | x when x == -1 => ()
        | _ =>
          // Check for default value
          def curArg = args.Nth(cur);
        ...
            
            create(args, cur - 1);
          }
        }
      }

С трудом в ней можно угадать банальный цикл. Вот только не ясно зачем так переусложнять.
Разберем по пунктам.
1. Конструкция "args.Nth(cur)" является крайне не эффективной, так как list[T] — это однонаправленный список. Доступ по индексу (коим и является Nth) приводит к перебору cur элементов списка. Надо стараться перебирать списки всегда в прямом направлении.
2. Конструкция:
match(cur)
{
  | x when x == -1 => ()
  | _ => ...
}

аналогична конструкции:
when (x != -1)
  ...

или
unless (x == -1)
  ...

3. Если нужен цикл который делает некие императивные действия (вроде добавления методов, то наверно лучше и воспользоваться циклом или методами Iter/IterI). В данном случае, наверное, лучше всего подошел бы IterI:
args.IterI(0, (cur, curArg) =>
  when(curArg.HasDefaultValue)
  {
    def mparms = args.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
    def fparms = mparms.Map(Parsetree.Fun_parm);

    def call = mparms + [(curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val.ToPExpr(curArg)];

    // Create a new method
    tb.Define
      (<[ decl:
        public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
        {
          this.$(mb.Name : dyn)(..$call)
        }
     ]>)
  });
Re: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 16.03.08 11:16
Оценка:12 (1)
Здравствуйте, _nn_, Вы писали:

Вот этот код тоже надо прокомментировать:
__>
__>    public ToPExpr(this lit : Literal, arg : TT.Fun_parm) : PT.PExpr
__>    {
__>      match(lit)
__>      {
__>      | p is Literal.Bool => p.val.ToLiteral()
__>      | p is Literal.Char => p.val.ToLiteral()
      
__>      // HACK: Nemerle.Compiler.Literal.Integer.val has type of ulong !
__>      // HACK: Here we get the real literal's type.
__>      | p is Literal.Integer =>
__>        if(arg.SystemType.Equals(typeof(byte)))
__>          (p.val :> byte).ToLiteral();
__>        else
__>        if(arg.SystemType.Equals(typeof(sbyte)))
__>          (p.val :> sbyte).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(short)))
__>          (p.val :> short).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(ushort)))
__>          (p.val :> ushort).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(int)))
__>          (p.val :> int).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(uint)))
__>          (p.val :> uint).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(long)))
__>          (p.val :> long).ToLiteral()
__>        else
__>        if(arg.SystemType.Equals(typeof(ulong)))
__>          (p.val : ulong).ToLiteral()
__>        else
__>        {
__>          Message.Error("Unsupported integral type");
__>          <[ ]>
__>        }
__>      | p is Literal.Float => p.val.ToLiteral()
__>      | p is Literal.Double => p.val.ToLiteral()
__>      | p is Literal.Decimal => p.val.ToLiteral()
__>      | p is Literal.String => p.val.ToLiteral()
__>      | _ => Message.Error("Unsupported literal type"); <[ ]>
__>      }
__>    }
__>  }
  __>


1. Literal — это вариант, а стало быть его значения не надо проверять по "is" (т.е. "p is Literal.Bool"). Вместо этого его можно просто описывать образцом "конструктор". Вместо
| p is Literal.Bool => p.val.ToLiteral()
| p is Literal.Char => p.val.ToLiteral()

можно писать:
| Literal.Bool(val) => val.ToLiteral()
| Literal.Char(val) => val.ToLiteral()

или даже:
| Bool(val) => val.ToLiteral()
| Char(val) => val.ToLiteral()

так как название варианта можно опускать если тип аргумента соответствует этому типу.
2. Literal содержится в PExpr следующим образом:
  public variant PExpr : Located 
  { 
    ...
    | Literal         { val : Nemerle.Compiler.Literal; } 
    ...

Таким образом, чтобы преобразовать литерал в PExpr достаточно написать "PExpr.Literal(lit)".
Естественно, что создавать для этого метод излишне. Нужно просто переписать строчку:
def call = mparms + [(curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val.ToPExpr(curArg)];

следующим образом:
def call = mparms + [PT.PExpr.Literal((curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val)];


Кстати, в Немерле параметры могут быть ref/out, а значения по умолчанию могут быть заданы не только у последних параметров, но и у любых других (для вызова можно обращаться к значениям параметров по именам).
Re: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 16.03.08 11:19
Оценка:1 (1)
Здравствуйте, _nn_, Вы писали:

Вот так сложно:
x.default_value = option[Nemerle.Compiler.Typedtree.TExpr].None()

тоже писать не надо. Можно так:
x.default_value = None()
Re[2]: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 16.03.08 22:44
Здравствуйте, VladD2, Вы писали:

VD>1. Конструкция "args.Nth(cur)" является крайне не эффективной, так как list[T] — это однонаправленный список. Доступ по индексу (коим и является Nth) приводит к перебору cur элементов списка. Надо стараться перебирать списки всегда в прямом направлении.


Это я знаю.
Проблема в том, что мне нужно делать перебор с конца, т.к. как только есть аргумент без значения по умолчанию смысла в перегрузки нет.
Если же конечно не изменить логику макроса:

[DefaultArguments]
public F(a : int = 1, b : int, c : int = 2) {}


Сейчас:
public F(a : int, b : int) { F(a, b, 2} }
public F(a : int, b : int, c : int) {}


Другая логика:
public F(a : int, b : int) { F(a, b, 2} }
public F(b : int) {F(1, b, 2) }
public F(a : int, b : int, c : int) {}


Вопрос насколько такое поведение очевидно и удовлетворит пользователя макросом.


VD>3. Если нужен цикл который делает некие императивные действия (вроде добавления методов, то наверно лучше и воспользоваться циклом или методами Iter/IterI). В данном случае, наверное, лучше всего подошел бы IterI:

К сожалению на официальном сайте узнать о всех методах невозможно. Object Browser помогает
А хотя очень нужно было бы обновить страницу на сайте или хотя бы выложить файл со списком всех классов и методов
Re[3]: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 17.03.08 09:10
Здравствуйте, _nn_, Вы писали:

__>Проблема в том, что мне нужно делать перебор с конца, т.к. как только есть аргумент без значения по умолчанию смысла в перегрузки нет.


Какая разница как перебирать? В Nemerle параметры со значениями по умолчанию могут быть в любом параметре.
К тому же можно воспользоваться вункцией Rev() переворачивающей список.

VD>>3. Если нужен цикл который делает некие императивные действия (вроде добавления методов, то наверно лучше и воспользоваться циклом или методами Iter/IterI). В данном случае, наверное, лучше всего подошел бы IterI:

__>К сожалению на официальном сайте узнать о всех методах невозможно. Object Browser помогает

Можно просто пользоваться списком выподающем при комплите. Там же и подсказки есть (если релиз используется).

__>А хотя очень нужно было бы обновить страницу на сайте или хотя бы выложить файл со списком всех классов и методов


Я никогда туда не заглядывал.
Re[2]: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 19.03.08 22:23
Здравствуйте, VladD2, Вы писали:

VD>3. Если нужен цикл который делает некие императивные действия (вроде добавления методов, то наверно лучше и воспользоваться циклом или методами Iter/IterI). В данном случае, наверное, лучше всего подошел бы IterI:

VD>
args.IterI(0, (cur, curArg) =>
VD>  when(curArg.HasDefaultValue)
VD>  {
VD>    def mparms = args.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
VD>    def fparms = mparms.Map(Parsetree.Fun_parm);

VD>    def call = mparms + [(curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val.ToPExpr(curArg)];

VD>    // Create a new method
VD>    tb.Define
VD>      (<[ decl:
VD>        public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
VD>        {
VD>          this.$(mb.Name : dyn)(..$call)
VD>        }
VD>     ]>)
VD>  });
VD>


Что-то не работает:
      def newName(name) { tb.ParsedName.NewName(name) }
      
      def parms = mb.GetParameters();
      parms.IterI(0,
        (cur, curArg) => 
        {
          when(cur != parms.Length - 1)
            if(curArg.HasDefaultValue)
            {
              def mparms = parms.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
              def fparms = mparms.Map(Parsetree.Fun_parm);

              def call = mparms + [PT.PExpr.Literal((curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val)];
              
              tb.Define
              (<[ decl:
                  public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
                  {
                      this.$(mb.Name : dyn)(..$call)
                  }
              ]>);
            }              
            else
              ()
          });


Почему-то не создаются методы.

А так работает:
      def newName(name) { tb.ParsedName.NewName(name) }
      
      def create(args, cur)
      {
        when(cur != -1)
        {
          def curArg = args.Nth(cur);
          if(curArg.HasDefaultValue)
          {
            def mparms = args.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
            def fparms = mparms.Map(Parsetree.Fun_parm);

            def call = mparms + [PT.PExpr.Literal((curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val)];
            
            tb.Define
            (<[ decl:
                public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
                {
                    this.$(mb.Name : dyn)(..$call)
                }
            ]>);
            
            create(args, cur - 1);
          }              
          else
            ()
        }
      }
      
      def parms = mb.GetParameters();
      create(parms, parms.Length - 1);


Получается, что все таки есть разница между IterI и функцией ?
Re[3]: Автоматическая перегрузка функций в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 20.03.08 12:27
Здравствуйте, _nn_, Вы писали:

__>Почему-то не создаются методы.


Ну, так запусти из под отладчика и погляди в чем проблема.

ЗЫ

Вот эта проверка:
when(cur != parms.Length - 1)

Снижает производительность (при обращении к свойству Length списка каждый раз происходит перебор всего списка).

И вообще, ты тут что-то странное выделываешь. Просто разверни список и возьми его хвост. Код будет примерно таким:
def newName(name) { tb.ParsedName.NewName(name) }

args.Reverse().Tail.IterI(0, (cur, value) => 
  when (curArg.HasDefaultValue)
  {
    def mparms = args.FirstN(cur).Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
    def fparms = mparms.Map(Parsetree.Fun_parm);
    def call = mparms + [PT.PExpr.Literal((curArg.DefaultValueAsTExpr() :> TT.TExpr.Literal).val)];
    
    tb.Define
      (<[ decl:
          public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
          {
              this.$(mb.Name : dyn)(..$call)
          }
      ]>);
  });
Re: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 07.04.08 18:47
Здравствуйте, _nn_, Вы писали:

Вторая и улучшенная версия.

C# тест:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ClassLibrary1;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            new Class1().F();
            new Class1().F(1);
            new Class1().F(2, "a");
            new Class1().F(3, "b", 3);

            new Class1().F2('q', 5, "d");
            new Class1().F2('q', 6, "e", 7.5);
        }
    }
}


Nemerle тест:
using System;
using System.Collections.Generic;
using System.Text;
using MacroLibrary1;
using Nemerle.Compiler;
using Nemerle.Compiler.Typedtree;
using Nemerle.Collections;

namespace ClassLibrary1
{
  public class Class1
  {
    // public F(x : int, y : string, z : byte) : void
    // public F(x : int, y : string) : void
    // public F(x : int) : void
    // public F() : void  
    [DefaultArguments]
    public F(x : int = 1, y : string = "a", z : byte = 9) : void
    {
     System.Console.WriteLine("{0} - {1} - {2}", x, y, z);  
    }
    
    private FTester() : void
    {
      F();
      F(0);
      F(0, "z");
      F(0, "z", 10);
    }
    
    // public F2(a : char, x : int, y : string, z : double) : void
    // public F2(a : char = 'a', x : int, y : string) : void    
    [DefaultArguments]
    public F2(a : char = 'a', x : int = 1, y : string, z : double = 3.3) : void
    {
      System.Console.WriteLine("{0} - {1} - {2} - {3}", a, x, y, z);
    }
    
    private F2Tester() : void
    {
      // TODO: (1) F2(y = "z");
      F2(a = 'x', y = "z", z = 1.0); // 'x' is implied
      F2(y = "z", z = 1.0); // 'a' and 'x' are implied
      F2('x', 0, "z");
      F2('x', 0, "z", 10.0);
    }
  }
}

1: На данный момент недоработка.
В следующей версии постараюсь исправить.

Nemerle Макрос:
using Nemerle.Compiler;
using Nemerle.Imperative;
using PT = Nemerle.Compiler.Parsetree;
using TT = Nemerle.Compiler.Typedtree;

namespace MacroLibrary1
{  
  /// <summary>
  /// Converts function with default arguments into overloaded functions.
  /// </summary>
  ///
  /// <example> One argument
  /// <code>
  /// [DefaultArguments]
  /// public F(a : int = 1) { ... }
  /// =>
  /// public F() { F(1); }
  /// public F(a : int) { ... }
  /// </code>
  /// </example>
  ///
  /// <example> More then one argument
  /// <code>
  /// [DefaultArguments]
  /// public F(a : int = 1, b : char = 'a') { ... }
  /// =>
  /// public F() { F(1, 'a'); }
  /// public F(a: int) { F(a, 'a') }
  /// public F(a: int, b : char) { ... }
  /// </code>
  /// </example>
  ///
  /// <example> Breaking the default argument sequence
  /// <code>
  /// [DefaultArguments]
  /// public F(a : int = 1, b : char, c : double = 1.1) { ... }
  /// =>
  /// public F(a : int, b : char) { F(a, b, 1.1) }
  /// public F(a : int = 1, b : char, c : double) { ... }
  /// </code>
  /// </example>
  [Nemerle.MacroUsage(Nemerle.MacroPhase.WithTypedMembers
                    , Nemerle.MacroTargets.Method)]
  public macro DefaultArguments(tb : TypeBuilder, mb : MethodBuilder, params opts : list[PExpr])
  {
    DefaultArgumentsImpl.DefaultArguments(tb, mb, opts);
  }
        
  internal module DefaultArgumentsImpl
  {
    public DefaultArguments(tb : TypeBuilder
                          , mb : MethodBuilder
                          , _ : list[Parsetree.PExpr]) : void
    {
      def newName(name) { tb.ParsedName.NewName(name) }
      def defaultValueToPExpr(l)
      {
        PT.PExpr.Literal((l.DefaultValueAsTExpr() :> TT.TExpr.Literal).val)
      }
      
      // Overloaded methods
      def parms = mb.GetParameters();
      
      mutable cur = parms.Length - 1;
      foreach(arg in parms.Reverse())
      {
        // Overload if we have default value
        if(arg.HasDefaultValue)
        {
          def mparms = parms.FirstN(cur)
                            .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
          def fparms = mparms.Map(PT.Fun_parm);

          // Arguments and the default value
          def call = mparms + [defaultValueToPExpr(arg)];
          
          tb.Define
          (<[ decl:
              public $(newName(mb.Name) : name)(..$fparms) : $(mb.ReturnType : typed)
              {
                  this.$(mb.Name : dyn)(..$call)
              }
          ]>); 
        }
        else
          break;  
        
        // Check for last element
        if(cur == 0)
          break;
        else
          --cur;
      }
      
      // Check if the sequence was broken, so we need to leave the last argument
      def brokenSeq = parms.FirstN(cur).Find(x => x.default_value.IsSome).IsSome;
      // Remove the default arguments to avoid ambiguity      
      parms.LastN(parms.Length - cur - if(brokenSeq && parms.Length > cur) 1 else 0)
        // TODO: (1) .Iter(_.default_value = None());
           .Iter(x => x.default_value = None());
            
      // Was the default arguments sequence broken
      when(brokenSeq)
        Message.Hint("Default arguments sequence was broken. " +
                     "The overload is only by last arguments with default values");
      
    }
  }
}

1: Пока нельзя так, но очень хотелось бы.

Критика приветсвуется
Спасибо.
Re[2]: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 09.04.08 13:38
Здравствуйте, _nn_, Вы писали:


__>
__>          def mparms = parms.FirstN(cur)
__>                            .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>          def fparms = mparms.Map(PT.Fun_parm);
__>


А почему опять параметры без префикса parameters описываешь?
Re[3]: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 09.04.08 13:48
Здравствуйте, VladD2, Вы писали:

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



__>>
__>>          def mparms = parms.FirstN(cur)
__>>                            .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>>          def fparms = mparms.Map(PT.Fun_parm);
__>>


VD>А почему опять параметры без префикса parameters описываешь?

Нельзя, ошибки компиляции
mparms нужен для вызова функции, а fparms для аргументов функции.

Иначе нужно дублировать код:
def mparms = parms.FirstN(cur)
              .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
def fparms = parms.FirstN(cur)
              .Map(p => <[ parameter: $(newName(p.name) : name) : $(p.ty : typed) ]>);


А этот код делает совершенно другое:
def mparms = parms.FirstN(cur)
                  .Map(p => <[ parameter: $(newName(p.name) : name) : $(p.ty : typed) ]>);
def fparms = mparms;
Re[4]: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 09.04.08 14:13
Здравствуйте, _nn_, Вы писали:

__>Иначе нужно дублировать код:

__>
__>def mparms = parms.FirstN(cur)
__>              .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>def fparms = parms.FirstN(cur)
__>              .Map(p => <[ parameter: $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>


А ты знаешь о том, что в Fun_header есть свойства Parameters и ParametersReferences реализующие свойства ParametersDeclarations и ParametersReferences интерфейса IParametersProvider? Насколько я понимаю, это то, что тебе нужно, причем в готовом виде. Поляки как раз ими обычно оперируют.
Re[5]: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: _nn_http://our-site.3dn.ru
Дата: 09.04.08 16:06
Здравствуйте, VladD2, Вы писали:

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


__>>Иначе нужно дублировать код:

__>>
__>>def mparms = parms.FirstN(cur)
__>>              .Map(p => <[ $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>>def fparms = parms.FirstN(cur)
__>>              .Map(p => <[ parameter: $(newName(p.name) : name) : $(p.ty : typed) ]>);
__>>


VD>А ты знаешь о том, что в Fun_header есть свойства Parameters и ParametersReferences реализующие свойства ParametersDeclarations и ParametersReferences интерфейса IParametersProvider? Насколько я понимаю, это то, что тебе нужно, причем в готовом виде. Поляки как раз ими обычно оперируют.


Можно и так тоже:
def fparms = parms.FirstN(cur)
                  .Map(p => <[ parameter: $(newName(p.name) : name) : $(p.ty : typed) ]>);
          
// Arguments and the default value
def call = fparms.Map(_.ReferencingExpr) + [defaultValueToPExpr(arg)];


Т.е. создать <[ parameter: ... ]> а оттуда вытаскивать аргументы без parameter:, вместо простого создания списка через Fun_param ?
Какой в этом сакральный смысл ?
Re[6]: Автоматическая перегрузка функций №2 в избранное  msdn  новое    Оценить +1123x:) +-   модер. 
От: VladD2 модераторwww.k-press.ru/cs
Дата: 10.04.08 13:32
Здравствуйте, _nn_, Вы писали:

__>Т.е. создать <[ parameter: ... ]> а оттуда вытаскивать аргументы без parameter:, вместо простого создания списка через Fun_param ?

__>Какой в этом сакральный смысл ?

Смысл в том, что первый список (у тебя) не является реально ссылкой на параметр. Могут, например, имена пересечься. Да и более понятно, что происходит.