Функциональное программирование в Nemerle
От: Чистяков Влад (VladD2) Российская Империя www.nemerle.org
Дата: 03.03.07 17:23
Оценка: 1315 (27) +1 -1
Статья:
Функциональное программирование в Nemerle
Автор(ы): Чистяков Влад (VladD2)
Дата: 03.03.2007
Язык программирования Nemerle заинтересовал многих в первую очередь своей мощнейшей подсистемой мак-росов. Однако и без них Nemerle предоставляет ряд су-щественных улучшений по сравнению с традиционными, императивными языками программирования (такими как Java, C# и C++).
Nemerle, кроме традиционного императивного програм-мирования, поддерживает функциональное программи-рование. Это выражается в наличии конструкций, упро-щающих манипуляцию функциями, построение и анализ сложных структур данных и т.п.
К сожалению, если вы не использовали возможности, присущие функциональным языкам ранее, то вам будет трудно оценить, насколько Nemerle может оказаться вам полезным в реальной повседневной работе. Данная статья призвана в неформальной форме продемонс-трировать это.


Авторы:
Чистяков Влад (VladD2)

Аннотация:
Язык программирования Nemerle заинтересовал многих в первую очередь своей мощнейшей подсистемой макросов. Однако и без них Nemerle предоставляет ряд существенных улучшений по сравнению с традиционными, императивными языками программирования (такими как Java, C# и C++).
Nemerle, кроме традиционного императивного программирования, поддерживает функциональное программирование. Это выражается в наличии конструкций, упрощающих манипуляцию функциями, построение и анализ сложных структур данных и т.п.
К сожалению, если вы не использовали возможности, присущие функциональным языкам ранее, то вам будет трудно оценить, насколько Nemerle может оказаться вам полезным в реальной повседневной работе. Данная статья призвана в неформальной форме продемонстрировать это.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Функциональное программирование в Nemerle
От: icWasya  
Дата: 22.03.07 12:40
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>Функциональное программирование в Nemerle
Автор(ы): Чистяков Влад (VladD2)
Дата: 03.03.2007
Язык программирования Nemerle заинтересовал многих в первую очередь своей мощнейшей подсистемой мак-росов. Однако и без них Nemerle предоставляет ряд су-щественных улучшений по сравнению с традиционными, императивными языками программирования (такими как Java, C# и C++).
Nemerle, кроме традиционного императивного програм-мирования, поддерживает функциональное программи-рование. Это выражается в наличии конструкций, упро-щающих манипуляцию функциями, построение и анализ сложных структур данных и т.п.
К сожалению, если вы не использовали возможности, присущие функциональным языкам ранее, то вам будет трудно оценить, насколько Nemerle может оказаться вам полезным в реальной повседневной работе. Данная статья призвана в неформальной форме продемонс-трировать это.


ЧВV>Авторы:

ЧВV> Чистяков Влад (VladD2)

А как попасть на эту статью через меню
Статьи->
Nemerle->
Функциональное программирование в Nemerle
Re[2]: Функциональное программирование в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.07 13:59
Оценка:
Здравствуйте, icWasya, Вы писали:

W>А как попасть на эту статью через меню

W>Статьи->
W> Nemerle->
W> Функциональное программирование в Nemerle

Чуть позже ее добавят вразделы:
/Статьи/Декларативное программирование/Nemerle и /Статьи/.NET/Nemerle
Сейчас она просто не выложена.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Функциональное программирование в Nemerle
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.03.07 07:15
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

Здравствуй на нашу пользу, не болей. Ждем статью про макросы
и солнце б утром не вставало, когда бы не было меня
Re: небольшие правки
От: Иванков Дмитрий Россия  
Дата: 09.05.07 07:29
Оценка: 35 (2)
ЧВV> с незаменяемыми полями
вероятно все же неизменяемыми, ... хотя

ЧВV> отряд не заменит потери бойца

так даже больше нравится, но вроде бы по контексту должна быть классика

ЧВV> Так, все поля Variant Option ... обязаны быть публичными, и по умолчанию являются изменяемыми

опечатка, "не" пропущено

ЧВV> но в основном их применение обычно обосновано и происходит из-за того, что программист просто пока не привык использовать неизменяемые структуры данных.

аналогично

ЧВV> Если функция начинается с выражения match, ...

все же точнее будет "Если тело функции состоит из выражения match, ..."
Re[2]: небольшие правки
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.05.07 07:44
Оценка:
Здравствуйте, Иванков Дмитрий, Вы писали:...

Спаисбо, постараемся в ближаейшее время поправить.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Функциональное программирование в Nemerle
От: AngeL B. Россия  
Дата: 09.05.07 17:57
Оценка:
Не компилируется пример из статьи. На кусок
// Другой вариант частичного применения. В этот раз первому параметру 
// назначен строковый литерал.
def f = WriteLine("Еще один вариант - '{0}'", _);
f("частичного применения функции");


компилятор у меня матерится следующим образом
in argument #1 of f, needed a array [System.Object]+, got string: string is not a subtype of array [System.Object] [simple require]

версия компилятора 0.9.3.
Что и где не так?
Re[2]: Функциональное программирование в Nemerle
От: Иванков Дмитрий Россия  
Дата: 09.05.07 18:48
Оценка:
Здравствуйте, AngeL B., Вы писали:

AB>Не компилируется пример из статьи. На кусок

AB>
AB>// Другой вариант частичного применения. В этот раз первому параметру 
AB>// назначен строковый литерал.
AB>def f = WriteLine("Еще один вариант - '{0}'", _);
AB>f("частичного применения функции");
AB>


AB>компилятор у меня матерится следующим образом

AB>in argument #1 of f, needed a array [System.Object]+, got string: string is not a subtype of array [System.Object] [simple require]

AB>версия компилятора 0.9.3.

AB>Что и где не так?

Не очень хорошо вышло, в 0.9.3 баг, в trunk версии бага нет, как минимум с r7392 (самое старое что есть под рукой).
Варианты исправления:
1) забрать из svn последнюю версию
2) забрать свежий daily snapshot
3) исправить пример
def f = x : string => WriteLine("Еще один вариант - '{0}'", x);
f("частичного применения функции");


