Re[17]: Функциональное программирование в Nemerle
От: Lloyd Россия  
Дата: 23.05.07 16:38
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Compiler-compiler
Автор: konsoletyper
Дата: 31.03.07

VD>Где искать мой ты и сам догадашся. Плюс можешь еще мне записать работу над тем же Немерловым компилятором.

VD>Что дальше?


Спасибо
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[16]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 23.05.07 23:47
Оценка: :)
Здравствуйте, Аноним, Вы писали:

K>>Всё-таки ты невменяемый.

А>Сумашедший гений? Что вы на гениальности не настаиваю, хотя видеть подобный крен в эпитетах приятно.
А>Впрочем, припоминаю, вы кажется уже хвалили мое умение искусно вести спор

Never argue with an idiot. He will lower you to his level and beat you with experience.

Как нельзя лучше объясняет твое "умение искусно вести спор".
Re[20]: Функциональное программирование в Nemerle
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.05.07 03:26
Оценка: +2
Здравствуйте, <Аноним>, Вы писали:

А>С одной стороны злонамеренный мудрец, в состоянии лего обмануть неискушенного человека, выстраивая ряд хитрых доказательств, с неочевидными упущениями.

А>С другой стороны для неискушенного человека, даже правильное сложное доказательство, выглядит недостаточно убедительным, ему кажется, что мудрец его обманывает.

Предлагаю завязать с оффтопом и троллингом. Или это такая пропаганда Nemerle путем чорного пеара его противников? Здесь в основном народ-то искушенный, так что переливания из пустого в порожнее и попытки сделать вид что "здесь я не нарочно нарушил стандарт форматирования исходников на C#" только забавляют. Не забавляет затянутость этой шутки.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 24.05.07 16:50
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Предлагаю завязать с оффтопом и троллингом.

Внимательно просмотрел, все страницы темы, ваших выступлений как по теме таки и вне ее не нашел. Надеюсь, вы не выступали анонимно?
Также интересует, в какой временной промежуток должно попадать предложение завязать с оффтопом после времени опубликования самого якобы оффтопа?
Следует, ли и через неделю после, опубликования показавшегося не по теме постинга, сообщать автору о недопустимости подобного?

S>"здесь я не нарочно нарушил стандарт форматирования исходников на C#"

Будь, я на месте konsoletyper'а обязательно написал бы в ответ, что это "откровенная ложь"!
А так заявляю, что никогда не делал вид, что не нарочно нарушил некий стандарт форматирования исходников на C#.

S>Не забавляет затянутость этой шутки.

Что-то мешает игнорировать тему?
Re: Функциональное программирование в Nemerle
От: Аноним  
Дата: 29.05.07 19:23
Оценка: -1
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

Обратил внимание, что в примере для Nemerle используются варианты и за счет этого можно успешно перебирать их в match.
Однако для C# также можно сделать подобное

using System;
using PatternMatching;
using Variants;

delegate Expr Convert(Expr expr);

class Variant : Variant<Lit, Plus, Minus, Mul, Div, Max, Min, Foo> {}

