Poznajemy nowe języki: Scala, czyli jak wypisać elementy z listy

Posted by wiktor on Dec 12, 2007 in java, scala

Scala. Co to za język?

  • Scala została sklasyfikowana jako język funkcyjny, obiektowy, wielo-paradygmatyczny (mam nadzieję, że dobrze tłumaczę),
  • statycznie i silnie typowany,
  • obecna implementacja bazuje na JVM, niedługo można się spodziwać implementacji na .NET,
  • tak!, Scala działa na platformie Java, więc ma dostęp do całego ekosystemu bibliotek Javy,
  • nietuzinkową postacią jest sam twórca języka Martin Odersky, który jest współautorem obecnego kompilatora Javy oraz jest współprojektantem obecnych typów generycznych w Javie,
  • jest to młody język programowania i posiada wiele ciekawych własności, o których to będę pisał w kolejnych postach,
  • więcej: Scala na Wikipedii, strona domowa Scali, wywiad z twórcą języka.

OK, wezmę na warsztat prostą czynność: wypisanie elementów z listy.
Kod w Javie byłby następujący:

[Java]
List lista = new ArrayList() {{
add(1); add(2); add(3); add(4);
}};

for (Integer x : lista)
System.out.println(x);

// Można też tak, ale raczej nie bym nie polegał na metodzie toString()
System.out.println(lista.toString());

// lub po prostu:
System.out.println(lista);
[/Java]

Dla odmiany w Ruby’im zrobilibyśmy to tak:

[Ruby]
# tutaj akurat mamy tablicę
lista = %w(1, 2, 3, 4)

# żeby ładnie było to definiujmy println
println = lambda { |x| puts x }

lista.each &println
[/Ruby]

Zobaczmy teraz, jak zrobilibyśmy to w Scali.

[Scala]
val lista = List(1, 2, 3, 4)

lista.foreach((x: Int) => println(x))
[/Scala]

Brzydko… idziemy dalej. Scala jest językiem funkcyjnym, który ma mechanizm currying. Opuśćmy deklarację typu i nawiasy.

[Scala]
lista.foreach(x => println(x))
[/Scala]

Nadal brzydko… idziemy dalej. Co jest argumentem metody foreach? Sygnatura metody jest następująca:

[Scala]
def foreach(f: A => Unit): Unit
[/Scala]

Na potrzebę chwili traktujmy Unit tak samo jak void. Zatem argumentem foreach jest funkcja, która przyjmuje argument A (jakiś nieustalony typ, patrz: currying) i zwraca Unit. Natomiast println jest zdefiniowany tak:

[Scala]
def println(x: Any) = Console.println(x)
[/Scala]

czyli bierze jakiś argument (nadal patrz: currying, funkcje wyższego rzędu) i zwraca Unit. Zatem typy się zgadzają. Zapiszmy to krócej:

[Scala]
lista.foreach(println)
[/Scala]

Już lepiej, ale można jeszcze lepiej :) . Scala ma bardzo fajną własność, którą nigdzie wcześniej nie spotkałem. Mianowicie w Scali technicznie nie ma operatorów. Wyrażenie 1 + 2 jest tożsame z wywołaniem metody 1.+(2). Jeśli metoda przyjmuję tylko jeden parametr to można pominąć nawiasy oraz kropkę. Zatem:

[Scala]
lista foreach println
[/Scala]

Piękny zapis, nieprawdaż? :) A czy twój ulubiony język zrobi to lepiej?

Related Posts with Thumbnails

27 Comments

adriahu
Dec 12, 2007 at 6:30 pm

[perl]
@lista = (1, 2, 3, 4);
$\ = “\n”;
print for @lista;
[/perl]

Nie wiem czy lepiej, ale też ładnie ;)


 
adriahu
Dec 12, 2007 at 6:41 pm

No i python, też ładnie :)
[python]
lista = [1, 2, 3, 4]
for element in lista: print element
[/python]


 
Wiktor
Dec 12, 2007 at 6:51 pm

@adriahu

Perl? Hmmmm… ciekawe, ale widać jaką magię Perla w drugiej linijce :) . Gdybym to gdzie indziej zobaczył to pewnie bym się nie domyślił, o co chodzi :) . Użyteczna jest konstrukcja print for.

Python? Też ładnie, ale print element powinno się znajdować w następnej linijce ;) .


 
adriahu
Dec 12, 2007 at 6:55 pm