Причем в случаях 1 и 2 даже необязательно собирать компилятор, бинарники в boot там этого бага не имеют.
Re: замыкания
От: x-code  
Дата: 09.05.07 19:12
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

Все отлично, статья очень понравилась, но хотелось бы как-то раскрыть понятие "замыкания" для людей, до этого не имевших дело с ФП. Это что физически такое?
Как я понял — средство упаковки функции вместе с некоторым количеством локальных переменных (аргументов функции и т.п.) в единый объект? Или я не прав?
Re[2]: замыкания
От: _FRED_ Черногория
Дата: 10.05.07 07:13
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все отлично, статья очень понравилась, но хотелось бы как-то раскрыть понятие "замыкания" для людей, до этого не имевших дело с ФП. Это что физически такое?


Подробнее об этом сказано в других статьях. Пример: Анонимные методы в C# 2.0
Автор(ы): Patrick Smacchia
Дата: 30.07.2006
Статья представляет новое свойство языка C# версии 2.0, называемое анонимными методами.
.

XC>Как я понял — средство упаковки функции вместе с некоторым количеством локальных переменных (аргументов функции и т.п.) в единый объект? Или я не прав?


Примерно, прав.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Функциональное программирование в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.05.07 09:34
Оценка:
Здравствуйте, AngeL B., Вы писали:

AB>версия компилятора 0.9.3.

AB>Что и где не так?

Компилятор в 0.9.3 имел много багов и недоработок. Этот код проверялся на последней версии.

Можно взять бинарники компилятора из boot-а:
http://nemerle.org/svn/nemerle/trunk/boot

Или попробовать одну из CTP-версий интеграции (к сожалению последняя версия не досутпна, но можно попробовать апрельскую Nemerle APR 2007 CTP (вторая попытка)
Автор: Блудов Павел
Дата: 09.04.07
).

Так же можно собрать компилятор самому, что сложнее, но дает самую последнию версию плюс рабочую версию интеграции.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: замыкания
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.05.07 09:34
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все отлично, статья очень понравилась, но хотелось бы как-то раскрыть понятие "замыкания" для людей, до этого не имевших дело с ФП. Это что физически такое?

XC>Как я понял — средство упаковки функции вместе с некоторым количеством локальных переменных (аргументов функции и т.п.) в единый объект? Или я не прав?

