wizzard: (Default)
[personal profile] wizzard

Никогда не возникало желания добавить в C# свой оператор? Или добавить бинарный оператор над встроенными типами, например…
Идея не нова, синтаксис подсмотрен в Хаскеле. И достаточно много boilerplate code. Но как DSL – вроде красиво.

Надо подумать, что с этим можно сделать и как можно более красиво конвертировать ф-и в операторы.

Использование:

private static void ArithmeticExample()
{
Func<int, int, int> _sum = (a, b) => a + b;
Func<int, int, int> _mult = (a, b) => a * b;
var sum = _sum.Infixize();
var mult = _mult.Infixize();




Console.WriteLine(1 |sum| (2 |mult| 4) |sum| 8); //17
}

private static void PoorMansLINQ()
{
Predicate<int> odd = x => x % 2 != 0;
// why the type inference is unable to do this?
Func<IEnumerable<int>, Predicate<int>, IEnumerable<int>> _where = Where;
var where = _where.Infixize();
Func<IEnumerable<int>, Func<int, int>, IEnumerable<int>> _Map = Map;
var perform = _Map.Infixize();
Func<IEnumerable<int>, IEnumerable<int>, IEnumerable<int>> _Join = Join;
var join = _Join.Infixize();
Func<IEnumerable<int>, IEnumerable<int>, IEnumerable<int>> _Intersect = Intersect;
var intersect = _Intersect.Infixize();



foreach (var x in Enumerable.Range(0, 10)
|where| odd |perform| SideEffectPrint) ; // 1 3 5 7 9

Console.WriteLine();

foreach (var x in
Enumerable.Range(0, 5) |join| Enumerable.Range(10, 5) |intersect| Enumerable.Range(3,10)
|perform| SideEffectPrint) ; //3 4 10 11 12

Console.ReadLine();
}


Реализация:



public static class InfixExtensions
{
public static InfixOperator<T1, T2, RT> Infixize<T1,T2,RT>(this Func<T1, T2, RT> f)
{
return new InfixOperator<T1, T2, RT>(f);
}
}
/// <summary>
/// TODO: Curryable Infix Operator
/// </summary>
/// <typeparam name="T1">Left operand type</typeparam>
/// <typeparam name="T2">Right operand type</typeparam>
/// <typeparam name="RT">Return type</typeparam>
public class InfixOperator<T1,T2,RT>
{
Func<T1, T2, RT> function;
T1 leftvalue;
public InfixOperator(Func<T1,T2,RT> f)
{
this.function = f;
}
public InfixOperator(T1 lv, Func<T1, T2, RT> f)
{
this.function = f;
this.leftvalue = lv;
}
public static RT operator |(InfixOperator<T1,T2,RT> a, T2 b)
{
return a.function(a.leftvalue, b);
}
public static InfixOperator<T1,T2,RT> operator |(T1 a, InfixOperator<T1,T2,RT> b)
{
return new InfixOperator<T1,T2,RT>(a, b.function);
}
}



(will be screened)
(will be screened if not validated)
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

Profile

wizzard: (Default)
wizzard

January 2019

S M T W T F S
  12 345
6789101112
1314 1516171819
202122 23242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 12th, 2026 10:45 pm
Powered by Dreamwidth Studios