29 października 2012

Różnica między wyrażeniem a wyrażeniem (instrukcją)

3 komentarzy
Istnieje różnica między wyrażeniem a wyrażeniem. Jaka?! - zapytasz? Natychmiast idzie to wyłapać przy przejściu na język angielski, w którym mamy dwa różne słowa odpowiadające pojedynczemu w polskim - "expression" oraz "statement" (aczkolwiek dla tego drugiego Google Translator wskazuje na "oświadczenie" czy "deklaracja" przed "wyrażenie").

Jeśli pracujesz z językami imperatywnymi, np. Java, w których króluje "statement" i/lub językami funkcyjnymi, np. Scala lub Clojure, w których prym wiedzie "expression", warto znać różnicę. Przyznaję, że mi to trochę zajęło (zajęcia na studiach jakoś tak wtedy nużyły).

Niby oczywista jest ta różnica, ale nie wszyscy ją wyłapują. U mnie długo trwało zanim zaskoczyło. "expression" zawsze zwraca wartość i jest jej reprezentantem, a "statement" może, ale nie musi i zwykle stosowany jest dla skutków ubocznych, np. przypisanie częściowego wyliczenia do zmiennej poza nim, np. pętla for w Javie.

Od tej chwili usilnie próbuję zapamiętać, że w językach funkcyjnych korzystamy wyłącznie z "wyrażeń", podczas gdy w imperatywnych również i "instrukcji" (patrz Wikipedia w Instrukcja (informatyka) w sekcji Wyrażenia).

I już nie mam problemów ze wskazaniem wyrażenia od instrukcji. A nawet w tłumaczeniu!

Dla zwrócenia uwagi, posłużę się kawałkami kodu w Clojure.