Именно так. Рассматривать их лучше не как объекты, а как отдельную абстракцию, но взгляд на замыкания как на эдакие инлайн-объекты тоже имеет право на жизнь. Собственно так и делается в компиляторе Nemerle. Но все может измениться. В принципе хороший оптимизирующий компилятор может переписывать код программы устраня как такие невидимые классы, так и вызов метода по ссылки. Но это уже детали реализации компиляторов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: замыкания
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.05.07 16:37
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все отлично, статья очень понравилась, но хотелось бы как-то раскрыть понятие "замыкания" для людей, до этого не имевших дело с ФП. Это что физически такое?


Closure, Замыкание
Re: Функциональное программирование в Nemerle
От: Аноним  
Дата: 14.05.07 10:52
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

По поводу интерпретатора арифметических выражений:

В C# версии реализован паттерн Visitor, а в Nemerle версии нет.
А было бы "замечательно" если бы у каждого варианта был бы метод Accept.

Вот аналог того, что в Nemerle на C#

using System;

abstract class Expression
{
    public virtual double Eval() 
    { 
        Literal literal = this as Literal; 
        if (literal != null) 
        {
            return literal.Value;
        }
        Operation operation = this as Operation; 
        if (operation != null)
        {
            if (this is Min) return Math.Min(operation.First.Eval(), operation.Second.Eval());
            if (this is Max) return Math.Max(operation.First.Eval(), operation.Second.Eval());
            if (this is Plus)  return operation.First.Eval() + operation.Second.Eval();
            if (this is Minus) return operation.First.Eval() - operation.Second.Eval();
            if (this is Mul)   return operation.First.Eval() * operation.Second.Eval();
            if (this is Div)   return operation.First.Eval() / operation.Second.Eval();
        }
        throw new InvalidOperationException(ToString());
    }

    public new virtual string ToString() 
    {
        Literal literal = this as Literal; 
        if (literal != null) 
        {
            return literal.Value.ToString();
        }
        Operation operation = this as Operation; 
        if (operation != null)
        {
            if (this is Min) return "Min(" + operation.First.ToString() + ", " + operation.Second.ToString() + ")";
            if (this is Max) return "Max(" + operation.First.ToString() + ", " + operation.Second.ToString() + ")";
            if (this is Plus)  return operation.First.ToString() + " + " + operation.Second.ToString();
            if (this is Minus) return operation.First.ToString() + " - " + operation.Second.ToString();
            if (this is Mul)   return operation.First.ToString() + " * " + operation.Second.ToString();
            if (this is Div)   return operation.First.ToString() + " / " + operation.Second.ToString();
        }
        throw new InvalidOperationException(base.ToString());
    }
}

class Literal: Expression
{
    private double value;
    public double Value { get { return value; } }
    public Literal(double value) { this.value = value; }
}

abstract class Operation: Expression
{
    private Expression first, second;
    public Expression First { get {return first; } }
    public Expression Second { get {return second; } }
    public Operation(Expression first, Expression second)
    {
        this.first = first;
        this.second = second;
    }
}

class Min:   Operation { public Min  (Expression first, Expression second): base(first, second) {} }
class Max:   Operation { public Max  (Expression first, Expression second): base(first, second) {} }
class Plus:  Operation { public Plus (Expression first, Expression second): base(first, second) {} }
class Minus: Operation { public Minus(Expression first, Expression second): base(first, second) {} }
class Mul:   Operation { public Mul  (Expression first, Expression second): base(first, second) {} }
class Div:   Operation { public Div  (Expression first, Expression second): base(first, second) {} }

public class Program
{
    public static void Main(string[] arguments)
    {        
        Expression expression = new Plus(new Literal(1.23), new Min(new Literal(3.45), new Literal(1.23)));
        Console.WriteLine("Expression '{0}' = {1}", expression.ToString(), expression.Eval());
    }
}
Re[2]: Функциональное программирование в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.05.07 15:45
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, Чистяков Влад (VladD2), Вы писали:


А>По поводу интерпретатора арифметических выражений:


А>В C# версии реализован паттерн Visitor, а в Nemerle версии нет.


Естественно, так как он попросту не нужен при наличии паттерн-матчинга.

А>А было бы "замечательно" если бы у каждого варианта был бы метод Accept.


Не вижу ничего замечательного в этом. Использование данного паттерна — это проектное решение. В чистом ООП оно имеет смысл, так как упрощает равитие системы, при наличии паттерн-матчинга оно попросту бессмысленно.

