poniedziałek, 26 maja 2014

Droga do szczęścia?

Droga do szczęścia zaczyna się niespodziewanie od czwartej edycji programowania funkcyjnego w Scali na Courserze a właściwie od tego co wyświetliło się na samym dole strony w sugerowanych kursach.

Nie wiem jakiego algorytmu oni używają do znajdywania polecanych pozycji ale w wyniku błyskotliwego wyszukiwania lub zwykłego random.next - na dole pojawił się kurs Buddhism and Modern Psychology czyli skrzyżowanie neurologii i najnowszych odkryć psychologii z kilkutysięczną filozofią.

Jeśli kogoś odpycha słowo buddyzm to niech je zwyczajnie oleje bo to był tylko taki abstrakcyjny dodatek do ścisłych faktów psychologicznych. Kurs będzie zamknięty w piątek, także jak ktoś chce obejrzeć wykłady to musi się pośpieszyć (polecam bardzo).

Na początek mały starterek.

Usiadł sobie koleś pod drzewem...

...kilka tysięcy lat temu - medytował i medytował - i wyprodukował Cztery szlachetne prawdy. Jeśli ktoś chce może sobie poczytać w linku rys filozoficzny - ale nas interesuje bardziej kontekst psychologiczny - a raczej psychologiczno-filozoficzny z naciskiem na część psychologiczną.

Pierwsza kwestia to koleś, który prowadzi wykłady ( Robert Wright - napisał fajne książki z pogranicza psychologii ewolucyjnej - "Moral Animal" i "The evolution of GOD") tłumaczy pewne nieporozumienie związane ze słowem "cirepienie", gdyż nie chodzi tu o cierpienie a o brak satysfakcji co jest chyba codziennością większości lemingów na świecie. I teraz uwaga - podobna koncepcja pojawia się w takich książkach jak "Power of habit" czy "Neuromarketing" co jest popularną częścią biblioteczki "skutecznego reklamodawcy". O co tu dokładnie chodzi?

I teraz paczta na ten obrazek bo mechanizm jest zabójczy (w swej prostocie i w ogóle). Weźmy bodziec R, który może być czymkolwiek - browar, wypłata, pochwała, nowe buty, jedzenie, sex itd. Gdy tworzy się nawyk najpierw możemy zaobserwować korelację ze skokiem dopaminy zaraz po otrzymaniu bodźca - np. małpka naciska dźwignie i dostaje banana - powstaje dosyć pożyteczny nawyk bo banan jest bogaty w potas i węgle proste.

I teraz pojawia się fascynująca rzecz - gdy nawyk się stabilizuje skok dopaminy przesuwa się przed "bodziec" - ma to sens gdyż cały mechanizm niejako zachęca małpkę do naciśnięcia dźwigni. A na ludzkie - to właśnie staje się istotą poszukiwań - nie bodziec a samo dążenie do bodźca, właśnie oglądamy neurologiczne podstawy ciągłej gonitwy po więcej oraz wytłumaczenie nieustającego braku satysfakcji. Dodatkowo jest to wzmocnione faktem, że z biegiem czasu wyskok dopaminy po samym bodźcu staje się coraz mniejszy - pozostawiając nas w stanie nienasycenia.

Mam nadzieję, że jest to wystarczająco jasne bo tutaj jest to tylko kilkoma zdaniami a na wykładzie było omawiane przez ponad dwie godziny - tak czy inaczej z ewolucyjnego punktu widzenia zagarnianie tego co się tylko da i ciągłe zaspokajanie potrzeb okazało się taktyką skuteczniejszą niż puszczanie bąków - dlatego mamy takie coś teraz w sobie (a bąki na zewnątrz). W trakcie kursu padło ciekawe sformułowanie - "hedonic threadmill".

Ale spoko - trzecia i czwarta z tych "szlachetnych prawd" mówi o rozwiązaniu - a neurologia wyjaśnia o co tu dokładnie chodzi. Lekarstwo pozostawimy jednak na koniec bo najpierw prawdziwe mięsko kursu.

Aby uzyskać fajny efekt kinowego przejścia na blogu tekstowym to teraz wyobraź sobie takie subtelne i delikatne ściemnienie się obrazu - jednocześnie dźwięk lekko zanika udostępniając przestrzeń nowym doznaniom - przed twymi oczyma pojawia się poniższy fragment z youtube (jak net będzie zamulał to trzeba sobie wyobrazić odpowiednio dłuższe przejście).

Kim nie jesteś

Taka ciekawa rzecz - musiałem to kilka razy przewijać aby załapać - generalnie ogromną tamą dla szczęścia w życiu jest pogoń każdego z nas za atrybutami, które błędnie kojarzymy ze sobą. Powoli.

mental formations

Czyli nasze przekonania. Weźmy sobie takie forum dyskusyjne - jak sama nazwa wskazuje forum dyskusyjne służy do napierdalania się do nieprzytomności o to kto ma rację. O proszę bardzo http://www.goldenline.pl/pawel-wlodarski2/wypowiedzi/ - 770 wypowiedzi z czego duża część jest bezwartościowym pierdoleniem o wyższości jednej rzeczy nad drugą. Masa irracjonalnych nerwów i straconego czasu.

Gdy zyskujesz doświadczenie zmieniasz swoje poglądy - Nie jesteś tym co uważasz

perception

Siedzisz sobie, walisz wódę i percepcja się zmienia. I tutaj fajne badanko - w zależności od tego jakiej muzyki słuchali badacze - strasznej lub przyjemnej - widzieli na obrazku aligatora lub wiewiórkę - Aligator czy wiewiórka - Nie jesteś tym czego doświadczasz

feeling

Do tego tematu powrócimy za chwilę bo uczucia to raczej sygnały, które oddziałują na nas a nie część nas. - Nie jesteś tym co odczuwasz

form (body)

To już w ogóle temat abstrakcja - jak już ktoś się zbierze i skoczy na siłkę, dobry trening siłowy zamiast stepera i maszyn - po kilku miesiącach "inny człowiek".

świadomość

To już w ogołe jest mindfuck - czas na modułową teorię swiadomości

