17 października 2012

Opóźnienia z => ciąg dalszy ze scala.Predef

2 komentarzy
Kiedy pisałem Różne miejsca wystąpienia => w języku Scala nie sądziłem, że symbol implikacji w Scali będzie mnie tak prześladował. W komentarzu do tego wpisu, Grzesiek napisał "no daj spokój, deklaracja sposobu przekazania wartości parametru metody ma być znajomością Scali "na wyższym poziomie"?", a tu na wykładzie Lecture 3.5 w "Functional Programming Principles in Scala" pojawił się scaladoc dla scala.Predef z assert, w którym drugi argument jest message: => Any. Widzicie ten symbol implikacji => przy Any?

W ten sposób możemy oczekiwać jedynie wykonania wyliczenia komunikatu, kiedy assertion typu Boolean jest spełnione. Sprytne. To lubię! Sprawdź to sam!
$ sbt console
Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0-u10-b09).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def printMessage = println("Wykonano mnie")
printMessage: Unit

scala> printMessage
Wykonano mnie

scala> assert(true, printMessage)

scala> assert(false, printMessage)
Wykonano mnie
java.lang.AssertionError: assertion failed: ()
     at scala.Predef$.assert(Predef.scala:160)
     at .<init>(<console>:9)
     at .<clinit>(<console>)
     at .<init>(<console>:11)
     at .<clinit>(<console>)
     at $print(<console>)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
     at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:914)
     at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:546)
     at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:577)
     at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:543)
     at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:694)
     at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:745)
     at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:651)
     at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:542)
     at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:550)
     at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822)
     at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:851)
     at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:73)
     at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:64)
     at sbt.Console.console0$1(Console.scala:23)
     at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
     at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
     at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
Pewnie domyślasz się, skąd ten wyjątek przy drugim wykonaniu? Niespecjalnie istotne w kontekście =>, ale znać, nie zawadzi.

15 października 2012

Notacja prefiksowa, infiksowa i static w Scali, Javie i Clojure

11 komentarzy
Zastanawia mnie, jak programujący w Scali czy Javie zaimplementowaliby metodę max, która zwraca element maksymalny dwóch lub więcej elementów, dla których porównanie zostało zdefiniowane, np. liczb i relacji mniejsze niż.

Mam nieodparte wrażenie, że zaproponowane rozwiązanie, ze względu na klasę tych języków jako obiektowych, w których kładzie się nacisk na definiowanie klas, będzie łamało zasady enkapsulacji i wyniesienia metody na poziom globalny przez zastosowanie słowa kluczowego static. I dlaczego statyczna metoda max w Javie trafiło to do klasy java.lang.Math zamiast java.lang.Number czy podobnie? Interesujący problem.

A wszystko za sprawą zajęć "Functional Programming Principles in Scala". Na wykładzie "Lecture 3.2 - More Fun with Rationals" (około 6:25) pojawiła się implementacja metody max.
class Rational(x: Int, y: Int) {
     ...
     def max(that: Rational) = numer * that.denom < that.numer * denom
}
Ten przykład uzmysłowił mi, że notacja prefiksowa (w Clojure domyślnie lub w Javie i Scali przez metody statyczne) sprawia, że nazwa operacji występuje przed argumentami. Uważam jednak, że użycie static gdziekolwiek w Javie czy Scali, sprowokuje uwagi osób przestrzegających zasad programowania obiektowego, aby nie stosować go, bo niszczy te zasady przez złamanie reguł enkapsulacji. W tym przypadku dobrze byłoby móc zdefiniować statyczną metodę max, która akceptowałaby wiele obiektów Rational i zwracała największy. Sądzę, że ten przykład na wykładzie był niezwykle niefortunny, bo promował zawężenie działania max do wyłącznie dwóch liczb oraz korzystał z notacji infiksowej, która w tym akurat przypadku jest niefortunna.
new Rational(1, 2).max(new Rational(1,3))
zamiast
max(new Rational(1, 2), new Rational(1,3))
Sądzę, że to drugie rozwiązanie odzwierciedla właściwiej fakt porównywania dwóch lub więcej elementów. Możnaby zastanowić się, co miałaby zwrócić ta metoda dla pojedynczej wartości?! Propozycje mile widziane (a dociekliwych zapraszam do przestudiowania rozwiązania w Clojure - clojure.core/max).