abstract class Expr: IMatch
{
  public static implicit operator double(Expr expr) { return expr.Eval(); }
  public double Eval()
  {
    return Variant.Switch<double, Expr>(this,
      delegate(Lit lit) { return lit.Value; },
      delegate(Plus plus) { return plus.First + plus.Second; },
      delegate(Minus minus) { return minus.First - minus.Second; },
      delegate(Mul mul) { return mul.First * mul.Second; },
      delegate(Div div) { return div.First / div.Second; },
      delegate(Max max) { return Math.Max(max.First, max.Second); },
      delegate(Min min) { return Math.Min(min.First, min.Second); },
      delegate(Foo foo) { return foo.Value; });
  }
  public override string ToString()
  {
    return Variant.Switch<string, Expr>(this,
      delegate(Lit lit) { return lit.Value.ToString(); },
      delegate(Plus plus) { return plus.First + " + " + plus.Second; },
      delegate(Minus minus) { return minus.First + " - " + minus.Second; },
      delegate(Mul mul) { return mul.First + " * " + mul.Second; },
      delegate(Div div) { return div.First + " / " + div.Second; },
      delegate(Max max) { return "Max(" + max.First + ", " + max.Second + ")"; },
      delegate(Min min) { return "Min(" + min.First + ", " + min.Second + ")"; },
      delegate(Foo foo) { return "Foo(" + foo.Value + ")"; });
  }
  public Expr Convert(Convert convert)
  {
    return Variant.Switch<Expr, Expr>(this,
      delegate(Lit lit) { return convert(new Lit(lit.Value)); },
      delegate(Plus plus) { return convert(new Plus(plus.First.Convert(convert), plus.Second.Convert(convert))); },
      delegate(Minus minus) { return convert(new Minus(minus.First.Convert(convert), minus.Second.Convert(convert))); },
      delegate(Mul mul) { return convert(new Mul(mul.First.Convert(convert), mul.Second.Convert(convert))); },
      delegate(Div div) { return convert(new Div(div.First.Convert(convert), div.Second.Convert(convert))); },
      delegate(Max max) { return convert(new Max(max.First.Convert(convert), max.Second.Convert(convert))); },
      delegate(Min min) { return convert(new Min(min.First.Convert(convert), min.Second.Convert(convert))); },
      delegate(Foo foo) { return convert(new Foo(foo.Value.Convert(convert))); });
  }
  /*тут секретный метод в одну строку для сопоставления с образцом*/
}
class Lit: Expr
{ 
  public readonly double Value; 
  public Lit(double value) { this.Value = value; }
}
abstract class Oper: Expr
{
  public readonly Expr First, Second;
  public Oper(Expr first, Expr second) 
  { 
    First = first; 
    Second = second; 
  }
  /*тут секретный метод в одну строку для сопоставления с образцом*/
}
class Plus : Oper { public Plus(Expr first, Expr second) : base(first, second) { } }

class Minus : Oper { public Minus(Expr first, Expr second) : base(first, second) { } }

class Mul : Oper { public Mul(Expr first, Expr second) : base(first, second) { } }

class Div : Oper { public Div(Expr first, Expr second) : base(first, second) { } }

class Max : Oper { public Max(Expr first, Expr second) : base(first, second) { } }

class Min : Oper { public Min(Expr first, Expr second) : base(first, second) { } }

class Foo : Expr 
{
  public readonly Expr Value;
  public Foo(Expr value) { Value = value; }
  /*тут секретный метод в одну строку для сопоставления с образцом*/
}
class Program
{
  public static void Main(string[] arguments)
  {
    Convert(new Max(new Mul(new Lit(2), new Lit(1)), new Lit(3)), RemoveMulToOne);
    Convert(new Foo(new Mul(new Lit(1), new Lit(5))), RemoveMulOneTo);
    Convert(new Max(new Lit(5), new Lit(3)), RemoveMaxOfLit);
    Convert(new Max(new Mul(new Lit(2), new Lit(2)), new Div(new Lit(3), new Lit(3))), RemoveSpecialMax);
    Console.ReadLine();
  }
  public static void Convert(Expr expr, Convert convert)
  {
    Console.WriteLine("Expression '{0}' = {1}", expr, expr.Eval());
    Expr converted = expr.Convert(convert);
    Console.WriteLine("Converted expression '{0}' = {1}", converted, converted.Eval());
    Console.WriteLine();
  }
  static Expr RemoveMulToOne(Expr expr)
  {
    return new Pattern<Mul, Expr, Lit>().Replace<Expr>(expr,
      delegate(Mul mul, Expr first, Lit lit) { return lit == 1 ? first : expr; });
  }
  static Expr RemoveMulOneTo(Expr expr)
  {
    return new Pattern<Mul, Lit, Expr>().Replace<Expr>(expr,
      delegate(Mul mul, Lit lit, Expr second) { return lit == 1 ? second : expr; });
  }
  static Expr RemoveMaxOfLit(Expr expr)
  {
    return new Pattern<Max, Lit, Lit>().Replace<Expr>(expr,
      delegate(Max max, Lit lit1, Lit lit2) { return new Lit(Math.Max(lit1, lit2)); });
  }
  static Expr RemoveSpecialMax(Expr expr)
  {
    return new Pattern<Max, Mul, Lit, Lit, Div, Lit, Lit>().Replace<Expr>(expr,
      delegate(Max max, Mul mul, Lit x, Lit m, Div div, Lit y, Lit d) { return new Lit(Math.Max(x * m, y / d)); });
  }
}

