wtorek, 5 maja 2015

Mechanika funkcji - zapowiedź warsztatów kilku

{tutaj wstaw dowolny fragment, który przekonuje cię do nauki programowania funkcyjnego}. Ale zanim zaczniemy uczyć się o Fabrykach monad i funktorach może warto przysiąść przy kawałkach kodu scali, które nie wiadomo dlaczego maja kilka par nawiasów zamiast jednej czy zrozumieć dlaczego w Playu przy tworzeniu konwerterów JSONa trzeba było pisać (_.tupled _)

Warsztaty

Warsztatów wyszło na 2.5 części :

Jest w sumie 10 zadań + różne takie ciekawe drążenia czaszki.

Czego będzie można się nauczyć

  1. Funkcja jako wartość - z tego co widziałem to programistą JAvy często wiesza się proces gdy coś co ma typ => w typ przekazują do czegoś co też ma typ => w typ
  2. Różne formy zapisu funkcji jak choćby : val f3:Int=>Int= _ + 3
  3. Coś na co nie zwracało się uwagi w Javie (do niedawna) kiedy funkcja to funkcja a kiedy metoda i kiedy metoda to metoda a kiedy funkcja.
  4. I coś moim zdaniem bardzo ważnego by nie odkleić się od rzeczywistości - przykłady ze słowami, które mogą pojawić się w codziennym życiu a nie tylko w książce od matematyki :
    //To na tę chwilę jedynie aliasy
    type Cash=Int
    type Policy= Cash=>Boolean
    type BusinessLogic= Cash=>Cash
    
    //Logika abstrakcyjna
    def cashService(p:Policy)(l:BusinessLogic)(c:Cash):Cash={
      if(p(c)) l(c) else 0
    }
    
    //niezależne i łątwe do testów funkcje
    def strictPolicy(c:Cash)=c>50
    def moneyMakesMoney(c:Cash)=c*1000
    
    //konkretna usługa
    val bank=cashService(strictPolicy)(moneyMakesMoney)_
    bank(100)  //res0: Cash = 100000
    bank(10)    //res1: Cash = 0
    
  5. Funkcje częściowe - po co są i jak są wygodne
  6. Lift,Lifting,Liftowanie,Podnoszenie - czy jak to się tam zwie - to już ciekawy koncept z FP jako takiego :
    val tekst: PartialFunction[String,String] = {
      case "tekst" => "TEKST"
    }
    //tekst: PartialFunction[String,String] = 
    
    val tekstLifted=tekst.lift //tekstLifted: String => Option[String] =  !!!
    tekstLifted("dupa")  //res0: Option[String] = None
    tekst("dupa") // scala.MatchError: dupa (of class java.lang.String)
    
    //i na powrót
    Function.unlift(tekstLifted) //res1: PartialFunction[String,String] = 
    
  7. I masa innych ciekawych rzeczy

Pierwszy warsztat pewnie uda się zrobić w drugiej połowie maja a drugą część jakoś na początku czerwca. Trzeba wycelować w złą pogodę i tyle.

Scala & Java 8

Spróbujmy zdefiniować sobie prostego acz zakręconego
Jest zwykła funkcja Int=>Int
zdefiniujmy funkcję, która zmodyfikuje tę pierwotną funkcję funkcję. (Int=>Int) => (Int=>Int)
Stwórzmy funkcję dekorującą, która przyjmie jakiś parametr typu Int Int=>....
zrobi currying Int=>(Int=>Int)
i zwróci funkcję, która przyjmuje pierwotną funkcję i dekoruje ją tak, że do wyniku dodaje podany wcześniej parametr i

val funkcja=(i:Int)=>(f:Int=>Int)=>(arg:Int)=>f(arg)+i
//typ to funkcja: Int => ((Int => Int) => (Int => Int)) = 
//wywołanie 
val curried=funkcja(2) curried: (Int => Int) => (Int => Int) = 
curried(_*5)(2) //12

Kompilator scali jak długo by nie pracował bardzo pomaga bo możemy skupić się na tym co po prawej
(i:Int)=>(f:Int=>Int)=>(arg:Int)=>f(arg)+i a typy zgadnie sam.
Jeśli bardzo chcemy możemy dać cały typ przy deklaracji:
val funkcja:Int => ((Int => Int) => (Int => Int))= i =>f => arg=>f(arg)+i
Albo wszystko na raz :
val funkcja2:Int => ((Int => Int) => (Int => Int))= (i:Int) =>(f:Int=>Int)=>(arg:Int)=>f(arg)+i

A jak to wygląda w Javie 8? Tutaj za dużo pomocy nie ma (albo ja coś robię źle) :

Function<Integer,Function<Function<Integer,Integer>,Function<Integer,Integer>>> function= i -> f -> (arg) -> f.apply(arg)+i;
Function<Function<Integer, Integer>, Function<Integer, Integer>> curried = function.apply(2);
Integer result = curried.apply(i -> i * 5).apply(2);

Linki i Nagrania z JUGa

Hello world w c++

object endl

//not thread safe!
object cout{
  private var texts=Vector.empty[String]
  def <<(s:String)={
    texts=texts :+ s
    cout
  }
  def <<(e :endl.type)=texts foreach print
}

cout << "Hello" <<" "<< "World c++" << endl;

------------------------------------------------------------------------------------------------------------------

2 komentarze:

  1. Takie szybkie pytanie (może gdzieś to jest napisane, ale jeszcze będę się dokładniej zapoznawał). Jeżeli istnieją operacje compose i andThen (które rozumiem) oraz koncepcja traktowania funkcji jako wartości to czy możliwa jest konwersja liczby (tak naprawdę dowolnej wartości dowolnego typu) do funkcji lub odwrotnie (a tym samym możliwość dodania funkcji i tej wartości). I czy to w ogóle miałoby sens.

    I jeszcze przy okazji: "To jest pierwszy moment gdzie standardowy prorgamista Javy moze dostać lekkiego przepalenia zwojów. Typ funkcji to nie "coś" ale "coś w coś".
    Coś - to typ wartości zwracanej przez funkcje, jak ktoś mówi, że typ funkcji to coś to albo za bardzo upraszcza bo go nie nauczono, albo stosuje popularny skrót myślowy.

    OdpowiedzUsuń
  2. cześć,

    Nie wiem czy o coś takiego ci chodzi :

    (1 to 10) map (()=>_)
    res6: scala.collection.immutable.IndexedSeq[() => Int] = Vector(, , ........

    OdpowiedzUsuń