DevTalk#06 – O programowaniu funkcyjnym z Michałem Łusiakiem

25

michal_lusiakOd razu po Nowym Roku wracamy z mocnym uderzeniem: na warsztacie tym razem znalazło się programowanie funkcyjne! Mój gość to Michał Łusiak – programista, prelegent, blogger. Możecie go znaleźć również na Twitterze: @mlusiak.

W temacie programowania funkcyjnego rozprawiamy o tym po co odchodzić od “standardowego” obiektowego podejścia, jakimi językami warto się zainteresować a nawet: jak zacząć z F# nie mając możliwości jego komercyjnego zastosowania w żywym projekcie. Pojawiają się też wzmianki o wielu interesujących narzędziach i bibliotekach.

Konkurs: firma Tretton37, w której pracuje Michał, sponsoruje książkę “Real-World Functional Programming“. Tak jak już bywało, otrzyma ją autor jednego z komentarzy pod niniejszym postem. Autora tego wybierze Michał, dzisiejszy Gość. Komentujcie, pytajcie, dzielcie się doświadczeniami!


Montaż odcinka: Krzysztof Śmigiel.
Ważne adresy:

Linki:

Tretton37

 


Muzyka wykorzystana w intro:
“Misuse” Kevin MacLeod (incompetech.com)
Licensed under Creative Commons: By Attribution 3.0
http://creativecommons.org/licenses/by/3.0/
Share.

About Author

Programista, trener, prelegent, pasjonat, blogger. Autor podcasta programistycznego: DevTalk.pl. Jeden z liderów Białostockiej Grupy .NET i współorganizator konferencji Programistok. Od 2008 Microsoft MVP w kategorii .NET. Więcej informacji znajdziesz na stronie O autorze. Napisz do mnie ze strony Kontakt. Dodatkowo: Twitter, Facebook, YouTube.

