Programowanie funkcyjne w C#

0

Dużo programowałem kiedyś w javascript i po przesiadce na C# łapię się że często ułatwiam sobie życie pisząc funkcje wewnątrz funkcji

Przykładowy, prosty kod:

int start = 7;
int end = a * b;
Console.WriteLine(start + " - " + end);
skomplikowaneOperacje(start, end);

for (int b = 0; b < 10; b ++)
{
    start = end;
    end = b * 5 + a;
    Console.WriteLine(start + " - " + end);
    skomplikowaneOperacje(start, end);
}

if (c)
{
    start = end;
    end = a * 9 - b;
    Console.WriteLine(start + " - " + end);
    skomplikowaneOperacje(start, end);
}

żeby się nie powtarzać mógłbym to zapisać w postaci pomocniczej klasy:

class Helper
{
    int start;
    int end;
    Action<int, int> operacja;

    public Helper(int start, Action<int, int> operacja)
    {
        this.operacja = operacja;
        this.start = start;
    }

    public void To(int end)
    {
        Console.WriteLine(start + " - " + end);
        start = end;
        operacja(start, end);
    }
}

której można używać potem w ten sposób:

var h = new Helper(7, skomplikowaneOperacje);

h.To(a * b);
for (int b = 0; b < 10; b ++)
{
    h.To(b * 5 + a);
}
if (c)
{
    h.To(a * 9 - b);
}

i byłoby to zgodne z ideą programowania obiektowego.
Ale często łapię się na naleciałościach z javascript i z lenistwa nie piszę nowej klasy, a wolę sobie to uprościć zapisując to jako:

int start = 7;

Action<int> f = end =>
{
    ConsoleWrite(start + " - " + end);
    start = end;
    skomplikowaneOperacje(start, end);
}

f(a * b);
for (int b = 0; b < 10; b ++)
{
    f(b * 5 + a);
}
if (c)
{
    f(a * 9 - b);
}

Pytanie brzmi - czy widząc taki kod byście mnie rozstrzelali, czy jest to dla innych równie czytelne co dla mnie? Czy wystrzegać się tego typu konstrukcji równie mocno co używania goto?

0

zakładamy że powtarzanego kodu by było więcej a to tylko uproszczony przykład

wiem też że można to zapisać na przykład jako metodę ze skutkiem ubocznym:

void To(ref int start, int end)
{
    ConsoleWrite(start + " - " + end);
    start = end;
    skomplikowaneOperacje(start, end);
}

i na dziesiątki innych sposobów. Chodzi mi o to czy ten konkretny sposób jest potępiany

1

#Przykro mi, ten kod nie ma nic wspólnego z programowaniem funkcyjnym.
#Mi też się nie chce pisać klasy do każdych 3 linijek. Moim zdaniem po to wymyślili ludzie prywatne metody w klasach, żeby można było tworzyć funkcje pomocnicze.
#Za takie nazewnictwo nabijałbym ludzi na pal, a potem wrzucał na stos, żeby mieć absolutną pewność, że delikwent jest skończony.

0

Przeczytaj jeszcze raz co napisałem; chodzi o używanie anonimowych funkcji / procedur zamiast używania prywatnych metod i Wasze zdanie na ten temat.

Kod pisany na kolanie podczas pisania posta, chodziło o to żeby nazwy nic nie mówiły żeby nie naprowadzały na konkretne użycie</quote>

0

Przecież dokładnie odpowiedziałem na Twoje pytanie. Wpychanie całego kodu do lambd jest słabe. Nie widzę absolutnie żadnego powodu, dla którego takie zastosowanie miałoby jakiś większy sens.

Edit:
Teoretycznie to możesz nawet metod nie pisać, tylko same lambdy, np. tak:

using System;

public class Test
{
	public Func<int> GimmeInt { get; private set; }
	
