Scala i bezpieczny "duck typing"

Opublikowane przez Jarosław Zabiełło Sat, 23 Jan 2010 06:40:00 GMT

Duck typing (opisywany przeze mnie wcześniej na przykładzie Pythona) to dosyć użyteczna technika popularna w językach dynamicznie typowanych. W typowym języku statycznie typowanym, takim jak Java, nie da się jej stosować. Ale ograniczeniem nie jest statyczne typowanie, lecz to że Java, jako język, jest po prostu słaba. W statycznie typowanej Scali “duck typing” to żaden problem. Mało tego. Fakt, że Scala jest statycznie typowana daje jej tu dodatkową przewagę na językami dynamicznie typowanymi.

Duck typing w języku dynamicznie typowanym ma pewne wady od których Scala jest wolna. Wpierw przykład dla języka Ruby:

class Kaczka
  def kwacz
    puts "kwa kwa" 
   end
end   

class Slowik
  def kwacz
    puts "fiu fiu" 
  end
end

class Kot
  def miau
    puts "miau miau" 
  end
end

def kwacz_kaczuszko(k)        
  k.kwacz
end

kwacz_kaczuszko(Kaczka.new) # => kwa kwa
kwacz_kaczuszko(Slowik.new) # => fiu fiu
kwacz_kaczuszko(Kot.new) 
# => NoMethodError: undefined method ‘kwacz’ for #<Kot:0x000001010195d8>

Błędy tego typu są trudne do wyłapania w językach dynamicznie typowanych, bo o ich wystąpieniu można się dowiedzieć dopiero w trakcie działania programu. I jeśli taki fragment kodu jest wykonywany rzadko, to trudno powiedzieć kiedy zostanie wychwycony. Jedynym sposobem aby tak błąd odpowiednio wcześniej wyłapać jest pisanie dodatkowych testów jednostkowych.

Co prawda, powyższy kod można co prawda lekko zmodyfikować (bo Ruby pozwala na ładne odpytanie obiektu, czy jest w stanie wywołać daną metodę)

def kwacz_kaczuszko(k)        
  if k.respond_to? :kwacz      
    k.kwacz                
  else
    puts "ja nie kwaczę!" 
  end
end

kwacz_kaczuszko(Kot.new) # => ja nie kwaczę!

Tylko czy to coś zmienia? Zamiast pisać dodatkową obsługę takiego błędu, nie lepiej go po prostu nie mieć?

Scala takie błędy wyłapuje już na etapie kompilacji. Tym samym gwarantuje (statycznie) że do kodu nic takiego się nie prześliznie. Można powiedzieć, że Scala obsługuje “duck typing” w sposób bezpieczny, prawidłowy. Odpada pisanie testów jednostkowych i obsługiwanie takich błędów bo w Scali one nigdy się nie pojawią!

class Kaczka {
  def kwacz {
    println("kwa kwa")
   }
}

class Slowik {
  def kwacz {
    println("fiu fiu")
   }  
}

class Kot {
  def miaucz {
    println("miau miau")
  }
}                     

def kwacz_kaczuszko(k : {def kwacz}) {
  k.kwacz
}

kwacz_kaczuszko(new Kaczka) 
kwacz_kaczuszko(new Slowik)
kwacz_kaczuszko(new Kot)

/*
(fragment of przyklad.scala):25: error: type mismatch;
 found   : this.Kot
 required: AnyRef{def kwacz: Unit}
kwacz_kaczuszko(new Kot)
                 ^
one error found

!!!
*/

Tagi , ,  | 17 comments