If jest specjalną formą (= wyrażeniem) w Clojure (w przeciwieństwie do Javy) i działa na podobieństwo funkcji, które można przypisywać (aliasować), przekazywać do czy zwracać z funkcji.
user=> ; przypisanie
user=> (def if-inside
  #_=>   (if nil "nil jest prawda" "nil nie jest prawda"))
#'user/if-inside
user=> if-inside
"nil nie jest prawda"

user=> ; przekazanie do funkcji
user=> (defn my-fn [if-stmt]
  #_=>   if-stmt)
#'user/my-fn
user=> (my-fn if-inside)
"nil nie jest prawda"

user=> ; zwrocenie z funkcji
user=> (defn my-fn-returns-if-stmt [if-stmt]
  #_=>   (fn [] if-stmt))
#'user/my-fn-returns-if-stmt
user=> (my-fn-returns-if-stmt if-inside)
#<user$my_fn_returns_if_stmt$fn__3525 user$my_fn_returns_if_stmt$fn__3525@2304a962>
user=> ((my-fn-returns-if-stmt if-inside))
"nil nie jest prawda"
Proste, co?

A może jednak nie? Pytaj, aby było! Mówią, że to podstawy podstaw programowania funkcyjnego i brak zrozumienie fundamentów może negatywnie "promieniować" na dalszą znajomość jego.

25 października 2012

Ja z TomEE na JDD 2012 w Krakowie

11 komentarzy
Nie mam co do tego jakichkolwiek wątpliwości - krakowskie JDD na stałe wpisało się w harmonogram polskiej społeczności javowej, a ostatnie ruchy proidei ku umiędzynarodowieniu jej przynoszą wciąż niewielkie, ale zauważalne rezultaty. Wciąż jednak uważam, że JDD to bardzo lokalna konferencja, która jedynie przez swoje usytuowanie (Kraków) potrafi przyciągnąć uczestników i prelegentów. Na moje oko przewinęło się przez nią 200 osób w szczycie, a prelegenci wciąż nie zachwycają. Wciąż brakuje mi na niej nazwisk, które mogłyby gwarantować poziom wystąpienia i możliwość zamienienia słowa już po. Właśnie ta cecha konferencji, gdzie siedzę z prelegentami (częściej) i uczestnikami (rzadziej) sprawia, że JDD i inne konferencyjne propozycje inspirują mnie do dalszego rozwoju i poszukiwań.

Konferencja JDD 2012 trwa 2 dni - 25.10 (czwartek) i 26.10 (piątek) - ale ze względu na kolejne wyjazdy konferencyjne na Ukrainę na JavaDay musiałem zadowolić się jedynie pierwszym dniem i spotkaniem wieczornym dzień wcześniej. Podczas dnia konferencyjnego wystąpiłem z prezentacją o Apache TomEE, który jak zapewne uczestnicy już dobrze pamiętają, jest "zwykłym" Apache Tomcat plus dodatki. Owe dodatki sprawiają jednak, że pracujemy z certyfikowanym środowiskiem spełniającym wymogi specyfikacji Java EE 6 Web Profile (TomEE). Mamy również do dyspozycji edycje rozszerzone o JAX-RS (TomEE JAX-RS) czy JAX-WS i JMS (TomEE+). Jak możnaby to określić - dla każdego coś dobrego.

Tylko po co mi kolejny serwer aplikacyjny? I to jeszcze jakiś tam TomEE? Zajrzyj do prezentacji, a może coś jednak znajdziesz w TomEE dla siebie?



Gdyby zliczać liczbę wystąpień frazy "TomEE is Tomcat" to pewnie byłaby to najczęściej wspominana fraza podczas mojego wystąpienia. Moim założeniem było odpowiedzenie na pytanie "Dlaczego TomEE?" i mimo, że robiłem, co mogłem, to i tak na koniec padło pytanie "Po co mi TomEE?" :-) Możnaby zapłakać, ale faktycznie ucieszyłem się. W końcu kiedy to pytanie padło, to skoro padło, to znaczy, że niewystarczająco dobrze wyjaśniłem tę kwestię, a pytanie z tłumu posłużyło jako dodatkowy katalizator, aby inni zwrócili uwagę na moją odpowiedź, co życzyłbym sobie, aby było na samym początku. Siła pytania od publiczności uważam, że jest porównywalna z moimi staraniami, aby odpowiedź przebiła się do umysłów uczestników i każda pomoc mile widziana. Mam wrażenie, że teraz, po 50 minutach mojego wystąpienia, kilku zgodziłoby się na spędzenie kilku chwil z TomEE w swoich rozwiązaniach. Naprawdę warto, bo wszystko, co nowe rozwija, a praca z TomEE to praca z Tomcatem plus uzupełnienia do profilu webowego Java EE 6. Nie będę gołosłowny, kiedy powiem, że tworzenie aplikacji webowych z TomEE jest znacznie przyjemniejsze niż z czystym Tomcatem. Spróbuj i postaraj się skontrować moje tezy.

Nadmienię, że w zanadrzu mam(y) przecież jeszcze IBM WebSphere Application Server V8.5 Liberty Profile, którym jestem zafascynowany i który może wydawać się być łudząco podobny do Apache Tomcat czy Apache TomEE, ale faktycznie nimi nie jest i ma również swoje małe poletko, na którym rządzi niepodzielnie lub za chwilę będzie - patrz Enterprise OSGi i wykorzystanie kodów źródłowych pełnego WASa. To dla związanych z WASem stanowi niebagatelny powód, aby przystanąć w rzędzie korzystających z Liberty Profile. W końcu, jeśli docelowym środowiskiem uruchomieniowym będzie IBM WebSphere Application Server, to ostatnią rzeczą, jaką należałoby zrobić, jako programista, to korzystać z serwera alternatywnego, a najgorszym rozwiązaniem byłoby korzystanie z serwera o mniejszych możliwościach, chociażby na płaszczyźnie pełności wsparcia dla specyfikacji Java EE. Czyż praca z Tomcatem przed wejściem na WASa, to nie obdzieranie ze skóry możliwości WASa i obniżania wartości cech, które udostępnia?! Warto o tym pamiętać, na długo zanim zacznie się psioczyć na środowisko docelowe - może to być związane z niewłaściwymi oczekiwaniami, których sami jesteśmy autorem (!)

Jeśli chcesz spróbować się z WAS V8.5 Liberty Profile, zachęcam do lektury moich artykułów. Oferuję dodatkowo swoją pomoc (licząc, że sam ją również otrzymam). Ty zadajesz pytania, ja odpowiadam - wirtualnie przez artykuły, fizycznie, siedząc przy kompie ramię w ramię. Podejmiesz wyzwanie? Spotkania WJUGowe czekają :-)

Organizatorzy konferencji wraz z radą programową, w skład której wchodził m.in. ten Sławek Sobótka, pozwoliła mi na uchylenie rąbka tajemnicy o sensowność zastosowania TomEE. Okazało się, że pytanie o wdrożenie produkcyjne, które skwitowałem niemiłym ruchem ramionami na znak niewiedzy, już po moim wystąpieniu, sprowokowało jednego z uczestników do podzielenia się swoimi doświadczeniami w produkcyjnym użyciu TomEE. Jest jednak w Polsce produkcyjne wdrożenie, którego wyłącznym celem było przesyłanie plików za pomocą Web Services i Tomcat^H^H^H...ekhm...to znaczy TomEE...świetnie się do tego nadawał. Osoba rekomendująca nie miała problemów z wyborem po krótkim spotkaniu z TomEE. Działa i na to użycie sprawdza się znakomicie. Branża bankowa.

Mieć wybór - to lubię najbardziej! Jeśli wydawało Ci się, że świat kończy się na JBoss AS, Glassfish czy Tomcat, to teraz dorzucam jeszcze WAS V8.5 Liberty Profile, Apache TomEE, Apache Geronimo i jeszcze nie sposób nie wspomnieć o Oracle WebLogic Server czy Jetty. Mnogość rozwiązań może przerazić, a to pewnie i tak jedynie ułamek wiedzy, której się od nas wymaga.

A skoro o wiedzy, to podczas spotkania wieczornego, Kuba z Allegro pozwolił sobie przypomnieć mi o referencjach w Javie - Weak-, Soft- oraz PhantomReference. Zawsze jakoś odkładałem rozpoznanie ich na półkę z innymi rzeczami oczekującymi mojej uwagi, ale teraz zostałem przywołany do porządku i muszę usiąść nad nimi i zrozumieć ich zastosowanie w praktyce. W końcu to jedynie 5 klas z pakietu java.lang.ref (!) Znasz? Korzystasz? Podziel się wrażeniami! Zawsze to przyjemniej być prowadzonym przez bardziej doświadczone osoby.

Właśnie to najbardziej cenię sobie w możliwości udziału w konferencjach - bezpośredni kontakt z osobami, z którymi trudno byłoby mi się spotkać w innych sytuacjach. Jakkolwiek moim obecnym marzeniem byłoby omówienie TomEE i Liberty Profile, to sam TomEE dał mi również wiele satysfakcji. Był także miły wieczór w doborowym towarzystwie i było wystąpienie na drugi dzień - nie mogę narzekać. Tylko trochę żałuję, że nie mogłem zostać na imprezie integracyjnej z czwartku na piątek, bo wydawało mi się, że wielu mogłoby jeszcze zagadnąć mnie o sensowność TomEE, Liberty Profile czy wręcz Clojure. Szkoda.

Moje slajdy z prezentacji Apache Tomcat + Java EE 6 Web Profile = Apache TomEE znajdują się już na slideshare. Miłego oglądania i gorąco zachęcam do komentarzy. Kiedy dwóch rozmawia, to nierzadko prowokuje do konfrontacji aktualnej wiedzy, której kwestionowanie prowadzi do dalszego rozwoju. Skoro ciągła integracja jest tak ważna w naszej profesji, to można wnioskować, że ciągła integracja społeczna również. Czego Tobie życzę.

p.s. Nagrania z prezentacji mają się pojawić w Sieci wkrótce. Podobnie zdjęcia.

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 :)