А>Вот аналог того, что в Nemerle на C#


Это как раз поптыка эмулировать паттерн-матчинг на C#. Только у этого решенпия есть две прблемы которые заставят отказаться от него.
1. Нет никаких гарантий, что обработаны все варианты. О том, что какой-то варинат не обработан будет известно только в рантайме. Стало быть мы получаем самые плохие стороны динамики в казалось бы статически типизированном языке. Вариант с паттерн-мачингом дает нам такие гарантии (компилятор проверяет полноту паттернов).
2. Это очень примитивный случай. В нем паттерн-матчинг действительно не так сложно эмулировать на операторах is/as. Но с разрастанием кода станет очевидным, что эмуляция хуже оригинала. Как я говорил в статье, паттерн-матчинг поддерживеет сложные вложенные паттерны, что значительно увеличивает наши возможности. Например, если нам понадобиться распознать некий паттерн в коде (ну скажем упростить мат.выражения), то с паттерн-матчингом прийдется добавить всего пару строк кода, а в императивном коду это уже красиво не выразить. Прийдется лепить кучи if-ов.

Ну, и надо заметить, что кода все равно значительно больше чем на Nemerle, хотя и не так много как в чисто ОО-решении. К тому же в нем ради "укомпакчивания" кода бвли допущены разные вольности вроде наличия Value у всех выражений хотя только оно нужно только у литералов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 14.05.07 16:58
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В чистом ООП оно имеет смысл, так как упрощает равитие системы, при наличии паттерн-матчинга оно попросту бессмысленно.

А главное отжирает по три строке в каждом классе. Я к тому, что в том примере C# и Nemerle сравнивались нечестно, за счет чего и получилась, столь впечатляющая разница в объеме кода в строках. В килобайтах, кстати не так много, не в 5 раз, а в 3.

VD>2. Это очень примитивный случай. В нем паттерн-матчинг действительно не так сложно эмулировать на операторах is/as. Но с разрастанием кода станет очевидным, что эмуляция хуже оригинала. Как я говорил в статье, паттерн-матчинг поддерживеет сложные вложенные паттерны, что значительно увеличивает наши возможности. Например, если нам понадобиться распознать некий паттерн в коде (ну скажем упростить мат.выражения), то с паттерн-матчингом прийдется добавить всего пару строк кода, а в императивном коду это уже красиво не выразить. Прийдется лепить кучи if-ов.

Ну и где такой пример, который бы с одной стороны имел достаточную сложность для показа превосходства Nemerle, а с другой не являлся бы, например, исходниками компилятора Nemerle.


VD>Ну, и надо заметить, что кода все равно значительно больше чем на Nemerle, хотя и не так много как в чисто ОО-решении.

В этом и мысль. Конечно превосходство Nemerle очевидно при сравнении 250 строк кода на С# и 50 строк кода на Nemerle, однако если аналогичный код на С# легко умещается в 80 строк, преимущество Nemerle испаряется.

VD>К тому же в нем ради "укомпакчивания" кода бвли допущены разные вольности вроде наличия Value у всех выражений хотя только оно нужно только у литералов.

Этого нет, Value только у Literal'ов.
Re[4]: Функциональное программирование в Nemerle
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 14.05.07 18:45
Оценка:
Здравствуйте, <Аноним>, Вы писали:

VD>>2. Это очень примитивный случай. В нем паттерн-матчинг действительно не так сложно эмулировать на операторах is/as. Но с разрастанием кода станет очевидным, что эмуляция хуже оригинала. Как я говорил в статье, паттерн-матчинг поддерживеет сложные вложенные паттерны, что значительно увеличивает наши возможности. Например, если нам понадобиться распознать некий паттерн в коде (ну скажем упростить мат.выражения), то с паттерн-матчингом прийдется добавить всего пару строк кода, а в императивном коду это уже красиво не выразить. Прийдется лепить кучи if-ов.

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

См. исходники здесь. Особое внимание советую обратить на src/Common/Bnf/BnfUtils.n. И заодно рекомендую прикинуть, как будет выглядеть аналогичный код на C#, и сколько времени уйдёт на его написание.

VD>>Ну, и надо заметить, что кода все равно значительно больше чем на Nemerle, хотя и не так много как в чисто ОО-решении.

