26 kwietnia 2012

Opóźnianie wykonania w Scali

Dostałem dostęp do MEAP dla książki Functional Programming in Scala i poza lekturą bezpłatnego rozdziału wprowadzającego "Introduction", mam jeszcze możliwość przeczytania "Strictness and laziness". Na razie niewiele stron do czytania, bo jedynie 25, ale i tak poznałem stosunkowo wiele w obszarze programowania funkcyjnego ze Scalą jako językiem "wykładowym".

Tam też trafiłem na ciekawostkę opóźniania wykonania kodu w Scali, dla której w Clojure musiałbym zaprząc mechanizm makr (wciąż moją znajomość tematu określiłbym jako teoretyczną) lub utworzyć funkcję.

W języku Scala wystarczy użyć symbolu => - tego samego jak przy rozdzielaniu części funkcji - wejścia od wyjścia dla deklaracji typów i samego ciała funkcji. Brzmi pogmatwanie, ale należy to zrzucić na barki mojej niewielkiej znajomości tematu. Przykład powinien rozjaśnić zagadnienie.

Pytanie rozgrzewające: "Czy potrafisz wskazać element(y) języka Java, które pozwala na warunkowe wykonanie kodu?" Chętnie poznam Twoją odpowiedź - skorzystaj z możliwości komentowania.

W Scala sprawa przedstawia się jak poniżej. Uruchamiamy interpreter Scali - scala i do dzieła.
scala> def laaazy(x: => Int): Int = { println("Inside laaazy"); x}
laaazy: (x: => Int)Int

scala> laaazy({ println("Input argument"); 5 })
Inside laaazy
Input argument
res16: Int = 5

scala> def laaazy(x: Int): Int = { println("Inside laaazy"); x}
laaazy: (x: Int)Int

scala> laaazy({ println("Input argument"); 5 })
Input argument
Inside laaazy
res17: Int = 5
Czy potrafisz wskazać owe szczególne miejsce w powyższej sesji do opóźnienia wykonania? Zwróć uwagę na kolejność występowania napisów "Inside laaazy" praz "Input argument". Ciekawe, co? A jak zrealizował(a)byś to w Javie?

4 komentarze:

  1. We wskazanym przypadku ważniejszą częścią do omówienia jest wydaje mmi się fakt że korzystasz z tzw "by-name-parameter". Możesz wołać to o tak:

    laaazy {
    doStuffHere
    }

    Notacja "=> Cos" versus "() => Cos" ma się własnie tym zezwoleniem na takie napisanie wywołania twojej metody. // btw zapis () => Int to też tylko shorthand, tym razem na: Function0[Int] ;-)

    Cheers,
    Konrad

    OdpowiedzUsuń
  2. Możesz wyjaśnić dlaczego można przekazać 2 parametry mimo, że jeden jest zdefiniowany?

    Dziękuję.

    OdpowiedzUsuń
  3. Cześć Leszku,

    Pytasz o laaazy({ println("Input argument"); 5 })? Czy o { println("Inside laaazy"); x}? Czy może o jeszcze inny przypadek. W obu wskazanych przekazuję jeden - blok wykonywalny, którego ostatnią wartością jest 5, więc ona będzie zwrócona, a co za tym idzie przekazana jako wejście do laaazy.

    Jacek

    OdpowiedzUsuń