Достаточно близкий аналог на Nemerle
using System;
using System.Console;
using Nemerle.Utility;
using Expr;

public variant Expr
{
  | Lit { value : double; }
  | Plus { first : Expr; second : Expr; }
  | Minus { first : Expr; second : Expr; }
  | Mul { first : Expr; second : Expr; }
  | Div { first : Expr; second : Expr; }
  | Max { first : Expr; second : Expr; }
  | Min { first : Expr; second : Expr; }
  | Foo { value : Expr; }
  public override ToString() : string
  {
    match (this)
    {
      | Lit(value) => value.ToString()
      | Plus(first, second) => $"$first + $second"
      | Minus(first, second) => $"$first - $second"
      | Mul (first, second) => $"$first * $second"
      | Div (first, second) => $"$first / $second"
      | Max(first, second) => $"Max($first, $second)"
      | Min(first, second) => $"Min($first, $second)"
      | Foo(value) => $"Foo($value)"
    }
  }
  public Eval() : double
  {
    match (this)
    {
      | Lit(value) => value
      | Plus(first, second) => first.Eval() + second.Eval()
      | Minus(first, second) => first.Eval() - second.Eval()
      | Mul(first, second) => first.Eval() * second.Eval()
      | Div(first, second) => first.Eval() / second.Eval()
      | Max(first, second) => Math.Max(first.Eval(), second.Eval())
      | Min(first, second) => Math.Min(first.Eval(), second.Eval())
      | Foo(value) => value.Eval()
    }
  }
  public Convert(converter : Expr -> Expr) : Expr
  {
    def res = match(this)
    {
      | Lit => this
      | Plus(first, second) => Plus(first.Convert(converter), second.Convert(converter))
      | Minus(first, second) => Minus(first.Convert(converter), second.Convert(converter))
      | Mul(first, second) => Mul(first.Convert(converter), second.Convert(converter))
      | Div(first, second) => Div(first.Convert(converter), second.Convert(converter))
      | Max(first, second) => Max(first.Convert(converter), second.Convert(converter))
      | Min(first, second) => Min(first.Convert(converter), second.Convert(converter))
      | Foo(value) => Foo(value.Convert(converter))
    }
    converter(res)
  }
}
module Program
{
  Main(_ : array [string]) : void
  {
    Convert(Max(Mul(Lit(2), Lit(1)), Lit(3)), RemoveMulToOne);
    Convert(Foo(Mul(Lit(1), Lit(5))), RemoveMulOneTo);
    Convert(Max(Lit(5), Lit(3)), RemoveMaxOfLit);
    Convert(Max(Mul(Lit(2), Lit(2)), Div(Lit(3), Lit(3))), RemoveSpecialMax);
    _ = ReadLine();
  }
  RemoveMulToOne(expr : Expr) : Expr
  {
    match(expr)
    {
      | Mul(first, Lit(1.0)) => first
      | _ => expr
    }
  }
  RemoveMulOneTo(expr : Expr) : Expr
  {
    match(expr)
    {
      | Mul(Lit(1.0), second) => second
      | _ => expr
    }
  }
  RemoveMaxOfLit(expr : Expr) : Expr
  {
    match(expr)
    {
      | Max(Lit(value1), Lit(value2)) => Lit(Math.Max(value1, value2))
      | _ => expr
    }
  }
  RemoveSpecialMax(expr : Expr) : Expr
  {
    match(expr)
    {
      | Max(Mul(Lit(x), Lit(m)), Div(Lit(y), Lit(d))) => Lit(Math.Max(x * m, y / d))
      | _ => expr
    }
  }
  Convert(expr : Expr, converter : Expr -> Expr) : void
  {
    WriteLine($"Expression '$expr' = $(expr.Eval())");
    def converted = expr.Convert(converter);
    WriteLine($"Converted expression '$converted' = $(converted.Eval())");
    WriteLine();
  }
}


Итог:
С# — 120 строк, 5206 байт, 120 символов самая длинная строка
Nemerle — 109 строк, 3368 байт, 91 символ самая длинная строка
Re[2]: Функциональное программирование в Nemerle
От: rameel https://github.com/rsdn/CodeJam
Дата: 29.05.07 19:40
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