А>В этом и мысль. Конечно превосходство Nemerle очевидно при сравнении 250 строк кода на С# и 50 строк кода на Nemerle, однако если аналогичный код на С# легко умещается в 80 строк, преимущество Nemerle испаряется.

Это эчень искусственно. В данном случае имеет место ужимание строк. Если честно эмулировать паттерн-матчинг, то строк должно быть около 120. Более чем в 2 раза — уже достойный результат. Причём, это C# так хорошо отделался на простом примере, дай ему что-то посложнее, и он быстро обломается.

Кстати, советую ещё обратить внимание на слова Влада про то, что компилятор Nemerle проверяет, все ли варианты отловлены и предупреждает в случае необходимости. А подчас помощь компилятора в нахождении ошибок за программиста — это гораздо больший плюс, нежели лаконичность.
... << RSDN@Home 1.2.0 alpha rev. 672>>
Re[5]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 14.05.07 20:55
Оценка:
Здравствуйте, konsoletyper, Вы писали:

K>Здравствуйте, <Аноним>, Вы писали:


K>См. исходники здесь. Особое внимание советую обратить на src/Common/Bnf/BnfUtils.n. И заодно рекомендую прикинуть, как будет выглядеть аналогичный код на C#, и сколько времени уйдёт на его написание.

Гляну.

K>Если честно эмулировать паттерн-матчинг, то строк должно быть около 120. Более чем в 2 раза — уже достойный результат.

Не вижу, где нечестно и чего нехватает.

K>Причём, это C# так хорошо отделался на простом примере, дай ему что-то посложнее, и он быстро обломается.

Из данного примера облом не очевиден.

K>Кстати, советую ещё обратить внимание на слова Влада про то, что компилятор Nemerle проверяет, все ли варианты отловлены и предупреждает в случае необходимости. Я обратил. Пока думаю, как реализовать это на C#.
Re[6]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 14.05.07 21:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я обратил. Пока думаю, как реализовать это на C#.


Достаточно перенести код для ToString и Eval в методы класса, тем самым если появится новый класс — то эти методы придется реализовать
using System;

abstract class Expression
{
    public abstract double Eval();
    public override abstract string ToString();
}

class Literal: Expression
{
    private double value;
    public double Value { get { return value; } }
    public Literal(double value) { this.value = value; }
    public override double Eval() { return value; }
    public override string ToString() { return value.ToString(); }
}

abstract class Operation: Expression
{
    private Expression first, second;
    public Expression First { get {return first; } }
    public Expression Second { get {return second; } }
    public Operation(Expression first, Expression second)
    {
        this.first = first;
        this.second = second;
    }
}

class Min: Operation 
{ 
    public Min  (Expression first, Expression second): base(first, second) {} 
    public override double Eval() { return Math.Min(First.Eval(), Second.Eval()); }
    public override string ToString() { return "Min(" + First.ToString() + ", " + Second.ToString() + ")"; }
}

class Max: Operation 
{ 
    public Max(Expression first, Expression second): base(first, second) {} 
    public override double Eval() { return Math.Max(First.Eval(), Second.Eval()); }
    public override string ToString() { return "Max(" + First.ToString() + ", " + Second.ToString() + ")"; }
}

class Plus: Operation 
{ 
    public Plus(Expression first, Expression second): base(first, second) {} 
    public override double Eval() { return First.Eval() + Second.Eval(); }
    public override string ToString() { return First.ToString() + " + " + Second.ToString(); }
}

class Minus: Operation 
{ 
    public Minus(Expression first, Expression second): base(first, second) {} 
    public override double Eval() { return First.Eval() - Second.Eval(); }
    public override string ToString() { return First.ToString() + " - " + Second.ToString(); }
}

class Mul: Operation 
{ 
    public Mul(Expression first, Expression second): base(first, second) {}
    public override double Eval() { return First.Eval() * Second.Eval(); }
    public override string ToString() { return First.ToString() + " * " + Second.ToString(); }
}

class Div: Operation 
{ 
    public Div  (Expression first, Expression second): base(first, second) {} 
    public override double Eval() { return First.Eval() / Second.Eval(); }
    public override string ToString() { return First.ToString() + " / " + Second.ToString(); }
}