I jakby na zamówienie, dzisiaj w skrzynce znalazłem maila od DZone z Refcard dla Scali! Promocja Scali działa pełną parą. Warto rozważyć podobne arkusze dla Clojure, podstaw programowania współbieżnego w Javie i Groovy. Miłej lektury.

14 października 2012

Różne miejsca wystąpienia => w języku Scala

6 komentarzy
Podczas zajęć "Functional Programming Principles in Scala" dowiedziałem się o możliwości definiowania parametrów wejściowych funkcji typu by-name, których wartość wyliczana jest z opóźnieniem - na czas, kiedy ich wartość jest potrzebna i z naciskiem na możliwe skutki uboczne. Zapis takiego parametru składa się ze znaku implikacji => oraz nazwy parametru funkcji. Jak rozumiem ze zdania "This feature must be applied with care; a caller expecting by-value semantics will be surprised." znajomość tej konstrukcji należy do tych rzadko stosowanych i sugeruje znajomość Scali na wyższym poziomie, a mimo to pojawiło się na początkowej lekcji "Functional Programming Principles in Scala" i dodatkowo było przedmiotem ćwiczenia (!) Widać, że Odersky'iemu zależy na znajomości tej konstrukcji i trzeba mieć się na baczności.

Przyjrzyj się takiemu zapisowi funkcji i pomyśl, jaki będzie efekt wykonania jej.
scala> def f(y: Int, x: => Int) = y
f: (y: Int, x: => Int)Int

scala> f(5, 1000^100000000)
res2: Int = 5
Jeśli dobrze rozumiem materiał, to wykonanie f powinno być równie efektywne co wykonanie f(5, 1), czyli skoro drugi argument funkcji jest wyliczany na czas użycia, a nie jest użyty w powyższym przykładzie, to do obliczenia wartości w ogóle nie dojdzie.

Na wykładzie o funkcjach wyższego rzędu pojawiła się notacja parametru wejściowego funkcji, który jest również funkcją i tutaj ponownie pojawił się symbol implikacji =>. To był ten moment, w którym kolejny raz naszło mnie na rozmyślanie o stałych jako swego rodzaju funkcji, które wyglądają jak funkcje stałe, ale różnią się tym, że nie są literałami funkcyjnymi a prymitywami.
scala> def g(h: () => Int) = h()
g: (h: () => Int)Int

scala> g(() => 5)
res8: Int = 5
Sądzę, że zrozumienie różnicy między stałymi a funkcjami stałymi ma niebagatelne znaczenie w poznawaniu zachowania języka wspierającego konstrukcje funkcyjne. W znanych mi językach - Java, Clojure, Scala - 5 jest zawsze 5 i "wykonanie" jej nie pozostawia śladu, podczas gdy wykonanie funkcji stałej zwracającej 5 może pozostawić swój ślad w środowisku.

A skąd mnie naszło na rozprawianie o tym?

Porównajmy zapis deklaracji argumentu wejściowego po nazwie x: => Int od deklaracji argumentu będącego funkcją f: Int => Int. W pierwszym przypadku definiujemy parametr wyliczany z opóźnieniem, w drugim podobnie, ale mamy dla tego specjalną nazwę - funkcja. Funkcja to obliczenie, które będzie wykonane na czas jego wykonania. Bardzo podobnie do owego opóźnionego wyliczania dla x: => Int. Jak zaznaczono w już wspominanym rozdziale Call by name w Effective Scala użycie funkcji do celów modelowania opóźnienia wykonania jest zalecane jako jawne wskazanie opóźnienia.

Zatem foruje się podejście oparte na funkcji.
scala> def f(y: Int, x: () => Int) = y
f: (y: Int, x: () => Int)Int

scala> f(5, () => 1000^100000000)
res9: Int = 5
Różnica niewielka, a jakie konsekwencje!

Ot, taka ciekawostka (para)naukowa, której objawienia mogłem doświadczyć podczas analizowania wykładu.

12 października 2012

Rozpocznij swoją przygodę z językiem Scala

5 komentarzy
Wzięło mnie ponownie na poznawanie Scali. Miałem już kilka spotkań z tym językiem, ale zwykle kończyło się na dumaniu, gdzie mógłbym to zastosować i ostatecznie brakiem pomysłów i zarzuceniem nauki. Jeszcze przed Euro 2012 coś tam liznąłem, aby 30 kwietnia doświadczyć wyczerpania weny.

I tak to trwało, i trwało, aż coursera udostępniła zajęcia "Functional Programming Principles in Scala".