Доктор, я слепой. Денег не вижу. (с)

... << RSDN@Home 1.2.0 alpha rev. 677>>
Re[3]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 29.05.07 20:48
Оценка: :))) :)
Здравствуйте, rameel, Вы писали:

R>

Доктор, я слепой. Денег не вижу. (с)

Рисование денег, оставлено в качестве упражнения.
Variant<> сделать совсем легко, а вот Pattern<> сильно потяжелее.
Иногда я даже удивляюсь, что смог его сделать.
Re[2]: Функциональное программирование в Nemerle
От: IT Россия linq2db.com
Дата: 30.05.07 13:30
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Обратил внимание, что в примере для Nemerle используются варианты и за счет этого можно успешно перебирать их в match.

А>Однако для C# также можно сделать подобное

Я когда-то очень давно эмулировал ООП на C, получалось примерно такое же г.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 13:43
Оценка: -2 :)
День добрый,

здесь в коде выделены жирным элементы, которые призваны улучшить читаемость кода:

def isBraceMatch()
{
  def lex = engine.GetLexer(_source);
    // без new данный вызов легко спутать с вызовом метода,
    // а различать вызов метода и конструктора нужно по многим причинам
  def stack = new Stack();
  stack.Push(Token.EndOfFile());

    // очень несложно поставить возвращаемый тип данных, тем более,
    // что меняться в будующем он вряд ли будет, а читаемость кода резко
    // возрастает - сразу понятно, как именно нужно относится к содержимому
  def scan(toc : Token) : bool
  {
        // это общее возражение на бесповоротный отказ от return - для конечного 
        // результата в стэке рекурсии очень полезно оставить флажок "а здесь
        // мы начали раскручивать стэк в обратном направлении"
    | EndOfFile           => return stack.Count == 1

    | BeginBrace             // {
    | BeginRound             // (
    | BeginSquare            // [
    | BeginQuote          => // <[
      stack.Push(toc);
      scan(lex.GetToken())

    | EndBrace            => check(_ is Token.BeginBrace)  // }
    | EndRound            => check(_ is Token.BeginRound)  // )
    | EndSquare           => check(_ is Token.BeginSquare) // ]
    | EndQuote            => check(_ is Token.BeginQuote)  // ]>
    | _                   => scan(lex.GetToken());
  }
  and check(predicate)
  {
      if (stack.Count > 0 && predicate(stack.Peek()))
      {
        stack.RemoveLast();
                // честное слово, очень многие люди оценят здесь return :)
        return scan(lex.GetToken())
      }
      else
        return false
  }

    // и здесь тоже - просто как флаг говорящий, что работа функции
    // официально закончена
  return scan(lex.GetToken());
}


без претензий на самое объективное мнение, но с твердой субъективной позицией

p.s. статья — отличная
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Функциональное программирование в Nemerle
От: Иванков Дмитрий Россия  
Дата: 30.05.07 14:22
Оценка:
Здравствуйте, Кэр, Вы писали:

Кэр>
Кэр>    // без new данный вызов легко спутать с вызовом метода,
Кэр>    // а различать вызов метода и конструктора нужно по многим причинам
Кэр>  def stack = new Stack();

Различать их очень легко, конструктор всегда имеет имя this/base, если речь идет о текущем классе.
Если речь о внешнем по отношению к классу коду, то ничего страшного нет, при неоднозначности получим "overload ambiguity".
Идеология простая — вызов конструктора = вызов ф-ии, возвращающей экземпляр класса.

Ключевое слово new есть, но только для деклараций методов (virtual override или new).

За указание мест где требуются пояснения безусловно спасибо
Re[3]: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 14:31
Оценка:
Здравствуйте, Иванков Дмитрий, Вы писали:

ИД>Идеология простая — вызов конструктора = вызов ф-ии, возвращающей экземпляр класса.