public class Program
{
    public static void Main(string[] arguments)
    {        
        Expression expression = new Plus(new Literal(1.23), new Min(new Literal(3.45), new Literal(1.23)));
        Console.WriteLine("Expression '{0}' = {1}", expression.ToString(), expression.Eval());
    }
}
Re[4]: Функциональное программирование в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.05.07 21:22
Оценка:
Здравствуйте, <Аноним>, Вы писали:

VD>>В чистом ООП оно имеет смысл, так как упрощает равитие системы, при наличии паттерн-матчинга оно попросту бессмысленно.

А>А главное отжирает по три строке в каждом классе. Я к тому, что в том примере C# и Nemerle сравнивались нечестно, за счет чего и получилась, столь впечатляющая разница в объеме кода в строках. В килобайтах, кстати не так много, не в 5 раз, а в 3.

Ох уж мне эти приверженцы единственно правильных решений.

Отжирается конечно не по три строки. В приличном ОО-обществе принято каждый класс помещать в тдельный файл, а значит для каждого из них дублируется просторанство имен, using-и и прочая дрибедень. Здесь svn://rsdn.ru/RSharp находятся исходники R# который я создал до знакомства с Nemerle. Уверя, что если бы я писал подобный код сейчас и на Nemerle, то он был бы не в 3 или 5 раз меньше, а раз в 10.

VD>>2. Это очень примитивный случай. В нем паттерн-матчинг действительно не так сложно эмулировать на операторах is/as. Но с разрастанием кода станет очевидным, что эмуляция хуже оригинала. Как я говорил в статье, паттерн-матчинг поддерживеет сложные вложенные паттерны, что значительно увеличивает наши возможности. Например, если нам понадобиться распознать некий паттерн в коде (ну скажем упростить мат.выражения), то с паттерн-матчингом прийдется добавить всего пару строк кода, а в императивном коду это уже красиво не выразить. Прийдется лепить кучи if-ов.

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

Понимаю, что мышление человека инерно. По этому предлагаю начать с малого. Давай расширим оба примера поддержкой фунций с 3 и 5 параметрами. Причем на этот раз ты продемонстриуешь свое решение первым.

Вторая здачка будет интереснее. Произвольная трансформация выражений. Берем исходное выражение применяем к нему некоторую функцию в параметах которой задем условия трасформации и получаем на выходе трансформированное (оптимизированное выражение). Для простоты, в качестве теста, будем использовать следующую оптимизацию — если выражение преставляет из себя "<любое выражение> * 1", то заменяем его на "<любое выражение>". Причем подразумевается, что это всего лишь один из возможных вариантов замены. Другими словами вызвав код вида:
expr = expr.Convert(<условия преобразования>);

мы должны получить преобразованное выражение.
Например:
До трансформации
Expression '1.23 + max(1, 2) * 1' = 3.23

После трансформации
Expression '1.23 + max(1, 2)' = 3.23

Задача понятна?
Теперь ход что называется за тобой. Ты представляешь свое решение, а затем я демонструю свое. Кстити, свое я уже написал .

VD>>Ну, и надо заметить, что кода все равно значительно больше чем на Nemerle, хотя и не так много как в чисто ОО-решении.

А>В этом и мысль.

В чем? В том, что ты потерял все приемущество ООП, но все равно не достиг такой же ясности и простоты кода?

А> Конечно превосходство Nemerle очевидно при сравнении 250 строк кода на С# и 50 строк кода на Nemerle, однако если аналогичный код на С# легко умещается в 80 строк, преимущество Nemerle испаряется.


Знаешь, многие были бы счасливы иметь 50 строк вместо 80, но на практике предпочитают 250, так как пользоваться инструментами вроде Nemerle они не умеют или боятся, а используя ООЯ прибегают к классическим паттернам проектирования приводящим именно к 250-строчному коду. И я их понимаю (правда, понимаю только в выборе паттернов, но не инструмента и парадигмы).

VD>>К тому же в нем ради "укомпакчивания" кода бвли допущены разные вольности вроде наличия Value у всех выражений хотя только оно нужно только у литералов.

А>Этого нет, Value только у Literal'ов.

Ой. Сори. Это я невнимательно смотрел код. Ну, да когда ты попыташся добавить поддеркжу метода с 3 и т.п. параметрами ты увидишь, что косяки поползут сами собой. А уж пример с оптимизацией, надесь, приведет к полному прозрению.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.