Zacząłem z 2 tygodniowym opóźnieniem i przyszło mi nadrabiać zaległości. Co mnie najbardziej zdumiewa to to, że nie sądziłem, że mnie aż tak wciągnie. Chyba łatwość języka (w porównaniu z poznawaniem Clojure) sprawia, że jakoś tak pisze się w Scali naturalnie (żeby nie napisać aż nazbyt znajomo). Martin Odersky prowadzi zajęcia w przyzwoity sposób i chce się w tym uczestniczyć. Nie mam obaw, aby polecić te zajęcia.

Ciekawostka: na dzisiejszym spotkaniu dot. warsjawa 2012, na 4 organizatorów aż 3 uczestniczy w tych zajęciach!

Jeśli zastanawiasz się, jak zacząć swoją przygodę z językiem, proponuję zapisać się na te zajęcia, a co najmniej instalację Scala IDE for Eclipse, które dostarczane jest z bardzo użyteczną funkcją - Scala Worksheet. Tworzysz taki "brudnopis" i każde wpisanie poprawnego wyrażenia w Scali jest wykonane przy następnym zapisie. Niezwykle wciągające narządko.


Można również zainstalować sbt, ale na początek Scala IDE wystarczy. W końcu to początek i ostatnią rzeczą, jaką należałoby zrobić to zawalić kompa narzędziami, których szybko nie przyjdzie nam używać, a ich nieużywanie będzie nam ciążyło! Nie mówię, że są niepotrzebne, ale początek zróbmy sobie delikatnym wstępem do środowiska Scala i całą energię skupmy na poznawaniu składni i programowania funkcyjnego.

Dla czytelników pragnących łyknąć trochę wiedzy teoretycznej proponuje się Programming in Scala, First Edition oraz Programming Scala (żadnej jeszcze nie czytałem, więc nie pytajcie, co o nich sądzę - stąd ta bezosobowa zachęta w postaci "proponuje się").

Mamy również książkę po polsku - Język programowania Scala od Grześka Balcerka. Jeszcze jej nie czytałem, a czeka na mnie już dobre kilka miesięcy! Jak wieść niesie, niedługo warsztaty Grześka z funkcyjnej Scali! Pierwszymi miastami mają być Poznań i Warszawa. Może pora uruchomić pierwszy hack-a-thon ze Scalą w Warszawie? Co o tym sądzicie? Ciekawym efektów programowania cały weekend w jakimś podziemiu :)

27 września 2012

Warsjawa potrzebuje Cię!

1 komentarzy
To nie pierwszyzna dla wielu z Was. Większość przyzna, że publiczne wystąpienia są potrzebne do ugruntowania wiedzy, a bywa, że wręcz do jej zdobycia. Trudno również zaprzeczyć, aby nie miało to żadnego wpływu na naszą karierę. Z własnego doświadczenia wiem, że prowadzenie szkoleń pozwala na sprawniejsze zapamiętanie tematu i wyrobienie sobie pewnych nawyków, które zwykliśmy nazywać doświadczeniem lub intuicją. Po prostu człowiek wie, nie wiedząc dlaczego.

27 października członkowie grupy Warszawa JUG organizują konferencję warsjawa 2012, która w zamierzeniu ma "praktyczne podejście do problemów związanych z tworzeniem oprogramowania na platformie Java (JVM), począwszy od Agile, Scrum, przez Software Craftsmanship, a skończywszy na konkretnych językach programowania (Clojure, Scala, Groovy, JRuby) czy rozwiązaniach (szkieletach, rusztowaniach i kompletnych produktach) budowanych z ich pomocą. Mile widziane są również tematy związane z tworzeniem aplikacji mobilnych na Androidzie."

Myślisz, że nie może Cię na niej zabraknąć? Wierzysz, że udział w roli uczestnika nie będzie dostatecznym wyzwaniem i nie spełni Twoich oczekiwań? Chcesz być prelegentem i poprowadzić warsztat z interesującej technologi bądź języka? Potrzebujesz się sprawdzić w boju, a projektów jak na lekarstwo? Zachęcam do zgłoszenia swojego tematu w formularzu Rejestracja prelegentów - Warsjawa 2012. Nikt za Ciebie tego nie zrobi. Musisz zrobić to Ty!

Wciąż się wahasz? Zapytaj na forum grupy Warszawa JUG, co inni sądzą o Twoim pomyśle. Możesz być mile zaskoczony/-ą!

20 września 2012

Współbieżność i Android na Mobilization^2