В том-то и дело, что не равно. Метод может вернуть существующую копию объекта, конструктор всегда даст новый объект. Это уже дает совершенно разное отношение к этому коду.
Кроме того — лучше когда сразу понятно, куда надо если что обратить свой взор — где могут быть потенциальные проблемы. В одношаговых логических цепочках — это все равно, если что внимательно посмотрели на контекст, спохватились, начали думать в другом направлении. В более длинных цепочках подобные умолчания будут только тормозить решение проблемы.

И вообще если уж говорить про принципиальные отличия: внутри обычного метода можно использовать вызовы виртуальных методов, внутри конструктора нельзя — так что думать о них как о близнецах-братьях очень не рекомендуется.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 14:33
Оценка:
konsoletyper, смелее, можно словами
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Функциональное программирование в Nemerle
От: nikov США http://www.linkedin.com/in/nikov
Дата: 30.05.07 14:35
Оценка: 1 (1)
Здравствуйте, Кэр, Вы писали:

Кэр>В том-то и дело, что не равно. Метод может вернуть существующую копию объекта, конструктор всегда даст новый объект.


В Nemerle вызов конструктора не всегда возвращает новый объект.
Re[5]: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 14:38
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Кэр, Вы писали:


Кэр>>В том-то и дело, что не равно. Метод может вернуть существующую копию объекта, конструктор всегда даст новый объект.


N>В Nemerle вызов конструктора не всегда возвращает новый объект.


Обалдеть А зачем это сделано?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Функциональное программирование в Nemerle
От: Сергей Туленцев Россия http://software.tulentsev.com
Дата: 30.05.07 14:40
Оценка:
Здравствуйте, Иванков Дмитрий, Вы писали:

ИД>Ключевое слово new есть, но только для деклараций методов (virtual override или new).


Vermicious Knid припахал его еще для конструирования анонимных типов. Правда, в SVN это так и не попало, по моему.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Re[6]: Функциональное программирование в Nemerle
От: nikov США http://www.linkedin.com/in/nikov
Дата: 30.05.07 14:40
Оценка:
Здравствуйте, Кэр, Вы писали:

N>>В Nemerle вызов конструктора не всегда возвращает новый объект.


Кэр>Обалдеть А зачем это сделано?


По-моему, очевидно... Для экономии объектов.
Re[7]: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 14:46
Оценка: 1 (1)
Здравствуйте, nikov, Вы писали:

N>>>В Nemerle вызов конструктора не всегда возвращает новый объект.


Кэр>>Обалдеть А зачем это сделано?


N>По-моему, очевидно... Для экономии объектов.


А, ну да
Имхо, это одна из вещей, которую надо вешать на пороге при входе в Nemerle. Типа — не забудьте пригнуться
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Функциональное программирование в Nemerle
От: Иванков Дмитрий Россия  
Дата: 30.05.07 14:51
Оценка:
Здравствуйте, Кэр, Вы писали:

Кэр>И вообще если уж говорить про принципиальные отличия: внутри обычного метода можно использовать вызовы виртуальных методов, внутри конструктора нельзя — так что думать о них как о близнецах-братьях очень не рекомендуется.


Верно, но конструктор "создающий" это как раз фактически обычная функция, и имя у нее такое же как и у класса.
А вот в том что внутри конструктора есть конечно упомянутая разница, и имя уже this/base для конструктора этого же экземпляра.
Re[5]: Функциональное программирование в Nemerle
От: Кэр  
Дата: 30.05.07 14:55
Оценка:
Здравствуйте, Иванков Дмитрий, Вы писали:

ИД>Здравствуйте, Кэр, Вы писали:


ИД>Верно, но конструктор "создающий" это как раз фактически обычная функция, и имя у нее такое же как и у класса.

ИД>А вот в том что внутри конструктора есть конечно упомянутая разница, и имя уже this/base для конструктора этого же экземпляра.

Ну, согласен
В общем, после того, как я осознал, что конструктор в Nemerle может не создать объект — надо сесть, помедитировать и провести оценку ценостей заново

Но замечания насчет return вполне в силе.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Функциональное программирование в Nemerle
От: anonym469  
Дата: 30.05.07 15:40
Оценка:
Здравствуйте, IT, Вы писали:

IT>Я когда-то очень давно эмулировал ООП на C

Я знал, что у нас есть что-то общее в далеком прошлом.
IT>получалось примерно такое же г.
Компактное г, смею заметить. А не пятикратное г.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.