W perlu to nie jest magia, tych parę użytecznych zmiennych można łatwo zapamiętać :) A w pythonie nie trzeba nowej linii :P


 
Wiktor
Dec 12, 2007 at 6:57 pm

Dobry komentarz napisał także Adrian Olek, że w Ruby‘im wystarcza po prostu:
[ruby]
puts [1, 2, 3, 4]
[/ruby]

Przy założeniu, że wypisujemy na standardowe wyjście, gdybyśmy chcieli wypisywać gdzieś do logów to wygodniejsze byłoby zastosowanie bloku.

Podejście w Javie, Ruby’im (tym w komentarzu), Pythonie, Perlu jest czysto imperatywne, natomiast w Ruby’im (tym w poście) oraz w Scali jest bardziej funkcyjne.

Kwestia gustu, a o gustach się nie dyskutuje :) .


 
Wiktor
Dec 12, 2007 at 7:00 pm

@adriahu

Perl. Każdy język ma parę takich “tajemnic” :) .

Python. Jasne, że nie trzeba, ale wtedy w Javie bym zapisał to tak:
[java]
for(Integer x : lista) System.out.println(x);
[/java]
;)


 
adriahu
Dec 12, 2007 at 7:38 pm

Faktycznie o gustach nie powinno się dyskutować, ale gdy myślę o podejściu funkcyjnym (funkcjonalnym) :D od razu przypomina mi się świetny dialekt lispa o nazwie scheme. Czy to nie w tym języku “scałkowano pierwszy raz ruch układu słonecznego”? :P


 

[...] Poznajemy nowe języki programowania: Scala, czyli jak wypisać elementy z listyblog.mocna-kawa.com/2007/12/12/poznajemy-nowe-jezyki-scala-c… dodane przez wwiktorr od paru sekund [...]


 
adriahu
Dec 12, 2007 at 8:54 pm

Już jest 20:33 :P hmmm


 
Koziołek
Dec 12, 2007 at 9:16 pm

Rzeczywiście ładne. A teraz prosimy o jakieś bardziej praktyczne zastosowanie. Wypisać listę (10 elementów) można i w whitespace:
http://compsoc.dur.ac.uk/whitespace/count.ws
(jak nie widać nacisnąć ctrl+a)
Na razie widzę ładne rozwiązanie problemów osób, które nie lubią perla/basha i potrzebują śmigać w konsoli, a na pisanie w “zwykłej” javie nie mają czasu. Dobra alternatywa dla Rubiego. Co jeszcze? Silna kontrola typów, plus, statyczne typowanie minus, ale mały.


 
Wiktor
Dec 12, 2007 at 10:42 pm

@Koziołek

Whitespace jest świetny :) . Dodajmy jeszcze brainfucka i będziemy w siódmym niebie :D


 
lopex
Dec 13, 2007 at 3:18 am

Największe możliwości fajnego zapisu w scali dają call by name i implicits, dzięki nim można bez problemu pisać potem:

1.foo

czy

myif (cond) { foo } myelse { bar }


 
Pitorek
Dec 14, 2007 at 11:49 am

A ja tam wolę Coca Colę – parafrazując “wielkiego poĘtę” :-) tzn. nie chciałbym kiedyś przeglądać kodu o tak srkóconej postaci, bo – jeśli się dobrze nie znasz – to ciężko coś takiego przeczytać, do czego się odnosi i wogóle… Kurczę, a może jestem zbyt konserwatywny? ;)

Pozdrawiam


 
jau
Dec 14, 2007 at 6:50 pm

pitorek: to daj poczytac kod javy osobie “swieckiej” ;) . Wiadomo, ze zeby czytac kod trzeba znac (chocby troche) jezyk programowania.

Z innej beczki:
Siedze w jezykach kilka lat, ruby, python, java, c# itd. Niedawno tez odkrylem scale i jak na razie wglebiam sie .. cos czuje, ze znalazlem swoj nowy ulubiony jezyk :) .


 
Wiktor
Dec 14, 2007 at 7:19 pm

@jau

Nieprawdaż? Jak ja się wgłębiam w Scalę to mam takie miłe uczucie, że to jest to :) . Tak samo, jak było z Javą (myślałem: ale ona fajne ;) ).


 
jau
Dec 14, 2007 at 9:35 pm

JAVA: for (int x : Arrays.asList(1, 2, 4) System.out.println(x);


 
jau
Dec 14, 2007 at 10:04 pm

poza tym scala pozwala stworzyc nowy typ danych – stos, gdzie dodawanie elementow bedzie wygladac tak

lista :-) element

a usuwanie

lista :-P element