	public Test() {
		GimmeInt = () => 3;
	}
	
	
	public static void Main()
	{
		var test = new Test();
		Console.WriteLine(test.GimmeInt());
	}
}

Ale nie wiem co ktoś miałby czymś takim osiągnąć poza zaciemnianiem kodu.

IMO najlepiej nawyki z jednego języka, zostawić w tym języku, w którym mają jakiś sens, a przy nauce nowego języka uczyć się nowych nawyków.

0

czasami zdarza się algorytm który operuje na kilku zmiennych wewnętrznych

do wyboru mamy wtedy albo stworzyć osobną metodę która będzie wywoływana tylko z jednej metody i może ona wtedy przybierać nawet kilka wartości z oznaczeniem ref, lub lambdę która z góry będzie miała dostęp do zmiennych lokalnych funkcji i nie trzeba ich jawnie przekazywać

Moim zdaniem po to wymyślili ludzie prywatne metody w klasach, żeby można było tworzyć funkcje pomocnicze.

istnieje też ideologia która mówi że powinny istnieć tylko metody publiczne, a jeśli mamy potrzebę stworzenia prywatnej metody to prawdopodobnie łamiemy zasadę single responsibility i funkcjonalność ta powinna być wydzielona do osobnej klasy

0

do wyboru mamy wtedy albo stworzyć osobną metodę która będzie wywoływana tylko z jednej metody i może ona wtedy przybierać nawet kilka wartości z oznaczeniem ref, lub lambdę która z góry będzie miała dostęp do zmiennych lokalnych funkcji i nie trzeba ich jawnie przekazywać

Możemy też stworzyć prywatna metodę przyjmującą kontekst algorytmu w postaci obiektu i zwracającą zmodyfikowany ów kontekst. Nie wiem po co utrudniać sobie debuggowanie i zmniejszać czytelność efektami ubocznymi i implicit domknięciem w takim przypadku.

istnieje też ideologia która mówi że powinny istnieć tylko metody publiczne, a jeśli mamy potrzebę stworzenia prywatnej metody to prawdopodobnie łamiemy zasadę single responsibility i funkcjonalność ta powinna być wydzielona do osobnej klasy

Hm. Ciekawe. Kto głosi taką teorie?

0
n0name_l napisał(a):

Hm. Ciekawe. Kto głosi taką teorie?

nie znam jakiegoś autorytetu ale często można się z takim stwierdzeniem spotkać
wpisując w google single responsibility principle private methods można się natknąć na parę

oczywiście nikt nie napisał że w ogóle należy się pozbyć prywatnych metod, ale zazwyczaj faktycznie można dostrzec brak SRP i utrudnienie tworzenia testów (bo metod prywatnych nie przetestujemy). Ale tak samo nie przetestujemy lambd i nie o tym miał być temat

Pytanie było proste - czy wrzucilibyście taki kod do tematu "wtf" czy może wzięlibyście go za fanaberie ale nie mieli z nim problemu
Wiadomo że wszystko da się zrobić inaczej

0
Baltazar Pąpka napisał(a):

oczywiście nikt nie napisał że w ogóle należy się pozbyć prywatnych metod, ale zazwyczaj faktycznie można dostrzec brak SRP

SRP dotyczy klas, nie metod. To klasa ma mieć jedną odpowiedzialność, i często oznacza to, że klasa ma jedną metodę publiczną. A prywatne metody tworzy się według potrzeb.

i utrudnienie tworzenia testów (bo metod prywatnych nie przetestujemy).

Przetestujemy testując metodę publiczną. Jeśli prywatnych nie da się przetestować w ten sposób, to znaczy, że są niepotrzebne.

Pytanie było proste - czy wrzucilibyście taki kod do tematu "wtf" czy może wzięlibyście go za fanaberie ale nie mieli z nim problemu

Raczej niczego dłuższego niż jedna linijka bym w ten sposób nie napisał.

1 użytkowników online, w tym zalogowanych: 0, gości: 1