15 października 2012

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

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.