Re[5]: Функциональное программирование в Nemerle
От: Аноним  
Дата: 15.05.07 19:16
Оценка: :))
Здравствуйте, VladD2, Вы писали:

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


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

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

Не мог вечером зайти в форум, какая-то ошибка, связанная с Dictionary Key, поэтому вечером писал по-памяти, что прочитал с утра, так что требования не соблюдены точно, но достаточно изоморфны.

150 строк, пока в c# не разочаровался.

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

abstract class Expression
{
  public abstract double Eval();
  public abstract override string ToString();
  public abstract void RemoveOneParameterMin(ref Expression expression);
}

class Literal : Expression
{
  double value;
  public Literal(double value) { this.value = value; }
  public override double Eval() { return value; }
  public override string ToString() { return value.ToString(); }
  public override void RemoveOneParameterMin(ref Expression expression) { }
}

abstract class Operation : Expression
{
  protected 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;
  }
  public override void RemoveOneParameterMin(ref Expression expression)
  {
    first.RemoveOneParameterMin(ref first);
    second.RemoveOneParameterMin(ref second);
  }
}

class Addition : Operation
{
  public Addition(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 Subtraction : Operation
{
  public Subtraction(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 Multiplication : Operation
{
  public Multiplication(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 Division : Operation
{
  public Division(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(); }
}

abstract class Call : Expression
{
  protected Expression[] expressions;
  public Expression[] Expressions { get { return expressions; } }
  public Call(params Expression[] expressions) { this.expressions = expressions; }
  protected string Join(string splitter)
  {
    if (expressions.Length == 0) return "";
    StringBuilder stringBuilder = new StringBuilder();
    foreach (Expression expression in expressions)
    {
      stringBuilder.Append(expression.ToString());
      stringBuilder.Append(splitter);
    }
    return stringBuilder.Remove(stringBuilder.Length - splitter.Length, splitter.Length).ToString();
  }
  public override void RemoveOneParameterMin(ref Expression expression)
  {
    for (int index = 0; index < expressions.Length; index++ )
    {
      expression.RemoveOneParameterMin(ref expressions[index]);
    }
  }
}

abstract class AtLeastOneParameterCall : Call
{
  public AtLeastOneParameterCall(Expression first, params Expression[] expressions) : 
    base(AtLeastOneParameterCall.Concat(first, expressions)) { }
  private static Expression[] Concat(Expression first, params Expression[] expressions)
  {
    List<Expression> list = new List<Expression>(expressions);
    list.Insert(0, first);
    return list.ToArray();
  }
  protected delegate void CompareValues(double current, ref double value);
  protected double FindValue(CompareValues compareValues)
  {
    double value = expressions[0].Eval();
    for (int index = 1; index < expressions.Length; index++)
    {
      compareValues(expressions[index].Eval(), ref value);
    }
    return value;
  }
}

class Min : AtLeastOneParameterCall
{
  public Min(Expression first, params Expression[] expressions) : base(first, expressions) { }
  public override string ToString() { return "Min(" + Join(", ") + ")"; }
  public override double Eval() { return FindValue(ChooseMin); }
  private void ChooseMin(double current, ref double value) { if (current < value) value = current; }
  public override void RemoveOneParameterMin(ref Expression expression)
  {
    if (expressions.Length == 1) 
    { 
      expression = expressions[0]; 
    }
    else 
    {
      base.RemoveOneParameterMin(ref expression); 
    }
  }
}

class Max : AtLeastOneParameterCall
{
  public Max(Expression first, params Expression[] expressions) : base(first, expressions) { }
  public override string ToString() { return "Max(" + Join(", ") + ")"; }
  public override double Eval() { return FindValue(ChooseMax); }
  private void ChooseMax(double current, ref double value) { if (current > value) value = current; }
}

public class Program
{
  public static void Main(string[] arguments)
  {
    // Min(1.23, 2.34 + Min(3.45))
    Expression expression = new Min(new Literal(1.23), new Addition(new Literal(2.34), new Min(new Literal(3.45))));
    Console.WriteLine("Expression '{0}' - {1}.", expression.ToString(), expression.Eval());
    expression.RemoveOneParameterMin(ref expression);
    Console.WriteLine("Expression '{0}' - {1}.", expression.ToString(), expression.Eval());
    Console.ReadLine();
  }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.