Być jak Haskell

Historia kołem się toczy, więc po raz kolejny zabieram się do programowania bardziej funkcyjnego. Obejrzałem film  Refactoring to Functional. a ponieważ jego autor Hadi Hariri pracuje obecnie dla JetBrains, to uznałem, że temat trzeba potraktować poważnie.

W C# mamy dobrodziejstwa Linq, jednakże istnieje, że jego uniwersalność jest okupiona dużym narzutem. Unikam zatem Linq w miejscach, gdzie może on być źródłem kłopotów wydajnościowych. Ponieważ nic nie może przebić piękna i prostoty pętli FOR, stosowałem ją tam gdzie podejrzewałem, że Linq może nie dać rady. Stąd też poniższy, przykładowy kod.

W pętli obliczana jest sumaryczna długość linii łamanej określonej przez tablicę punktów Points . Może nie ruszyłbym tego kodu, gdyby nie druga inspiracja, film Michała Bartyzela,  Jak zniszczyć swój kod — podstawy lingwistyki dla programistów.

Postanowiłem wykorzystać zalety programowania funkcyjnego ale nie w oparciu Linq, zwłaszcza że obliczenia bazują nie tyle na kolejnych elementach kolekcji co na parach sąsiadujących elementów. Zapytanie Linq zamieniające sekwencję elemntów na sekwencję par mogłoby być karkołomne i zaciemnić kod zamiast go uprościć, t.j.

Powyższy kod zainspirowany http://stackoverflow.com/questions/1624341/getting-pair-set-using-linq.

Kod własności Length zamieniłem na taki.

z użyciem ExtensionMethod

Wadą tego rozwiązania jest to, że nie sprawdzam czy w trakcie działania metody FoldPairs lista źródłowa się nie zmieniła. Klasa List<T> posiada prywatne pole _version, które jest skrupulatnie wykorzystywane przez iterator. Pole to jednakże nie jest – poza mechanizmami refleksji – możliwe do uzyskania. Istnieje jednak bardzo wiele scenariuszy, w których rozwiązanie takie jest wystarczające. Zawsze można dopisać alternatywną wersję metody, która wykorzystując enumerator będzie czuwała nad niezmiennością listy.

Zaleta jest taka, że czytelność kodu jednak się poprawiła. W środku mam swoją pętlę for, więc nie korzystam z iteratorów, enumeratorów i innych elementów.

Węsząc za pętlami for

Przy okazji starałem się w prosty sposób przeszukać kod źródłowy w poszukiwaniu pętli for zaczynających się od zera. Prosty (choć nie wolny od wad) regexp, którego używłem wygląda tak:

Odnośniki