25 Comments

  1. Względem programowania funkcyjnego odnoszę wrażenie, że mam wyprany mózg obiektówka. Pomimo tego, ze konstrukcje językowe F# są dość klarowne i zrozumiałe, to przeskoczenie na realny projekt jest jakieś takie problematyczne. Trzeba próbować i próbować, aż furtka w głowie się otworzy, a trybiki ruszą. Nie ma innej rady!

  2. Pingback: dotnetomaniak.pl

  3. Fajne naprawdę fajne. Nie ma takiego bullshitu typu “super nie można bez tego żyć”, “projekt bez tego to bad practice”. Szczerze i na temat. WINCYJ

  4. Fajny podcast. Scala brzydkim językiem jest no ale chociaż dość popularnym – przynajmniej w Londku.

    Wśród języków funkcyjnych Clojure to mój faworyt :)

  5. siararadek on

    Że dać się napisać cały projekt w F# przekonywał jeden z pracowników Credit Suisse na spotkaniu grupy .NET we Wrocławiu mówiąc, że 99% kodu u nich w jednym z dużych projektów jest napisany w F#. Mnie bardzo zainteresowało testowanie w F# bo z tego co widzę jest o wiele bardziej czytelniejsze niż testy w C#.

  6. Bardzo ciekawy odcinek. Tylko dwie uwagi, Lisp jest językiem wieloparadygmatowym, z własną, skrajnie odmienną od znanej Javy czy C# implementacją obiektowości. Clojure natomiast nie jest implementacją Common Lispa na JVM, tylko nowym językiem.

  7. Niestety trochę się zawiodłem na tym odcinku, ale to “na własne życzenie”. Na co dzień programuję za $$$ w języku funkcyjnym (akurat “źle” wspominana Scala) i spodziewałem się, że podejmiecie jakieś grube, zaawansowane tematy, a tymczasem po prostu sobie porozmawialiście, co zapewne biorąc pod uwagę medianę wiedzy słuchaczy na temat FP (tak “strzelam”), jest jak najbardziej uzasadnione.

    Do tego moja refleksja na koniec była taka, że jako początkujący chyba nie zainteresowałbym się po tym podcaście F#, bo trochę w treści zabrakło porządku. Chcąc uzyskać taki efekt (ale nie wiem czy takie było zamierzenie), wydaje mi się, że lepiej spisałoby się, gdybyście na początku porozmawiali o pryncypiach programowania funkcyjnego (na przykładzie F#), a potem skupili się na tym dlaczego to może być fajne/lepsze od podejścia tradycyjnego. Trochę w tej dyskusji nie było porządku i tu trochę pattern-matchingu, trochę list, trochę optionów i w sumie to nie wiadomo po co/dlaczego to wszystko. W tym natłoku tematów wydaje mi się też, że trochę ucierpiała wiedza, bo Michał zmuszony wytłumaczyć to i owo “na szybko” musiał zastosować pewne uproszczenia, które czasem nieco mijały się ze stanem faktycznym.

    Niemniej jednak dzięki – 39 minut drogi do domu zostało umilone :) Aha, na blogu brakuje jednego linku – do kursu, o którym wspomniał Michał: https://www.coursera.org/course/progfun – zrobiłem i od tego czasu zosatałem w temacie “na dłużej” = polecam!

  8. Łukasz,
    Dzięki za linka do Coursera, uciekł mi w trakcie pisania posta :)

    Co do zawartości nagrania… DevTalk raczej nigdy nie będzie podcastem bardzo zaawansowanym technicznie. Powodów jest wiele, a trzy główne to:
    1) zarówno ja jak i Gość musielibyśmy być ekspertami żeby sensownie mówić
    2) słuchacze również musieliby być ekspertami żeby zrozumieć (i pojawia się problem: jak nie zanudzić ekspertów?)
    3) słowem “mówionym”, bez pomocy tekstu/slajdów/rysunków bardzo trudno jest wytłumaczyć skomplikowane kwestie techniczne w zrozumiały sposób, szczególnie bez uprzedniego długiego przygotowania (przed nagraniem nie uzgadniam pytań z Gośćmi, czasami tylko udostępniam planowany szkic/”spis treści”, ale bez możliwości ingerencji)

    Celem tego odcinka nie było zachęcenie do rzucenia wszystkiego i programowania w F# :). Było raczej pokazanie że takie coś istnieje, do czego “mniej więcej” służy i jak do tego podchodzić na dzień dzisiejszy. Plus: przedstawić możliwy sposób “wejścia” w temat jeśli ktoś chciałby poeksplorować dalej na własną rękę.

    Ale… może miałbyś chęć zgłosić się do mnie i nagrać bardziej zaawansowany “follow-up”? :)

  9. Jan Koprowski on

    W LISPie tak bardzo widać listy bo LISP to nic innego jak skrót od “LiSt ProcessIng”. Ale najbardziej podstawową jednostką, tak jak atom we wszechświecie, jest funkcja. W językach funkcyjnych nawet kolekcje, takie jak listy są implementowane za pomocą funkcji co bardzo wyraźnie widać w rachunku lambda przy opisywaniu czym jest para elementów. A lista to nic innego jak ciąg par, w których pierwszy element trzyma wartość a drugi “wskaźnik” na kolejną parę lub znak końca listy.

    Pattern Matching zaś przybiera formę switch-a tylko w niektórych językach. “Wypasiony switch” to jego implementacja – nie istota. Widać to świetnie na przykładzie funkcji ‘maximum z Learn Haskell for your Great Good:

    maximum’ :: (Ord a) => [a] -> a
    maximum’ [] = error “maximum of empty list”
    maximum’ [x] = x
    maximum’ (x:xs) = max x (maximum’ xs)

    http://learnyouahaskell.com/recursion

    W tej formie bardziej niż cokolwiek przypomina to przeciążanie funkcji niż switcha. A tak naprawdę to nic innego jak możliwość zrzucenia na kompilator generacji takiego “switcha”, który w sprytny sposób wybierze za nas najbardziej odpowiednią implementację funkcji do wywołania. Nam programistą pozwala to uniknąć brzydkiego warunku na zakończenie rekurencji jak na przykład tutaj:

    factorial :: (Integral a) => a -> a
    factorial 0 = 1
    factorial n = n * factorial (n – 1)

    I wszystko jasne :)

  10. @Daniel, widziałem Twoje posty o Clojure – sprawiły, że też się trochę zainteresowałem. Nie wiedziałem, że siedzisz teraz w Londynie. Tam jest bardzo fajna grupa F#-owa, jakbyś chciał się zainteresować ;) http://www.meetup.com/FSharpLondon/

    @Łukasz podeszliśmy do rozmowy tak jak mówisz, trochę chaotycznie i powody też już wyjaśnił Maciek. Ja od siebie mogę dodać, że nie jestem też super doświadczony i dlatego też niektóre moje tłumaczenia były dość kulawe ;). Bardzo chętnie dowiedziałbym się gdzie i z czym pracujesz funkcyjnie. Dobrze jest wiedzieć, które firmy fajnie cisną ten temat. Możesz odpowiedzieć tutaj, albo jakoś na priv: michal@tretton37.com :)

  11. @Maciek
    Dzięki za odpowiedź – tak jak napisałem zawiodłem się na własne życzenie, bo spodziewałem się więcej niż to faktycznie możliwe, “pretensji” więc nie mam :). Jedyne co na pewno dałoby się poprawić to pewne uporządkowanie, np. zaczęcie rozmowy od definicji FP i może np. porównania C# vs F#, przynajmniej w kluczowych cechach. W poprzednich odcinkach, np. nt. AoP takie wyjaśnienia wręcz “definicyjne” bardzo dobrze otworzyło rozmowę i np. ja – raczej zielony ludek w tym temacie od razu poczuł się pewniej.
    Co do “follow-upu” – bardzo chętnie, ale za jakiś jeszcze czas :)

    @Michał
    Dzięki w ogóle, że poruszyłeś na łamach devtalka temat FP – serce roście, jakby napisał poeta :). Ja podejście funkcyjne uprawiam, ewangelizuję, a wręcz wymuszam na ludziach w mojej własnej firmie: Iterators. Zaczynaliśmy w zupełnie innym miejscu i po odkryciu Scali zupełnie zmieniliśmy kurs i praktycznie jesteśmy teraz housem scalowym. W ogóle to jeśli by przyjrzeć się mocniej klimatom JVM-owym (czego dotnetowcy pewnie za często nie robią) to FP wyrasta tam na prawdziwą potęgę – głównie za sprawą Scali i Clojure, które są interesującą alternatywą do jakże nędznej Javy ;) (hołd należy jednak oddać Javie 8, która wprowadziła parę rozwiązań FP do core języka). Zgodnie z raportami Ważnych Ludzi okazuje się, że Scala w Polsce jest bardziej popularna niż w UK i Ger razem wziętych, choćby w samej Warszawie jest sporo firm, które robią pieniądze na Scali (lista tu http://scalawaw.github.io/ trochę niekompletna, bo można byłoby tu dodać choćby Citi Bank i jeszcze parę instytucji finansowych) – niektóre bardzo znane. Poza Warszawą bardzo mocno trzyma się także Kraków i Gdańsk, które mają całkiem duże zaplecza scalowców i firm, które pracują w tym języku (choćby VirtusLab i Scalac). Co do Clojure niestety nie mam informacji, ale pamiętam, że istnieje parę firm w Polsce, które większość swojej pracy wykonują w tym języku. Na tym jednak nie koniec, bo w kraju nad Wisłą są też firmy, które programują nawet w takiej “egzotyce” jak Haskell, np. http://flowbox.io A to tylko Polska – na świecie FP trzyma się jeszcze lepiej i czasem można się nieźle zdziwić odkrywając, że pisząc tweeta czy odrzucając zaproszenia rekruterów na Linkedzie wywołujemy kod napisany funkcyjnie w językach funkcyjnych. Naprawdę fajnie poznać ten świat i wspomniana przez Ciebie konferencja LambdaDays doskonale się do tego nadaje. W zeszłym roku było super, zachęcam wszystkich do wzięcia udziału w tegorocznej edycji!
    PS. Będziesz na LambdaDays? Chętnie wypiłbym piwko w Krk podczas tego eventu :)

  12. Dobry odcinek ale chcialbym dodac troche wlasnych doswiadczen.

    Ciekawi mnie co jest potocznie rozumiane przez ‘duzy projekt’. Czy jest to solucja ze stu projektami, czy byc moze jeden serwis ktory ‘obsluguje’ baze danych z czterystoma tabelami ? Moim zdaniem pierwszej jak i drugiej sytuacji nalezy unikac i najprawdopodobniej jest to oznaka glebszych problemow. Jezeli natomiast ‘duzy projekt’ jej systemem z autonomicznymi serwisami ktore komunikuja sie w jakis luzny sposob przy uzyciu otwartych protokolow to nic nie stoi na przeszkodzie by nawet kazdy z nich napisac w innym jezyku. Ciekawy artykul o uzyciu Haskell w firmie ktorej reszta kodu byla napisana w PHP http://engineering.imvu.com/2014/03/24/what-its-like-to-use-haskell/

    A skoro juz jestesmy przy PHP, to jezeli ‘duze projekty’ sa pisane w jezyku ktory ledwo trzyma sie kupy, tzn ze wszystko sie da…

    Z mojego doswiadczenia, a wylacznie z F# pracuje od roku, nie ma wiekszych problemow by zastapic nim C# praktycznie wszedzie. Serwisy, dostep do danych roznego typu (tu dzieki Type Providers praca z danymi jest czysta przyjemnoscia i mozna sie wreszcie odciac od zarazy ORMem zwanej), wyplucie jakiegos HTMLa (nic nie stoi na przeszkodzie by uzyc istniejacych C#owych frameworkow, MVC, NancyFx, czy co tam ostatnio jest popularne). Z apkami desktopowymi nie mialem do czynienia ale z tego co slyszalem, oprocz niedogodnosci ze Visual Studio / Resharper nam za bardzo kodu nie pomoze generowac, wiekszych problemow nie ma. Kilka ostatnich tygodni spedzilem uzywajac WebSharpera (http://www.websharper.com/) i zanosi sie na to i ze Javascript porzuce na dobre.

    Chyba najwazniejsze to uswiadomic sobie ze koniec koncow CLR jest wspolne i F# jest po prostu kompilowany do IL tak jak i C#. Poza doslownie kilkoma dziwnymi konstrukcjami ktorych nawet w C# nie zdarzylo mi sie uzyc F# wspiera znakomita wiekszosc funkcjonalnosci C#. Dlatego kooperacja z kodem napisanym w C# jest w wiekszosci bezproblematyczna, w druga strone zazwyczaj trzeba napisac jakis prosty wraper poniewaz C# oferuje podzbior mozliwosci F# i niektore F#owe konstrukcje wygladaja dosc dziwnie konsumowane bezposrednio z poziomu C#.

    Jest kilka rzeczy ktorych po przesiadce z C# moze brakowac, albo moga wydawac sie ograniczeniami jak np:
    – kod musi byc napisany doslownie od ‘gory do dolu’, tzn nie mozna odwolac sie do typow ktorych kompilator jeszcze nie odczytal. Oznacza to mniej wiecej ze nie tylko funkcje i typy musza byc zdefiniowane w pliku w prawidlowej kolejnosci ale takze kolejnosc plikow w projekcie ma znaczenie. Moze to sie wydawac dziwne i bardzo ograniczajace ale jest to chyba jedna z wiekszych zalet tego jezyka (i calej rodziny ML).
    Wiecej na ten temat: http://fsharpforfunandprofit.com/posts/cyclic-dependencies/
    – Visual Studio nawet w odslonie 2013 traktuje F# troche po macoszemu i takie rzeczy jak np reorganizacja plikow mocno kuleja. F# Power Tools poprawiaja sprawe ale i tak nie jest to poziom do ktorego jestesmy przyzwyczajeni w C#. Z drugiej strony zazwyczaj jest to znacznie mniejszym problemem bo w F# po prostu nie tworzy sie wielu plikow bo nie ma potrzeby. Kod jest zdecydowanie bardziej zwiezly i zasada plik per klasa przestaje byc problemem.

    Osobiscie dla mnie najwazniejsze po przesiadce na F# bylo to ze odzyskalem przyjemnosc z programowania ktora bylo dosc nadwyrezona ORMami, IOC i innymi niepotrzebynmi komplikacjami.

    Artykul z dobrymi argumentami nt stanu adopcji F# w srodowisku .NET: http://ericsink.com/entries/fsharp_chasm.html

    Rozpisalem sie bardziej niz na maturze z jezyka polskiego… Mam nadzieje ze te moj mocno zopiniowany komentarz bedzie komus przydatny :-)

  13. Jestem bardzo zawiedziony odcinkiem. To z powodu gościa. W komentarzach widzę, że inni nie. Może jestem zbyt wymagający, ale nie rozumiem po co zapraszać do rozmowy o F# kogoś kto jak sam mówi prawie nie ma doświadczenia w tym języku?
    Ma projekty rozkopane, bo mu się nie chce, ale zamierza “kontrybuować” w innych. W sumie to w F# nie pisze, no może testy, ale bardzo krótko i na razie w sumie nie wie, czy są fajne. Tylko tyle, że nazwy metod ładnie wyglądają. Nie za bardzo potrafi opowiedzieć o czymkolwiek w F#.

    Do tego taka osoba prowadzi prelekcje po całej Polsce, czy na internetowych konferencjach…

    Nie trzeba być ekspertem, aby czegoś uczyć. Zgoda. Ale bez przesady. To już raczej (patrząć tylko na komentarze) to Dawid Kowalski powinien być gościem tego odcinka.

    Do tego “zajebiste”, “mindfuck” itp.

  14. Jam co prawda dżaważ, ale widzę, że komentatorzy podchodzą do tematu głębiej, więc pozwolę sobie dodać kilka myśli do przedyskutowania (abstrahując od nagrania, bardziej ogólnie o FP):

    1. OO vs FP
    Widziałem wiele prezentacji na ten temat i niestety był tam zastosowany chwyt erytrystyczny Strawman (przedstaw wroga tak aby było łatwo po pokonać). Mamy zatem “abiektawe” programowanie, czyli encje anemiczne i serwisy, czyli Pascal, czyli proceduralne. I jest ono miażdżone przez FP.
    Moim zdaniem dobrze zrobione OO jest bardzo, bardzo blisko FP. Trzymając się: SOLID, GRASP i 4 zasad OO dochodzimy chcąc nie chcąc do kilku elementarnych wzorców, które są defacto funckcjami, np z grubej rury: fabryka dekorowanych strategi, czyli funkcja (fabryka) zwracjąca funkcję (strategię), która jest w innym miejscu domknięciem (closure) innej higher order…
    “Jednyny” problem: siermiężna, barokowa składnia:/

    2. Myślenie zachowaniami
    Jeżeli robimy porządne OO (np dzięki DDD lub po prostu 2 pierwszym punktom paradygmatu OO:P ) to zaczynamy od zachowań. Teraz to już kwestia składni, czy będzie barokowa w obiektach udających funkcje, czy w języku bardziej odpowiednim, ale moim zdaniem kluczowe jest myślenie zachowaniami.
    Można używać języka FP a wcale nie myśleć w sposób funkcyjny – jedynie masturbując się zgrabną składnią filtrowania kolekcji;)
    Swoją drogą boli mnie nieco to, że twórcy i ewangelizatorzy rzadko kiedy potrafią podać przykład poza kolekcjami… W sumie się nie dziwię, bo pracując nad kompilatorem, bo kolekcję będą tak na prawdę “grubą” domeną biznesową. Ale większość z nas, twórców softu biznesowego skorzysta z czegoś takiego jak np. polityka w DDD

    3. Synergia
    Nie lubię tego słowa, ale go użyję. Moim zdaniem świadomy projektant zgrabnie może posługiwać się paradygmatem OO, FB i Proc, łącząc je ze sobą nawet w jednym pliku źródłowym. Przykładowo: Warstwa Serwisów aplikacyjnych (API) to nic innego jak procedury, które orkiestrują domenę: obiekty (np. Agregaty) i funckje (np. Polityki domykające Agregaty)

    Nieco na ten temat można posłuchać na początku mojej prezentacji o ORM: https://www.youtube.com/watch?v=uj25PbkHb94
    jak również tutaj rzucić okiem: http://bottega.com.pl/pdf/materialy/receptury/orm.pdf

    Moim zdaniem używanie języka, który byłby w “faszystowski” sposób czysto funkcyjny może być mocno ograniczające. Bo czy aby na pewno wszystko jest funkcją? Ale wszystko? Pewnie można to tak wyabstrahować, ale model może nie być naturalny w niektórych miejscach i tracimy komunikację z ekspertem domenowych. I wówczas zaczyna się upadek projektu na twarz, ale to już pewnie każdy duży chłopiec i dziewczyna zaliczył:)

    4. Modelowanie
    Tutaj dochodzę do problemu, który mam jeszcze nie rozwiązany…
    Jak modelować funkcyjnie, gdzie model rozumiem w sensie DDD, czyli narzędzie do gromadzenia wiedzy o działaniu biznesu i do komunikacji? Czy używanie jedynych building blocków do wyrażenia modelu z puli chwytów funkcyjnych jest dobre? Czasem na pewno tak, a czasem może doprowadzić do kuriozalnych potworków – to na pewno zależy od domeny. Nie mam tutaj jednak doświadczenia z modelami czysto funkcyjnymi… pewnie w domenach “matematycznych” byłby to strzał w 10.

  15. @Łukasz, będę i bardzo chętnie się spotkam :)

    @Marek zajebiście (:P) cieszy mnie Twój komentarz, bo w głowie bardzo się z nim zgadzam. Też nie rozumiem, czemu Maciek mnie zaprosił ;) Jestem świadom, że są ludzie znacznie bardziej obyci z tematem i w żadnym miejscu nie twierdze że jestem w jakimkolwiek stopniu ekspertem. Raczej świeżym pasjonatem, ale nie sądzę, żeby to był powód aby ekscytacją się nie dzielić.

    @Dawid, Sławek – bardzo ciekawe uwagi, dzięki za te komentarze :)

  16. @Marek, pytanie tylko, co miałby wnieść do tej mimo wszystko poglądowej rozmowy ekspert? Pamiętam jak jakieś dwa lata temu trafiłem na “minicykl” Maćka dotyczący testowania. W kontekście mojej obecnej wiedzy mogę śmiało napisać, że wpisy te nie miały charakteru eksperckiego, ale pozwoliły mi zapoznać się z tematem i w konsekwencji stać się lepszym programistą. Właśnie dlatego jestem Maćkowi niesamowicie wdzięczny za to, co robi. Podobnie traktuję rozmowę z Michałem. Już sklonowałem FSharpKoans i zapoznaję się z F#.

    Odnośnie samego FP to zupełnie nie mam z nim doświadczenia w pracy nad “prawdziwymi” projektami. Muszę powiedzieć jednak, że ilekroć uda mi się napisać jakieś funkcyjne rozwiązanie problemu algorytmicznego, doznaję “developerskiej ekstazy” i mam wrażenie, że danego problemu nie da rozwiązać się lepiej. W związku z tym też bardzo chętnie posłuchałbym rozmowy z kimś, kto zawodowo zajmuje się FP.

    @Maciek, @Michał – wielkie dzięki za świetny podcast. Już po raz kolejny Maciek ze swoim gościem wybrał się ze mną w góry :)

  17. @all: dzięki za takie wypasione komentarze, bardzo wartościowe i interesujące!

    @Marek: ja się dowiedziałem czegoś nowego podczas rozmowy i z komentarzy wynika, że inni też… więc mission accomplished; być może będzie ciąg dalszy z kimś bardziej doświadczonym, zawsze czekam na zgłoszenia chętnych do wzięcia udziału

    @Tomek: dzięki za miłe słowo ;)

  18. Maciek poprosił mnie, żebym dzisiaj rozstrzygnął konkurs.

    A więc książka leci do Dawida Kowalskiego za rzeczowy komentarz z ciekawymi spostrzeżeniami, który fajnie rozszerza naszą rozmowę.

    Dzięki wszystkim za dyskusję!

  19. Ja też się trochę zawiodłem na tym odcinku :(.
    Swoją przygodę z F# zacząłem dawno temu. Przerobiłem parę tutoriali, napisałem parę drobnych programów.

    Wydaje mi się, że świetnym wprowadzeniem jest Project Euler — https://projecteuler.net/problems.

    Ja tak zrobiłem: https://github.com/ggierlik/FSharp.Euler.Problems.
    Proste (na początku) problemy i co więcej — wymarzone do funkcyjnej implementacji (rekursja, przetwarzanie list, pipelining).

    Jeżeli ktoś nie wie jak zacząć to Project Euler jest chyba dobry na start — szybko widać efekty.

    Z mojego doświdczenia:
    * parę problemów rozwiązałem w 5-10 minut, w paru liniach kodu i zadziałało od pierwszego razu (jeden od przeczytania do zaliczenia w ok. 3 minuty) — naprawdę robi wrażenie.
    * są problemy (np. 17) które doskonale nadają się do wypróbowania unit testów/TDD (ja używałem FSUnit, gdzie testy można zapisywać tak "ships" |> should startWith "sh".

  20. Trochę tutaj chyba nakłamaliście :)

    Genericsy nie były przeniesione z F# do C#. Powstawały już w 1999.
    Również nie jest prawdą, że FAKE, Rake, Psake są nakładkami na MSBuild. MSBuild jest przez nie wykorzystywany tylko do zrobienia Builda (bo skrypt MSBuild-owy już macie – plik sln). I to jest wszystko do czego MSBuild się nadaje :)

  21. Piotr,
    Co do genericsów to nie mam pojęcia, nie wypowiadam się, ale co do MSBuild: zgadzam się kompletnie, że nadaje się tylko do “build” ;). I w tym sensie inne rozwiązania to nakładki, bo wykonują msbuildowe “build” :). Ja dostaję furii jak mam w MSBuild bezpośrednio skopiować jakieś pliki – nigdy nie potrafię zrozumieć jak działają jego mechanizmu include/exclude, zwykle inaczej niż bym się spodziewał.