Comments

  1. Avatar Chyba Cię pogło ;P powiedział about 4 hours later:

    Kiedy wreszcie zrozumiesz, że dobry język to nie jest język, do którego nawpierdalano wszystkich możliwych ficzerów?

    Jestem fanem Javy (a od jakiegoś czasu i Rubiego). Z początku byłem sceptycznie nastawiony do Rubiego, bo denerwowało mnie to, że niektóre rzeczy można robić na kilka sposobów (nadużywanie aliasów też mnie wkurzało) i chociaż nadal nie rozumiem tej manii aliasowania, to uważam, że chociaż ma 2 składnie na tworzenie domknięć, 2 na tworzenie Hasha itd, to jednak Ruby ma pomysł na siebie i nie wrzuca wszystkiego co się jeszcze da (np. parametrów nazwanych).

    Java jest świetnym językiem. Prostym, jednoznacznym – widzę coś w kodzie i od razu wiem co to znaczy, a nie tak jak w innych językach wszystko poprzeładowywane, np. w Rubym przeginają z przeładowywaniem operatorów ;P

    Jedyne co mogłoby być lepsze w Javie, to typy generyczne (powinny nie być wymazywane) – ale powodem tego jest kompatybilność wstecz, które też jest dobra.

    Myślisz, że programiści z Sun-a nie potrafią napisać takich śmiesznych ficzerów jakie ma Scala?

    Ta Scala to taki troszkę lepszy C# – ale to niby język funkcjonalny więc wszyscy muszą ohać i ahać bo nie wypada nic mówić xD

  2. Avatar Jarosław Zabiełło powiedział about 4 hours later:

    Java nie jest nawet językiem w pełni obiektowym. Aby móc porównywać języki programowania trzeba znać najpotężniejszy z nich, a ty co znasz? :) Polecam doskonałą prezentację Are we there yet? oraz obowiązkowo esej Paula Grahama Beating the Averages – otwierają umysł.

  3. Avatar zuber powiedział about 4 hours later:

    A czy kompilator Scala wykrywa już błędy logiczne? Bo, jeśli nie, to nadal trzeba pisać testy jednostkowe.

  4. Avatar Jarosław Zabiełło powiedział about 4 hours later:

    zuber: nigdzie nie twierdzę, że nie należy pisać testów jednostkowych. Twierdzę tylko, że dzięki statycznemu typowaniu trzeba ich pisać mniej. A kolega (koleżanka?), co napisał wyżej, że “java to świetny język” bredzi, bo nie wie o czym pisze. W następnym tekście dostanie się interfejsom…

  5. Avatar Chyba Cię pogło ;P powiedział about 5 hours later:

    Rozumiem, że znasz się bardziej na Scali, więc mam pytanie wolne od wszelkich docinków. Nie ma w tym języku statyczności, a jest za to: object SomeClass { }

    czy jest to jakoś ładnie połączone z metaprogramowaniem (jak jest to zrobione w Rubym)? Mogę tego obiektu teraz jakoś elegancko odpytywać o metody itd?

  6. Avatar Marek Dominiak powiedział about 6 hours later:

    Problem z Javą jest taki że gdy była wersja 1.4 i był pomysł aby dodać typy generyczne, i ze względu na wsteczną kompatybilność musieli je spaprać … One są do kitu :-) W .NET nie mieli tego problemu – mieli mniej wdrożeń więc pozwolili sobie na wsteczną niekompatybilność i dzięki temu mają tam normalne typy generyczne.

    Java już jest w użyciu od 95 roku i teraz ciężko wrzucić im jakieś udogodnienia dla developerów, chociaż w javie 7 mają być dodane proste closures .

    Zaletą javy jest jej prostota, język nie utrudnia czytania kodu, oczywiście dotyczy też to scali czy ruby’ego jeśli programista nie będzie mieć celu napisać to najkrócej i najciemniej jak się tylko da ;-)

    Jest dużo rzeczy w javie które mi nie pasują:

    - interfejsy (wole traitsy :-), - MIXINS (chociaż powstał framework http://www.qi4j.org/ w którym można robić MIXIN-y, to i tak wolę mięć to na poziomie możliwości samego języka) - wkurza mnie ciągłe pisanie nazwy typu gdzie to jest oczywiste - brak closures - niezrozumiałe typy generyczne - pewnie wiele więcej

    Podoba mi się podejście w scali że programiści sami zdecydują które feature’y będą w bibliotece standardowej po pewnym czasie – (biblioteki wyglądają jakby były wbudowane w składnię języka) niż wrzucanie durnych feature’ów do składni języka…

    Siłą javy są jej frameworki – Spring, Hibernate, EJB, Seam i 1000 innych :-)

    Jeśli miałbym wybór w pracy wolałbym pisać w scali – zresztą do małych problemów pewnie będę próbować.

  7. Avatar Jarosław Zabiełło powiedział about 6 hours later:

    Do odpytywania obiektu o metody w Scali używa się tego samego mechanizmu co w Javie – refleksji. Zaimplementować znane w Ruby .methods w Scali jest proste. Co do samej znajomości Scali, to wypada wpierw zapoznać się z podstawami, a potem dopiero krytykować. Nie wiem czy czytałeś mój wcześniejszy tekst o Scali. Polecam też świetną serię artykułów o Scali napisanych dla programistów Javy: Roundup: Scala for Java Refugees.

    Frameworki Javy to bardziej frameworki JVM, więc są dostępne tak samo dla Javy jak i dla Scali, czy Clojure. Nic nie stoi na przeszkodzie aby użyć Wicketa w Scali (choć na pewno bardziej naturalne byłoby użyć Lifta)

    Tak w ogóle, to komentarze w blogu niezbyt się nadają do dyskusji. Zapraszam zatem na nasz polski kanał IRC’owy #scala.pl (dostępny też z poziomu zwykłej przeglądarki)

  8. Avatar :P powiedział about 8 hours later:

    Linki, które podałeś już widziałem xD Niestety mi Scala nie podchodzi. Ma dużo niepotrzebnych ficzerów, w dodatku brak im lekkości. Muszę przyznać, że na Scalowej refleksji się zawiodłem. Myślałem, że tutaj coś z Rubiego zostanie zaczerpnięte.

    Aczkolwiek statyczne języki mają w tym miejscu problem. Bo ciężko w nich zrobić elegancką refleksję, gdyż kilka metod może mieć tę samą nazwę :/

  9. Avatar lopex powiedział about 8 hours later:

    Jak można się zawieść na refleksji scali skoro ona nie ma własnego api do tego ? 20 Linijek z implicitami i możesz mieć nawet lepiej niż w ruby.

  10. Avatar ziom powiedział 1 day later:

    @P A które to ficzery scali są nie potrzebne według Ciebie?

  11. Avatar Jiima powiedział 2 days later:

    @JZ Trochę jesteś już męczący z tym “A Scala to to, a Java to tamto”. Tekst o generyczności scali brzmiałby dużo lepiej bez wynurzeń jak to w języku o wiele niższego poziomu jest gorzej. “Duck typing” to jedno, interfejsy to drugie. Rozwiązanie które podajesz jest czymś pośrednim (constraint, czyli coś jakby anonimowy interfejs który nie musi być explicite deklarowany). Nie pamiętam jednak czy Scala ma obsługę sygnału “method missing” czyli głównego piękna duck typing. Scalę z resztą nazwał bym raczej językiem pseudo-statycznie typowanym, właśnie ze względu na takie kwiatki jak ten constraint. Podobnie jest ze wspomnianym tu wcześniej C# 3.0 – odkąd wprowadzono w nim bezklasowe obiekty anonimowe i LINQ, oraz dynamiczne interfejsy (dla lepszej pracy z COM) język ten trudno nazwać statycznie typowanym (raczej “opcjonalnie statycznie typowanym” – tak jak FAN). Czy to źle, czy dobrze? Zależy od stylu programowania.

    Mnie w javie jedyne czego NAPRAWDĘ brakuje, to funkcji jako obiektów języka, lub chociaż namiastki tego takiej jak w .NET delegaty. No i sensownej składni – np podanie Klasa.nazwaFunkcji – (bez nawiasów) zwraca nam obiekt Function. No i po raz kolejny sensownej generyczności, ale to wiele razy powtarzano.

    Co do frameworków JVM jak ty to nazywasz, większość jednak ciężko sensownie użyć ze Scalą. Inne idiomy, inna logika programowania. Nie możesz łatwo np. ustawić funkcji scalowej jako listenera, musi istnieć jakaś warstwa pośrednia.

    Lift mi się nie podoba. Jest dziwaczny i ostatnio cicho na jego sajcie. Największą “zbrodnią” tego frameworka jest ciężkie wykorzystanie sesji – coś jak JSF i ASP.NET, ale one potrafią składować stan strony nie w sesji (pomijam czy jest to dobre rozwiązanie). Zrobienie lekkiego sajtu czy rozwiązań REST jest tu trudne. Co więcej nie da się tego replikować, a autorzy radośnie oświadczają, że replikacja sesji na serwerach J2EE w zasadzie nie działa, więc nie ma się czym martwić. Wyklucza to zastosowanie LIFTa w wielu miejscach, gdzie jednak trzeba pracować w klastrze.

    A co do interfejsów, rzeczywiście lepiej od deklarowania implementacji interfejsu powinna być możliwość przetestowania czy obiekt PASUJE do interfejsu i dynamicznie generować jakiś class cast exception. Tyle że coś za coś – takie podejście będzie prawdopodobnie wolniejsze w działaniu. No i gorzej się będzie pisać do tego narzędzia, takie jak IDE.

  12. Avatar Jarosław Zabiełło powiedział 2 days later:

    Jiima, wpadnij na #scala.pl to sobie wygodniej obgadamy kwestie jakie tu poruszyłeś. W ogóle, zanim ktoś coś większego napisze w komentarzu, niech lepiej wpadnie na nasz kanał IRC. Tak można szybciej wyjaśnić jakieś nieporozumienia.

  13. Avatar Jiima powiedział 3 days later:

    @JZ Może się pojawię, ale nie będę obiecywał. Mam mało czasu wolnego, a w robocie mamy poblokowane wszystko oprócz www i ssh jak to w firmach bywa…

  14. Avatar Jarosław Zabiełło powiedział 3 days later:

    Jiima: no to odpal ff z foxyproxy i ustaw sobie tunel, podalem przeciez link do webowego klienta do irca

  15. Avatar Moro powiedział 3 days later:

    Najbardziej przeładowany język to C++. Aż włos mi się języ na głowiek jak widzę co dodali w 0x. Myślałem, że jednym języku nie może być więcej “języków” a jednak w 0x jest kolejny :)

  16. Avatar psk powiedział 8 days later:

    Słaby pomysł z tym przenoszeniem wątku na irca. Zazwyczaj sporo się można było dowiedzieć na tym blogu właśnie z ciekawych komentarzy… Pozdrawiam

  17. Avatar mikołajS powiedział 9 days later:

    Scala bardzo mi się podoba. Jednak o ile się orientuje to zachwalane “concise” scali powoduje, że czytelność kodu scali może być zbliżona do kodu Perla, a sam język jest dużo trudniejszy do opanowania niż Java (ale to akurat mi się podoba :) ). Myślę więc, że nie będzie to nigdy popularny język programowania,

(leave url/email »)

   Pomoc języka formatowania Obejrzyj komentarz