Pokazcie mi drugi jezyk, ktory tak potrafi :-D


 
Roman
Dec 14, 2007 at 11:09 pm

Z tego co rozumiem (i co chyba jest napisane na Wikipedii) to currying nie polega na ominięciu typu w deklaracji, tylko stworzeniu nowej funkcji, ktora przyjmuje mniej argumentow…


 
MySZ
Dec 14, 2007 at 11:59 pm

Perl:
print join (“\n”, @lista);

lub używając ‘zmiennej magicznej’:
$, = “\n”;
print @lista;

Python:
print “\n”.join (lista)


 
Mardok
Dec 27, 2007 at 9:39 am

A mi sie marzy LISP z dobrymi bibliotekami, a tak jestem zdany na rubiego. Ech co by nie mowic o javie to biblioteki ma swietne.


 
Tomek
Jan 27, 2008 at 1:21 pm

Scala ma bardzo fajną własność, którą nigdzie wcześniej nie spotkałem. Mianowicie w Scali technicznie nie ma operatorów. Wyrażenie 1 + 2 jest tożsame z wywołaniem metody 1.+(2)

Podstawa to podstawy. O ile pamiętam w takim języku jak Smalltalk operatory były tak naprawdę metodami, więc nie jest to nic nowego.

Kolejne języki nie wprowadzają tak naprawdę nic nowego poza kompilacjami istniejących już i stosowanych paradygmatów programowania w różnych proporcjach.

Warto byłoby się zastanowić raczej nad pytaniem “Dlaczego scala może ułatwić tworzenie oprogramowania ? Dlaczego miałaby się dobrze przyjąć?” Moim zdaniem heterogeniczne środowiska (powiedzmy Java + Scala) znakomicie podnoszą kłopotliwość tworzenia (złożonych) systemów informatycznych, zwłaszcza w kontekście zespołowej pracy i późniejszego utrzymania.


 
Wiktor
Jan 27, 2008 at 1:51 pm

@Tomek

Smalltalk to było dopiero szaleństwo. Metody np:

labirynt go: there :with light :and

Piękne :) .

Muszę się zgodzić, że nieheterogeniczne środowiska są trudniejsze w utrzymaniu. Jest także to kwestia ludzi, którzy żeby poznać działanie aplikacji muszą znać kilka języków.

Mnie bardzo podoba się idea (nie weryfikowana jeszcze w praktyce) polyglot programming, gdzie używa się odpowiednich języków/technologii do pracy, np. Ruby on Rails do frontendu, Java jako backend. Czas wszystko zweryfikuje. Ja wierzę w tą ideę.


 
Tomek
Jan 27, 2008 at 8:52 pm

Ja w tę ideę wierzyłem (i nadal trochę wierzę).

Ideę zweryfikowałem na 2 sporych projektach ( 4 m-ce x 4 os), miksując JEE + Adobe Flex 2. Generalnie ujdzie, ale:

w krótkim czasie programista nie jest w stanie być dobry w wiecej niż 1 technologii, mam na myśli bycie rzeczywiście świadomym języka, jego charakterystyki, dobryk praktyk etc.
konieczność przełączania się z języka do języka wybija z rytmu pracy
mimo prób rozdzielenia warstw oprogramowania niestety niektóre rzeczy musisz powielać
integracja bywa trudna, czasochłonna i nie działa zbyt wydajnie
proces budowania lub CI jest zdecydowanie trudniejszy


 
br
Feb 5, 2008 at 2:29 am

To chyba nie jest currying. Tylko po prostu funkcja println jest takiego typu jakiego jest parametr for’a.

Currying to taki bajer że napisa f x y => x + y montuje funkcję typu int => (int => int). Zamiast int*int => int jak w pascalu, po bożemu.


 
Wiktor
Feb 5, 2008 at 10:12 am

@br

Tak, z rozpędu napisałem, że to currying… co nie zmienia postaci rzeczy, ze currying w Scali występuje ;) .

Wyjaśnię przykład br do końca:
f x y => x + y (funkcja bierze 2 argumenty i zwraca ich sume)

succ = f 1 (ukonkretnienie pierwszego argumentu, typ succ to (int => int)

write succ 4 (wypisze 5)


 
jau
Jul 3, 2008 at 8:49 pm

@Mardok
http://clojure.org/


 
crackcomm
Mar 2, 2010 at 1:46 pm

[php]
print_r($lista);
[/php]


 

Reply

Copyright © 2012 Mocna Kawa All rights reserved. Theme by Laptop Geek.