Home > Blockchain >  Functional programming in C#, how can I convert this imperative method into functional approach?
Functional programming in C#, how can I convert this imperative method into functional approach?

Time:08-07

I'm trying to convert my business logics, and many of my code are like this:

public Result1 Logic1(int a)
{
  var b = ComputeByA(a);
  var c = ComputeByB(b);
  var d = ComputeByC(c);
  return new Result1()
  {
    B = b, C = c, D = d
  }
}

public Result2 Logic2(int a)
{
  var b = ComputeByA(a);
  var e = ComputeByB2(b);
  var f = ComputeByE(e);
  return new Result2()
  {
    B = b, E = e, F = f
  }
}

I need to compute values that dependent by other values, and I need them all. And some methods are reused many times, others are only used in the domain.

I tried like this :

public Result1 Logic1(int a)
{
  return 
    ComputeByA(a)
      .ComputeByB(b)
      .ComputeByC(c)
      .ToResult();
}

That method computes values well, but I cannot find good (or 'elegant') way to store b and c for result during function chains. How can I do this?

CodePudding user response:

It's not really clear what you are trying to accomplish, but I appreciate that the OP isn't your real code.

You can chain functions by echoing the input as part of the output, but in general it's not a good idea, because it's going to make the code inflexible. Unless you have very specific requirements, it's probably a better idea to go with what you already have.

Situations where the following may be appropriate is if you have to build an object piecemeal and you want to use the static type system to ensure that all steps have been invoked.

You can use custom types (classes, structs, or records) to echo back the input together with the output, or you can use tuples. Here I've just used tuples:

public static B ComputeByA(int a)
{
    return new B();
}

public static (B, C) ComputeByB(this B b)
{
    return (b, new C());
}

public static (B, E) ComputeByB2(this B b)
{
    return (b, new E());
}

public static Result1 ComputeByC(this (B b, C c) tuple)
{
    return new Result1(tuple.b, tuple.c, new D());
}

public static Result2 ComputeByE(this (B b, E e) tuple)
{
    return new Result2(tuple.b, tuple.e, new F());
}

This now gives you the ability to chain functions together:

public static Result1 Logic1(int a)
{
    return ComputeByA(a).ComputeByB().ComputeByC();
}

public static Result2 Logic2(int a)
{
    return ComputeByA(a).ComputeByB2().ComputeByE();
}

Again, unless you have specific reasons to constrain how functions can be chained, I wouldn't recommend an API design like this. If, for example, ComputeByC only requires C, then forcing callers to supply both B and C is unwarranted.

  • Related