Świadomość i moduły

Temat jest tak nieintuicyjny, że lekko go tu musnę tak czubeczkiem po powierzchni - generalnie polecam amazon i wpisać "Michael S. Gazzaniga" pojawią się takie książeczki jak Who's in Charge?: Free Will and the Science of the Brain.

Polecam też kliknąć w te linki :

  • Modułowa teoria umysłu
  • http://psychologydictionary.org/beneffectance/ - termin tłumaczący po co wyewoluowała samoświadomość. Nie jest ona prezesem a raczej działem marketingu - inaczej rzucenie palenia czy zmiana nawyków żywieniowych byłaby zwykłą sekundową decyzją. Nie chcę palić - no dobra to nie palę - nichuja to tak nie działa
  • http://biasandbelief.pbworks.com/w/page/6537179/Beneffectance - bardziej praktyczne opracowanie.
  • Samooszukiwanie - a to takie życiowe - jak mi się nie udało to miałem pecha. Jak mi się udało to jestem zajebisty. Jak komuś kogo nie lubię się udało to miał oczywiście farta ("Fartuch pierdolony"). A jak mu się nie udało to było do przewidzenia...
  • No i generalnie różne uczucia włączają różne moduły a później nasza świadomość to wszystko racjonalizuje aby miało sens w kontekście skomplikowanej sieci społecznych zależności. Weźmy te kłótnie na forach. Tutaj działa między innymi modułu odpowiedzialny za obronę statusu społecznego i później umysł świadomy racjonalizuje, że ja się nie napierdalam tak dla zasady ale naprawdę ten PHP jest zjebany (no bo jest ale chyba wiadomo o co chodzi). W końcu! Neurologiczne wytłumaczenie świętych wojen!

    Cytat : "One last bit of evidencein support of the argumentthat the self is essentially a tool of impression management and the product of a specialize dprocessor. Severely brain damaged individuals, eventhose subjected to commissurotomies, maintain a steady stream of rationalization and denial of their handicap. They appear to be striving to convey an impression of being reasonable and sensible (Gazzaniga 1985). The algorithms of the selfs specialized processor appear to demand this." by jerome barkow - http://www.omega23.com/Journal_of_Ideas/Barkow-Folk_Pyscholog_Free_Will_Evolution-JoI_V2_2_3-1991.pdf

    No dobra na razie jest tak trochę mrocznie - ale jest lekarstwo

    Mindfulness meditation

    Specjalnie zostawiłem angielski tytuł aby uniknąć "szklanej pułapki" tłumacza. Generalnie pierwsze pojęcie-klucz to Default mode network. Jest to to coś co działa w nas kiedy nie myślimy o czymś konkretnym.

    I tutaj jest ciekawy link : Wpływ medytacji na default mode network. Generalnie medytacja wycisza to DMN co ma dosyć ciekawe konsekwencje gdyż pozwala spojrzeć nam na emocje - czyli trigery zachowań - z dystansu. I teraz bardzo ważny rodzaj medytacji - wspomniana w tytule "mindfulness meditation"

    Idea jest prosta - odbierać uczucia,odczucia, obserwacje bez oceniania ich. Co ciekawe ta koncepcja atakuje z różnych stron w różnych publikacjach - w NLP to była praca z "presupozycjami", było też o tym w wizualizacjach metody Silvy jeśli dobrze pamiętam. Generalnie pomaga skupienie się na scence gdzie oglądamy w trzeciej osobie siebie odbierającego dane wrażenia co tworzy formę interesującego dystansu od uczuć. Przywraca nam ograniczoną kontrolę nad tym co robimy i pomaga programować siebie na przyszłość.

    Zmieniamy postrzeganie świata, zmieniają się uczucie, zmienia się nasze zachowanie ... i postrzeganie świata. I o to tutaj kurwa chodzi. A no i przy okazji zrozumiałem dlaczego tak mi się podoba rzucanie kurwami w tekście. Generalnie to takie podświadoma próba uwolnienia się od mentalnych łańcuchów społecznych. Tak naprawdę awersja do słów kurwa,chuj itd to takie lekko snobistyczne podejście podobnie jak jedzenie śledzia pięcioma widelcami - niby udajemy, że jesteśmy szlachta - ale wracając do tematu.

    Gdy zerwie się łańcuchy ewolucji i naturalnej selekcji wtedy czeka nas.. dobra ostatniej częsci jeszcze nie skumałem ale pojawia się słowo "enlightenment" (I nie chodzi o javascript enligtment) oraz pojęcie "emptiness" co wbrew pozornym negatywnym zabarwieniu ma znaczenie pozytywne gdyż pozwala nam dostrzec rzeczy takimi jakie są. To jest ciekawe arcy arcy ciekawe. Może zrozumiem przy okazji drugiej edycji.

    I jeszcze jeden ciekawy cytat dlaczego świat jest generalnie taki zjebany - niestety nie zapisałem autora a i słowa są z pamięci : "This planet is settled by beings which each one has build in system to convince them that they are more important than others"

    Następny odcinek będzie pewnie coś o Scali aby czytelnicy nie pouciekali - chociaż z drugiej strony jebać to - nie jestem swoim blogiem

    niedziela, 18 maja 2014

    Jeden slajd z Geecon 2014

    DRY - tutaj są dobre recenzje :

    Zwykły acz niezwykły slajd

    Powyższy slajd zaprezentował Sam Newman podeczas swojej prezentacji o Mikroserwisach.

    To jest arcyciekawy slajd gdyż jedzie walcem po pseudo-perfekcjonistycznej nasyconej strachem przed porażką kulturze wielu korporacji. Tutaj jest wyraźnie narysowane, że będziemy testować po deployu i trzeba się szykować na ewentualną "cofkę". Na slajdzie użyte jest słowo remediation zamiast rollback ale chyba chodzi mniej więcej o coś podobnego.

    Problem polega na tym, że jak coś wrzucimy na produkcję a później się cofamy to metryki stoją w miejscu. W tematyce samorozwoju istnieje takie pojęcie jak learning experience co też trochę trąci bullshitem ale jednocześnie ma za zadanie pokazać, że pewne zdarzenia owocują jedynie niematerialnym zastrzykiem wiedzy, który generuje zmiany w połączeniach neuronowych - niestety nichuja z tego nie da się wyrysować fajnego wykresu do powerpointa na spotkanie.

    Jakby np. wyglądała nauka jazdy na rowerze według korpo procesu? Najpierw potrzebny jest jakiś ambitny target metodą smart więc jebnijmy sobie "przejechać 100m", co zostanie zmienione na "100km" przez innego managera posługującego się formułkami "push harder" i "reach higher". Teraz koleś wsiada na rower i gleba. Jego mózg przetwarza nowe informacje jak tu się utrzymać na dwóch kółkach ale zanim będzie miał okazję wsiąść na rower musimy odbyć meeting dlaczego się nie udało, "This situation makes me very concern" i inne takie "postmortem analysis".

    Dobra, koleś siada drugi raz - 5 metrów i znowu gleba. Trzeba zrobić meeting z "root cause anlysis" dlaczego wciąż ponosimy porażki - a przecież ponosimy porażki bo według flow chartu rower stoi w miejscu a przecież na kursie z zarządzania pan Zdzichu wyraźnie mówił, że jak "stoimy w miejscu to się cofamy".

    I tutaj nagle na dużej konferencji pojawia się slajd, który mówi, że to w sumie dobra opcja wyskoczyć do świata rzeczywistego, zebrać rzeczywiste info z tego świata rzeczywistego i ewentualnie się wycofać - "Reality driven development".

    I nawet ci ludzie od robotów odnieśli spektakularny sukces bo zdobyli niesamowicie cenną wiedzę "co może pójść źle w czasie prezentacji" - i teraz jak wyskoczą przed potencjalnych inwestorów maja szansę zabłysnąć.

    Apropo robotów to nawet one były najebane.

    Do rozwiązania ponadto pozostaje standardowy problem wszystkich konferencji IT czyli blokowanie się wątków przy wejściu do męskiego kibla.

    ***

    niedziela, 11 maja 2014

    PlayFramework - drugie spotkanie i scenariusz nauki

    Gdy coś się dzieje po raz drugi to już trudniej nazwać to coś tymczasową anomalią. I w ten sposób - ku mej uciesze - warsztaty z Playa i Scali wydają się mieć dobrze i będą rozwijać się nadal.

    Uwagi i wnioski

    1. Tym razem na początku było trochę więcej chaosu związanego z konfiguracją środowisk toteż będę musiał pisać dokładną instrukcję tak krok po kroku jak się przygotować.
    2. Muszę pamiętać by ustawiać limity na meetupa bo tym razem przyfarciłem i zorientowałem się jak było akurat 15 osób zapisanych.
    3. Nie udało się zrobić tyle zadanek ze scali ile planowałem i do tego niektóre koncepcje nie są od razu jasne przy pierwszym zetknięciu. Być może będzie opcja na niezależne warsztaty ze scali?
    4. Chociaż programowanie w parach upraszcza prowadzenie warsztatów to jakoś ludzie wydają się być niechętni co do tego sposobu pracy na zajęciach.

    Co dalej

    W czerwcu jedno lub dwa spotkanka z dalszej części warsztatów. Czas na formularze, parsery i kompozycje akcji. Materiału jest trochę także może podzielę to jeszcze na dwa części.

    Play 2.3 RC1 jest już do pobrania także w lipcu może dla kolejnych chętnych będzie powtórka startu z playa - tym razem wersja 2.3 i scala 2.11.

    Scenariusz warsztatów

    To jest tak jakby kontynuacja Części pierwszej. Poniżej rozwinięta wersja punktu 3 z programu warsztatów --> Program warsztatów

    Start

    Tutaj standardowo tworzymy aplikację i w akcji index zmieniamy Your new application is ready. na pomidor albo dupa żeby było więcej zabawy

    HTTP

    Od razu trzeba pokazać, że dla Playa HTTP to przyjaciel a nie wróg. Robimy dodatkową akcję i prezentujemy jedyny chyba działający "quick fix" dla playa w eclipse - "ctrl+1" i automatyczne generowanie "ruta".

    //application.scala
    def moja = Action {
        Ok("siema")
    }
    //routes
    GET   /moja           controllers.Application.moja()
    

    I od razu działa bez restartu. Tutaj trzeba zrobić efekt WoW, o ku*wa itd. Wydaje mi się, że za pierwszym razem wyszło mi to bardziej epicko.

    Na razie akcja zwraca nam text/plain ale łatwo i przyjemnie można to zmienić.

    Ok("siema").as(HTML) //text/html;charset UTF-8
    Ok(siema) // application/xml
    import play.api.libs.json._
    Ok(Json.obj("klucz"->"siema")) // application/json
    

    Parametry

    Tutaj przede wszystkim dobrze pokazać jak jasno Play raportuje gdzie brakuje parametru i gdzie popełnione są błędy w mapowaniu. Przy każdej okazji staram się podkreślać, że kompilator stara się tutaj pomóc jak może. Albo się walczy z kompilatorem albo z Runtimem - to pierwsze wydaje mi się bezpieczniejsze i przyjemniejsze

    //Application.scala
    def moja(name:String) = Action {
       Ok(s"siema $name")
      }
    

    A jak już mapowanie będzie ok, to nadal raportowanie o złym użyciu api jest zajebiste. Aby uspokoić zmysły kolor czerwony zamienia się w kolor klocka.

    Tutaj też jest dobry moment aby uświadomić uczestników warsztatów o tym, że play wygenerował nam ładną lokalną dokumentację, w której można sobie sprawdzić opcje na deklaracje parametrów w query, w urlu, na parametry zdefiniowane i opcjonalne. Była krótka dyskusja o tym czy da się zrobić tak aby wartość parametru była deklarowana w akcji a nie w routach - chociaż wydaje mi się to bez sensu bo parametr to części API to jednak w wolnej chwili muszę to sprawdzić.

    Szablony

    Tutaj dobrze jest ujawnić opcję ~run oraz ciekawe ustawienie w eclipse Window->preferences->General->Workspace->Refresh using native hooks pooling . Ze zwyklym run po stworzeniu nowego widoku trzeba by najpierw odświeżyć stronę a później projekt - co jest zwyczajnie słabe.

    I teraz też czas na pokazanie szczodrości kompilatora - ku naszej uciesze nie da się do widoku przekazać Int kiedy oczekiwany jest String. Mniej zjebek typu "Object w jsp" - ano i podpowiadanie jest IDE jak zna typ.

    Więcej o szablonach w opisie poprzednich warsztatów -> Szablony

    Testy

    Wygenerowane testy powinny nam nie przechodzić na tym etapie gdyż domyślny nagłówek strony głównej został zastąpiony słowem pomidor lub dupa. Co akurat pokazuje, że owe testy działają.

    Tutaj też fajnie pokazać, jak łatwo testuje się widoki, które są zwykłymi funkcjami.

    @* widok Template File *@
    @(name: String)
    <html>
    <head>
    <title>widok</title>
    </head>
    <body>
    <h1>Siema @name </h1>
    </body>
    </html>
    

    I jak mamy ów widoczek to najwygodniej otworzyć worksheet i najzwyklej w świecie widoczek wywołać.

    object warszt {
     
     html.widok("Bożenka")                     //> res0: play.api.templates.HtmlFormat.Appendable = 
                                                      //| <html>
                                                      //| <head>
                                                      //| <title>widok</title>
                                                      //| </head>
                                                      //| <body>
                                                      //| <h1>Siema Bożenka </h1>
                                                      //| </body>
                                                      //| </html>
    }
    
    

    I w końcu można testować widok w testach jednostkowych. Nie chce mi się drugi raz opisywać tego samego -->Testy jednostkowe dla widoku

    Reverse routing

    To jest dosyć ciekawa funkcjonalność bo chyba nie ma czegoś podobnego w innym frameworku javowym. Żeby był efekt jebnięcia wystarczy chyba utworzyć obok siebie link zwykły i link używający reverse routing aby pokazać, że problemy z updatem linków w aplikacji nie będą nas już niepokoić

    //widok.scala.html
    <a href="/">link do indexu </a> <br/>
    <a href="@routes.Application.index">samoupdatujący się link do indexu </a> //i zmiana w routes GET /nowaStrategiaMarketingowa controllers.Application.index

    I to na razie byłoby na tyle

    ***

    niedziela, 27 kwietnia 2014

    Nauka PlayFramework - program edukacyjny część pierwsza

    Poniżej program edukacyjny dla pierwszej części warsztatów "PlayFramework" (moduł 1 - "start"). Program wymyśliłem sobie sam i dla mnie subiektywnie jest dobry bo ująłem w nim swoje przeżycia z nauki Playa,Scali i w ogóle podejścia funkcyjnego. Czy będzie dobry dla wszystkich to się okaże...

    Jak komuś się do czegoś ten program przyda to niech śmiało bierze i korzysta.

    Pierwsze zetknięcie ze Scalą i programowaniem funkcyjnym

    Program startuje z założeniem, że uczestnicy nie zetknęli się jakoś w dużym stopniu ze Scalą i programowaniem funkcyjnym. Niby Java8 powinna spopularyzować trochę to podejście ale nie zdziwię się jak masa osób będzie cały czas jechać w Javie4 czy Javie5 - taki urok miasta "low cost centrów".

    Ćwiczenia będą się rozwijać a to co jest na tę chwilę opisałem pod linkiem : Playframework moduł 1 "Start" - opis warsztatów

    Najpierw idzie godzinka scali dla zaznajomienia się z podejściem a później w drugiej części jedziemy z Playem.Poniżej bardziej szczegółowy opis pierwszej części.

    Deklaracja funkcji jako zmiennej

    Ten punkt ma za zadanie zaznajomić słuchaczy z sytuacja gdzie w zmiennej jest trzymana pewna logika, operacja a nie zaś same dane

    val funkcja=(arg:Int)=>arg+1         //> funkcja  : Int => Int = |function1|
    val dane=1                           //> dane  : Int = 1
     
    funkcja(1)                           //> res0: Int = 2
    funkcja(dane)                        //> res1: Int = 2
    
    
    Kompozycje funkcji

    Zadanie : zbudować funkcję z już istniejących z użyciem andThen oraz compose. Ta część ma pokazać siłę prostoty kompozycji funkcji. Wystarczy by zgadzały się określone typy funkcji aby można było je ze sobą składać. W OOP często atakuje nas specyficzny kontekst danego rozwiązania i trzeba uciekać do tworzenia abstrakcji, które mogą (ale nie muszą) zaciemniać rozwiązanie.

    val pomnozPrzezDwa = (arg: Int) => arg * 2 //> pomnozPrzezDwa  : Int => Int = |function1|
      funkcja.andThen(pomnozPrzezDwa) //> res2: Int => Int = |function1|
      //można też bez kropek
      val dodajJedenIPomnozPrzezDwa = funkcja andThen pomnozPrzezDwa
      //> dodajJedenIPomnozPrzezDwa  : Int => Int = |function1|
    
      dodajJedenIPomnozPrzezDwa(1)
      //> res3: Int = 4
    
    

    Metodę "compose" można wytłumaczyć na czymś bardziej z życia wziętym - na przykładzie klasy User (bo teraz chyba każdy system an ziemi ma klasę User). Może pojawić się pytanie co to jest to "case" - na tym etapie to jest raczej nieistotne i może wprowadzić niepotrzebny zamęt. Można powiedzieć, że to generuje z paczki hashcode, toStringa i kilka podobnych metodek.

    case class User(email:String)
    val validacjaEmaila=(email:String)=>email.nonEmpty
                                                      //> validacjaEmaila  : String => Boolean = |function1|
    val emailUsera=(user:User)=>user.email    //> emailUsera  : poligon.User => String = |function1|
     
    val validujeEmailUsera=validacjaEmaila.compose(emailUsera)
                                                      //> validujeEmailUsera  : poligon.User => Boolean = |function1|
    validujeEmailUsera(User("aa@wp.pl"))      //> res0: Boolean = true
    validujeEmailUsera(User(""))              //> res1: Boolean = false
    
    
    Funkcje wyższego rzędu

    Tutaj może pojawić się pierwszy kolaps czaszki gdyż standardowy programista Javy, który rzeźbi całe życie CRUDy raczej rzadko kiedy spotyka się z sytuacją przekazywania kawałka logiki jako argumentu do innego kawałka logiki. Niby to jest podobne do "Strategii" ale zazwyczaj w Springu czy czymś takim wszystko jest już wstrzyknięte. Co najwyżej można to porównać do przekazywania komparatora w Collections.

    Szybka demonstracją może być sumowanie wszystkich liczb nieparzystych od 1 do 100. Drugim przykładem - bardziej przydatnym - wypisanie wszystkich maili Userow, które są krótsze niż 5 znaków.

    val lista=1 to 100 toList                 //> lista  : List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                                                      //|  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
                                                      //|  35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
                                                      //|  54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
                                                      //|  73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
                                                      //|  92, 93, 94, 95, 96, 97, 98, 99, 100)
    val czyNieparzysta=(arg:Int)=>arg%2==0    //> czyNieparzysta  : Int => Boolean = |function1|
     val sumuj=(akumulator:Int,element:Int)=>akumulator+element
                                                      //> sumuj  : (Int, Int) => Int = |function2|
     lista.filter(czyNieparzysta).reduce(sumuj)//> res0: Int = 2550
    
    Uproszczenie zapisu

    W końcu dochodzi moment, w którym trzeba uczestnikom pokazać zapis z podkreślnikami - bez względu na wygodę takiego zapisu osoby niezaznajomione z tąże notacją mogą wykazać postawę "o ku*wa!". No i tutaj jest okazja wytłumaczyć kiedy nie trzeba deklarować typów bo kompilator może to wykminić z kontekstu.

    //poniższe linie są równoważne
    lista.filter(arg=>arg%2==0).reduce((akumulator,element)=>akumulator+element)  //> res0: Int = 2550
    lista.filter(_%2==0).reduce(_+_)          //> res1: Int = 2550
    
    Currying

    To będzie potrzebne później przy templatach Playa. Tutaj pokazać tylko na szybko prosty przykład aby słuchacze zaznajomili się z faktem wykorzystywania kilku par nawiasów przy deklaracji funkcji. Według mnie prościej takie funkcje deklaruje się wychodząc od metody "def" ale tutaj dla porównania dwie wersje

    def metoda(a:Int)(b:Int)=a+b              //> metoda: (a: Int)(b: Int)Int
    val funkcja=(a:Int)=>(b:Int)=>a+b         //> funkcja  : Int => (Int => Int) = |function1|
     
    val funkcjaZMetody=metoda(1)_             //> funkcjaZMetody  : Int => Int = |function1|
    funkcjaZMetody(2)                         //> res0: Int = 3
     
    val funkcjaZFunkcji=funkcja(1)            //> funkcjaZFunkcji  : Int => Int = |function1|
    funkcjaZFunkcji(2)                        //> res1: Int = 3
    
    
    Serwer jako funkcja

    Teraz nastąpi połączenie dotychczasowych ćwiczeń z Playem.

    case class Request(url:String)
    case class Response(resultCode:Int)
     
    
    val handler:(Request=>Response)=(request)=>request match{
     case Request("/jug/warsztaty") => Response(200)
     case Request("")=>Response(500)
     case wszystkoInne=>Response(404)
    }                                         //> handler  : poligon.poligon.Request => poligon.poligon.Response = 
                                                      //| 
    
    handler(Request("/jug/warsztaty"))        //> res0: poligon.poligon.Response = Response(200)
    handler(Request(""))                      //> res1: poligon.poligon.Response = Response(500)
    handler(Request("/poradnikSwiatlegoManagera"))
                                                      //> res2: poligon.poligon.Response = Response(404)
    

    Mając powyższe możemy dojść do zapisu Action z Playa

    def Action(handler:(Request=>Response))={
     println("jakies operacje na serwerze przed handlerem")
     val result=handler(Request("/aaa"))
     println("jakies operacje na serwerze po handlerze : "+result)
    }                                         //> Action: (handler: poligon.poligon.Request => poligon.poligon.Response)Unit
     
     
    Action(handler)                           //> jakies operacje na serwerze przed handlerem
                                                      //| jakies operacje na serwerze po handlerze : Response(404)
     
    Action{handler}                           //> jakies operacje na serwerze przed handlerem
                                                      //| jakies operacje na serwerze po handlerze : Response(404)
     
    Action{request=>
     println("inline function")
     Response(200)
    }                                         //> jakies operacje na serwerze przed handlerem
                                                      //| inline function
                                                      //| jakies operacje na serwerze po handlerze : Response(200)
    
    Podsumowanie

    Powyższe ćwiczenia mają za zadanie wprowadzić uczestników w świat Scali i programowania funkcyjnego. Maja także za zadanie zsynchronizować wszystkich gdyż część ludzi kończy robotę tak, że może przyjść na 17 a część na 18.

    Ćwiczenia są przewidziane na godzinę, Jeśli zajmą więcej czasu to można zacząć przeplatać je Playem. Za tydzień lub dwa lub trzy lub więcej opiszę część druga.

    ***

    poniedziałek, 21 kwietnia 2014

    Udawane Multiple Dispatch poprzez takie niby niewidzialne wizytatory

    Dwie hierarchie

    Z nauką nowych rzeczy jest trochę jak z oglądaniem reklam - nagle dowiadujesz się, że masz nowe potrzeby i to co było do tej pory przestaje wystarczać. A Coż może być takie fajne?. Gdy błądzący programista przedziera się przez materiały o obiektówce to zazwyczaj w sąsiedztwie słowa "Polimorfizm" znajduje się jakiś przykład gdzie kot i pies dziedziczą z klasy Animal czy coś w ten deseń.

    Okazuje się, że te przykłady przedstawiają coś co nazywa się "single dispatch" i to coś ma ograniczenia, których nie ma bogatszy mechanizm zwany Double Dispatch lub Multi Dispatch. Może to dla większosci oczywiste ale mnie o tym w szkole nie uczyli.

    A jeśli ktoś tak jak ja został niedopieszczony przez system edukacji to kod jak zwykle najlepiej pokaże o co chodzi. ( a jeśli ktoś jednak woli wikipedię to :

    )

    kod

    Użyjemy dwóch hierarchii klas.
    Pierwsza jest ludzka i zawiera

    • Klasę Human - nie chodzi humanistę tylko ogólnie o człowieka
    • Klasa Hipster dziedziczy z Human - Hipster to ktoś kto deklaruje swoją niezależność od "mainstreamu" głównie poprzez używanie mainstreamowych aplikacji społecznościowych
    • Klasa AntyHipster dziedziczy z Human - Antyhipster to ktoś kto jest takim hipsterem, że aż nie używa fejsbuka - wspomni o tym w przeciągu pierwszych 20 sekund rozmowy

    Druga hierarchia to martwa natura i zawiera :

    • Klasę Drink - czyli napój
    • Klasa Vodka dziedziczy z Drink - czyli wóda
    • Klasa OrangeJuice dziedziczy z Drink - Litr soku pomarańczowego zawiera więcej cukru niż litr Coli --> ile cukru w cukrze

     
    
    abstract class Human {
      def consume(drink: Drink):String
    }
    class Hipster extends Human{
      def consume(drink: Drink) = s"hipster consuming drink : $drink"
      def consume(drink: Vodka) = s"hipster consuming vodka : $drink"
      def consume(drink: OrangeJuice) = s"hipstewr consuming Orange : $drink"
    }
    
    class AntyHipster extends Human {
      def consume(drink: Drink) = s"antyhipster consuming drink : $drink"
      def consume(drink: Vodka) = s"antyhipster consuming vodka : $drink"
      def consume(drink: OrangeJuice) = s"antyhipster consuming Orange : $drink"
    }
    
    
    class Drink
    class OrangeJuice extends Drink
    class Vodka extends Drink
    
    //deklaracje
    
    val hipster = new Hipster
    val antyhispter = new AntyHipster
    val juice = new OrangeJuice
    val vodka = new Vodka
    
    

    Przypadek jeden Zero dispatch - mała elastyczność

    Na samym początku przykład prosty jak cep. Metoda, która przyjmuje konkretną implementacje Human (Hipster) i konkretny napój (Vodka). Gdybyśmy chcieli obsłużyć wszystkie przypadki (Human,Drink) wtedy potrzebujemy 4 różne metody (bardzo niedobrze, bardzo bardzo źle)

    
    def zeroDispatch(hipster:Hipster,vodka:Vodka)=hipster.consume(vodka)
    
    zeroDispatch(hipster, vodka)              //> res0: String = hipster consuming vodka : Vodka
    
    

    Trochę lepiej - Single dispatch

    Co chcę zrobić : przekazać obiekt typu człowiek i ma się wywołać metoda z odpowiedniej implementacji. Czyli poniżej metoda spodziewa się po prostu Human i można tam przekazać i Hipstera i AntyHisptera - czyli klasyczny "Javowy Polimorfizm". Aby obsłużyć wszystkie kombinacje (Human,Drink) potrzebowałbym dwóch metod - po jednej na każdy napój.

    def singleDispatch(human:Human,vodka:Vodka)=human.consume(vodka)
    val hipster : Human= new Hipster
    val antyhispter : Human = new AntyHipster
    
    singleDispatch(hipster, vodka)            //> res0: String = hipster consuming drink : Vodka
    singleDispatch(antyhispter, vodka)        //> res1: String = antyhipster consuming drink : Vodka
    

    Multiple Dispatch - pierwsze podejscie z failem

    I teraz ważne co chcę zrobić : chcę mieć jedną metodę która ani nie wie co to za Human ani co to za Drink i jak np. przekażę Hipstera i Vodkę to się automatycznie wywoła metoda z Hipstera, która przyjmuje Vodke.
    Proba 3..2...1..

    val hipster : Human= new Hipster
    val antyhispter : Human = new AntyHipster
    val vodka : Drink= new Vodka
    
    def notWorkingMultipleDispatch(human:Human,drink:Drink)=human.consume(drink)
    notWorkingMultipleDispatch(hipster, vodka)//> res0: String = hipster consuming drink : Vodka
    notWorkingMultipleDispatch(antyhispter, vodka)//> res1: String = antyhipster consuming drink : Vodka
                                                      
    

    No i Ch** bo jakby ktoś nie zauważył wywołana jest generyczna metoda "consume(Drink)". W Javie można zrobić takie nieładne "instanceof" albo Vizytatora. W Scali można zrobić Pattern Matching albo Vizytatora.

    Ewentualnie można zrobić takiego "niewidzialnego" Vizytatora co zrobimy dla ćwiczeń teraz bo nie mam innego pomysłu na zakończenie tego artykułu

    Rzeźbimy

    abstract class Human {
      def consume[A](drink: A)(implicit dispatcher: DrinkMultiDispatch[A]): String
    }
    class Hipster extends Human{
     override def consume[A](drink: A)(implicit dispatcher: DrinkMultiDispatch[A]): String="hipster "+dispatcher.dispatch(drink)
    }
    
    trait DrinkMultiDispatch[A] {
      def dispatch(drink: A): String
    }
    

    Idea polega na dołożeniu "czegoś" co będzie decydowało o tym jak obsłużyć konkretny napój. Ponieważ mamy implicity to będzie pojawiało się znikąd i user nawet nie zauważy.

    implicit val udawaneMultipleDispatch = new DrinkMultiDispatch[Drink]{
      def dispatch(drink: Drink) = drink match {
       case _:Vodka => "drinking vodka"
       case _:OrangeJuice => "drinking juice"
      }
     }
    

    To jest takie oszukiwanie przez pattern matching. Próbowałem dopasować typ Dispatchera poprzez Generyk ale zawsze dostawałem "ambiguous implicit values" jak siedziały obok siebie [Vodka] i [OrangeJuice].

    def workingMultipleDispatch(human:Human,drink:Drink)=human.consume(drink)
    workingMultipleDispatch(hipster, vodka)   //> res3: String = hipster drinking vodka
    workingMultipleDispatch(hipster, juice)   //> res4: String = hipster drinking juice
    workingMultipleDispatch(antyhipster, vodka) //> res5: String = antyhipster drinking vodka
    workingMultipleDispatch(antyhipster, juice) //> res6: String = antyhipster drinking juice
    

    No i od bidy można powiedzieć, że to rozwiązanie uwalnia klasy "domenowe" od instanceof. Jeśli jest jakieś lepsze rozwiązanie to nie umiem go znaleźć. Zawsze trochę zabawy i edukacji.

    A w ogóle skąd ten multi dispatch? Przeczytałem, że Clojure ma to z paczki ale podobno wolne strasznie.

    *               *              *
    

    poniedziałek, 14 kwietnia 2014

    Warsztaty z Play i ciekawostki ze Scali

    Zamiast zastanawiać się jak zacząć ten wpis aby oddać jak szczęśliwy jestem, że warsztaty udało się doprowadzić do skutku i spotkały się one z moim zdaniem dużym zainteresowaniem - użyję cudzej pracy i dam link do relacji Krzysztofa Telki z warsztatów

    FoldLeft wszyscy szybko załapali

    I z pisaniem testów też nie było problemów.

    Tu jest reszta fotek:

    Kolejne spotkania

    Drugą edycję wprowadzenia będę chciał zrobić pomiędzy majówką a Geeconem. Na retro były prośby o więcej zadań - także zacząłem przygotowywać plan zajęć (a być może nawet i go skończyłem)

    Jak ktoś ma sugestie niech śmiało zapodaje. Później po Geeconie a przed 33Degree (konferencje to dobry punkt odniesienia w czasie bo mogę zaplanować kiedy będę trzeźwy) zorganizuję jakoś drugi moduł "Obsługa formularzy, parsery requestów i kompozycja Akcji".

    Layouty w Playu

    W trakcie warsztatów pojawiło się pytanie, na które już umiem odpowiedzieć : "czy da się zrobić tak layouty aby dany tail nie wiedział w jakim szablonie jest używany".
    O co chodzi : Play domyślnie wygeneruje nam szablon z rozwiązaniem "tail wywołuje szablon"

    @main("Naglowek") {
    
     <h1>Moj tail</h1>
    
    
    }
    
    Jako że szablony to zwykłe funkcje to można też w drugą stronę : "wywołać taila z szablonu"
    To źródło jest footer.scala.html
    @import play.api.Play.current
    <footer>
    Revision @current.configuration.getString("application.revision")
    </footer>
    
    A to już wywołanie w szablonie
     <body>
            @content
            @footer()
     </body>
    
    Proste?Proste.

    Ciekawy przykład z życia

    Na jednym ze spotkań firmowych dyskutowaliśmy sobie po co robić w deklaracji funkcji kilka par nawiasów i co dobrego z tego może wyjść. Wymyśliliśmy sobie funkcję "policjanta", która sprawdza czy dany user może wykonać jakąś tam operację :

    def withProperAccess(user:User)(operation:User=>String)={
      if(user.securityLevel>2) operation(user) else "sorry ziom"
     } 
    
    I teraz aby nawiązać do jakiejś formy dependency injection stworzymy funkcję, która z kontekstu wstrzyknie usera i wyprodukuje funkcje jednoelementową :
     def injectUser(function:(zagadka))={
       val contextUser=User("Roman",3)
       function(contextUser)
      } 
    
    I tutaj pojawiła się zwiecha - jaki właściwie typ ma oryginalna funkcja dwuargumentowa, która jeszcze jako jeden z parametrów przyjmuje funkcje?(czyli co tam w ten nawias (zagadka) wstawić)

    Okazuje się, że ów typ to : User=>(User=>String)=>String I teraz ktoś kto to widzi po raz pierwszy w życiu może zareagować niezwykłym zdumieniem wypływającym z silnego zderzenia jego obecnego pojęcia świata z napotkanym kształtem: Ewentualnie w twojej głowie może zabłysnąć niecodzienne zdziwienie wywołane kontrastującym konfliktem pomiędzy zmysłami a doświadczeniem:
    A niepotrzebnie bo wyjaśnienie jest proste.

    Co to jest?

    Zaczynamy od strony lewej User=>(User=>String)=>String
    Generalnie to co jest po lewej stronie strzałki to to co funkcja dostanie jako argument a to co po prawej (jak dziwne by nie było) to to co zwróci. Tutaj po stronie lewej jest User i to jest właśnie to magiczne wstrzykniecie usera z kontekstu - function(contextUser) i w wyniku dostajemy to po prawej.

    Mamy teraz to coś : (User=>String)=>String i znowu to co jest po lewej to argument ale tym razem argument ma też strzałkę w sobie - bo toż to funkcyja jest ino. Argumentem jest funkcja, która przyjmuje Usera a zwraca String czyli np :

    val funkcjaBiznesowa=(user:User)=>secretKeys.getOrElse(user.name, "nima")
    
    Zaś wywołanie funkcji
    (User=>String)=>String
    Wygląda tak :
     val securityAccesWithUserInjected=injectUser(withProperAccessFun)
    securityAccesWithUserInjected(funkcjaBiznesowa)
    

    Mam nadzieję, że teraz jest trochę jaśniej.

    *               *              *
    

    niedziela, 6 kwietnia 2014

    Scalar i stacktrace

    Konferencja była bardzo fajna i można sobie poczytać wiele pochwał na twiterze : "#scalarconf". Dobra jak już posłodzone to teraz o jednej konkretnej rzeczy...

    Zdrowy dystans do Scali

    Bardzo chciałem posłuchać wykładu o wadach scali aby nie popaść w zbytnie uwielbienie technologii przechodząc metamorfozę w fundamentalistycznego fanatyka. Problem z konferencjami w sobotę jest taki, że dzień wcześniej jest piątek i wieczorem blokersi drą ryje na ośce co zaowocowało jedynie 4 godzinami snu. Ze względów bezpieczeństwa stymulanty zachowałem na podróż samochodem (obecnie jest to Thermo Shred co poza ogólnymi bonusami do statystyk dostarcza w jednej porcji 200mg kofeiny co wystarczająco wyostrza percepcję by bezpiecznie przebyć trasę Łódź-Wawka za kierownicą samochodu) przez co po obiedzie włączyła się standardowa zamuła.

    Kiedy Tomek Nurkiewicz rozpoczynał wykład ja toczyłem bój o to aby przekierować jak najwięcej uwagi systemu nerwowego z trawienia na odbiór co zaowocowało drzemką przerywaną w postaci : jestem na Majorce-jestem na scalarze-jestem na Majorce-jestem na scalarze-i ostatnia faza to był taki mix Gry o tron z rosyjska inwazją na Krym ale zanim fabułą się rozwinęła obudził mnie jakiś koleś z komunikatem, że chciałby przejść do kibla.

    Tomek mówił bardzo ciekawie co należy docenić podwójnie bo co innego jak angol mówi ciekawie po angielsku a co innego jak obcym językiem sprawnie posługuje się Polak. I nawet ten gostek co go zjadła trema na uderscore zrobił kawałek dobrej roboty i mam nadzieję, że nikt go nie hejtował na twiterach. Generalnie wkurwiają mnie ludzie, którzy nie mają jąder żeby samemu coś zrobić w życiu ale krytykują każdą wpadkę tych co ryzykują (tym bardziej, że sam tak kiedyś robiłem). Najlepsza scena to i tak jest wtedy jak jebany grubas z browarem i czipsami siedzi przed meczem i drze ryja "nooooo biegnij ku*waaa do tej piłki". Ale wracając do Scali.

    Nie wiem czy ten temat był faktycznie poruszony czy to tylko widmo delirium poobiedniego ale generalnie temat nieczytelnych StackTraców już w kontekście scali widziałem razy kilka. A ostatnio ten argument pojawił się przy okazji lambady w Javie8. Następuje tu moim skromnym zdaniem pewne nieporozumienie łączące dwa niepowiązane fakty.

    To, że stacktrace przy błędzie w funkcji anonimowej czy czymś takim może być z deczka nieczytelny nie wynika bezpośrednio z natury języka czy mechanizmów siedzących pod lambdą. Nieczytelność stacktrace wynika... z nieczytelnego stacktracu. Już tłumaczę o co chodzi.

    Bo to zły stacktrace był...

    Ten problem pojawia się nie tylko w Scali. Niedawno czytałem dyskusję o Coffescript i o tym, ze jak coś się popsuje to i tak trzeba debugować w javascript. Podobnie jest czasami z Hibernate jak używamy sobie klasy a tu nagle nam stacktrace o jakiejś tabelce gada. W tym miejscu zazwyczaj ludzie po raz 50000 cytują artykuł z przed 200 lat o "liking abstraction" ale już wystarczy tego suchara.

    Tutaj koleżko opisuje jego bóle z stacktracem w scali i javie8 --> bóle - I zastanówmy się teraz przez chwilę dlaczego stacktrace Javy7 wydaje się być ok (a nie musi).

    Jak mam np.

    Object tekst=null;
    tekst.toString();
    
    To dostanę w Javie NullpointerException i ja wiem dokładnie gdzie on poleciał. ale tak wcale być nie musi.

    Mogłoby być np. coś takiego

    InvocationException in memory cell 561275
    
    I dalej 150 dziwnych linijek zdradzających konstrukcje procesora. Stacktrace w Javie7 jest po prostu na tym samym poziomie abstrakcji co język a w javie8 i Scali jeszcze nie! Ale głowa do góry bo już gdzieniegdzie jest to poprawione. Np. Tak wygląda jeden z błędów w Playu.

    Jak nie widać co jest na obrazku to trzeba w niego kliknąć. Generalnie nie ma tam błędu w stylu anon$12 czy coś w tym stylu ale jasno jest napisane, że nie ma obiektu danego typu a jedynie klasa i dla mnie osobiście ten poziom jasności jest wystarczający aby wiedzieć co się dzieje. Na scaladays 2013 było wystąpienie tego gościa od Springa co tam teraz w Ławie Typesafe zasiada i jasno dał im do zrozumienia, że zamiast jarzyc się tym, iż można całkę po granicy zbiorów nieokreślonych obliczyć w jednej linii - mają zrobić stacktracy czytelne dla zwykłych ludzi oraz stworzyć jakieś IDE, którego nie będą musieli się wstydzić - podejście zaczyna chyba działać.

    Wracając jeszcze do percepcji stacktrejsów - generalnie kiedyś pisałem kod w stylu :

    MOV A,10
    
    Ta magiczna instrukcja umieszcza wartość 10 w akumulatorze procesora Z80 (tak tak pracownia była super zaawansowana). Ponieważ technikum orało mi mózg tym poziomem abstrakcji przez 5 lat to jak na studiach zobaczyłem : int a=a+1 to też się głowiłem jak to będzie można debugować jak nie wiadomo do którego akumulatora to trafia i z jakiej komórki pamięci. Tutaj jest fajna prezentacja o tym jak szybko technologie się zmieniają a ludzie zbyt wolno ---> Bret Victor - The Future of Programming

    Z życia wzięte

    Podobny mechanizm działa w korpo gdzie jedne levele abstrakcji komunikują się z innymi levelami abstrakcji. A piszę o tym tylko bo przypomniał mi się dowcip (uwaga dowcip):

    - jak facet nie może dojść to wina faceta
    - jak kobieta nie może dojść to wina faceta
    
    I teraz w wersji korpo :
    - jak biznes nie rozumie informatyków to wina informatyków
    - jak informatycy nie rozumieją biznesu to wina informatyków
    
    Ten obraz skutecznie podsycają różnego typu konsultanci aby nachapać więcej kapusty w kieszenie ale to już inna historia...

    Podsumowanie

    Konferencja bardzo fajna i za rok na pewno też pojadę chyba, że zaatakują ruscy - wtedy trzeba będzie znowu programować głowice jak w starym dobrym magnetofonie od C64 (chociaż nie, nie takie głowice)