0 komentarzy
W najbliższą sobotę będę miał przyjemność występować na konferencji Mobilization^2 w Łodzi, podczas której przedstawię temat "Zrównoleglanie zadań w Javie na platformie Android". Prezentacja będzie podsumowaniem dotychczasowych doświadczeń w rozpoznaniu tematu zrównoleglania zadań na platformie Android i liczę na kontakt z osobami, których tematyka intryguje, a moje wystąpienie stanie się swoistym katalizatorem dalszych studiów.

Prezentacja zaplanowana jest na godzinę 10:15 w sali F10 – Fortress. Reszta na stronie konferencji. Zapraszam!

11 września 2012

Znalezione w skrzynce: Do czego mi Clojure?

9 komentarzy
Właśnie dostałem do skrzynki maila, który odzwierciedla większość pytań i wątpliwości, jakimi zarzucają mnie moi rozmówcy w temacie Clojure. Postanowiłem opublikować moją odpowiedź, która specjalnie nie wnosi nic nowego w temacie, ale być może zainspiruje do ciekawej dyskusji o sensowności...właśnie! Czego ta sensowność miała by dotyczyć?! Pytanie pozostawiam otarte.

> Na pikniku rzuciłeś pytanie "W jaki sposób przekonać programistów Javy do
> użycia Clojure w swoich projektach?". Poczytałem trochę na ten temat i
> jedyne co mi nie pozwala używać tego języka to to, że po prostu nie mam
> czasu na naukę nowych języków. Musisz wziąć pod uwagę to, że ja reprezentuje
> jak to powiedziałeś "żółtodziobów" (chociaż za takiego się nie uznaję). Ja
> swój czas zamierzam poświęcić na naukę technologi takich jak Spring , JPA,
> JSF,EJB, SQL itd. Są to technologie które najczęściej występują w
> ogłoszeniach o pracę i jest ich tak dużo że nie ma czasu na naukę Clojure.

Cześć XXX,

Święta racja! W zasadzie nic dodać nic ująć, ale zastanów się, ile
osób tak myśli. Sądzę, że cała masa. Właściwie nawet więcej, co
sprawia, że przebicie się na lidera w tej grupie jest zadaniem
wymagającym dużego nakładu pracy. A może by tak warto rozważyć
poświęcenie nie mniej czasu na coś odmiennego, co sprawi, że jeśli
wartościowe (podkreślam słowo "jeśli") da Ci gwarantowaną przewagę.
Czy w takim świetle Clojure wypada ciekawiej?

> -powiedział ile czasu zajmie nauka Clojure
> -powiedział jak szybko można zrobić coś co działa w Clojure
> -do czego ten język wykorzystuje się w praktyce, jakiś konkretny przypadek w
> którym Clojure jest bez cenny ( bo jak sam stwierdziłeś że przykład z
> wyświetlaniem daty nie za bardzo wszystkich przekonał)
> -zapewnił że użycie Clojure jest stabilne, można go obdarzyć zaufaniem
> To prawdopodobnie kupił bym Clojure In Action i zaczął przerabiać kolejne
> rozdziały.

Czy potrafiłbyś odpowiedzieć na te pytania, gdyby zamiast Clojure
występowało Java lub inny język programowania? Celem Clojure było
przybliżenie programowania funkcyjnego do platformy Java i wielu
przypadło to do gustu. Jak to bywa, znalazło się też wielu, którym
niekoniecznie. Trudno powiedzieć, kto ma rację, bo gdyby tak było, nie
byłoby tylu języków programowania.

Nie oczekuj od innych, że powiedzą Ci, jak masz żyć. To Twoje życie,
Twoje wybory i co dla jednego wpadką, dla innego sukcesem. Wszystko
zależy od nastawienia. Moje jest otwarte na nowe, a że udaje mi się
zwykle trafiać w ciekawe technologie/języki, nie obawiam się o własną
przyszłość znając Clojure. Na pewno poszerza horyzonty.

> Ogólnie Java jest językiem w którym można zrobić wszystko i należało by
> wskazać taką rzecz która w Javie jest za obszerna. Jakieś porównanie ile to
> trzeba się na główkować w Javie a w Clojure robi się to w prosty sposób i
> można się zająć innymi rzeczami.

Weźmy trywialne przechodzenie po liście. A teraz pomyśl, że to cały
strumień danych. Współbieżność. Zwartość kodu funkcyjnego jest nie do
przecenienia w porównaniu z obiektowym. Oba jednak mają swoje plusy i
minusy.