Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Scala — pierwsze kroki cz.2

Poniższy wpis jest kontynuacją części pierwszej kursu.

Krok trzeci - definiowanie funkcji

Do definiowania funkcji lub metody służy słowo kluczowe def.
Napiszemy funkcję max zwracającą większą wartość z dwóch wartości przekazanych jako parametry:def max(x:Int, y:Int):Int = { if(x > y) x else y } max jest nazwą funkcji przyjmującej dwa parametry typu całkowitego - Int i zwracającą również typ Int. Jak widać pominięto znane z innych języków słowo kluczowe return. Jest ono opcjonalne w tym przypadku i moglibyśmy je dopisać przed x i y. Zwracana jest zawsze ostatnia wartość z miejsca do którego doszła funkcja.

Nie potrzeba też średników po każdej instrukcji. Kompilator sam znajduje gdzie się ona kończy. Charakterystyczne też jest odwrócenie kolejności nazwy argumentu z jego typem, jak również pojawienie się zwracanego typu po liście parametrów funkcji. (Może niektórzy już zorientowali się, że przypomina to sposób zapisu z języka UML.). Nawiasy klamrowe tak jak w większości języków pochodzących od C definiują nam zasięg. W tym przypadku ciało funkcji. Znak równości w pierwszej linii mówi, że funkcja zwraca wartość. Jest ona obowiązkowa dla funkcji. Jeśli jej nie napiszemy to oznacza to procedurę i brak zwracania wartości (oznacza to zwracanie Unit - coś podobnego do void w C).

Funkcję możemy wywołać np. w taki sposób: max(3, 5)Na co interpreter odpowie w znany nam już sposób:res0: Int = 5 Dla małych funkcji i metod możemy skrócić zapis do jednej linijki. Nasza funkcja max może być zapisana w następujący sposób: def max(x:Int, y:Int) = if(x > y) x else yPodobnie jak przy definicji z inicjalizacją zmiennych funkcja potrafi sama odgadnąć zwracany typ.
Gdy napiszemy procedurę kompilator przypisze jej zwracany typ jako Unit:def powitanie() = println("Witaj świecie!") powitanie: ()Unit

Krok czwarty - piszemy skrypty

Mimo, że Scala powstała do pisania dużych programów i systemów to umożliwiono pisanie w niej skryptów. Stwórzmy plik o nazwie hello.scala i napiszmy w nim następującą treść:println("Witaj świecie z wnętrza skryptu!")Skrypt uruchamiamy poleceniem:scala hello.scalaUruchomienie skryptu trwa kilka sekund ze względu na czas kompilacji. Skrypty w Scali wydają się być miłym dodatkiem i mogą okazać się czasami użyteczne. Jednak nie zastąpią wielu przypadkach ani skryptów Pythona, ani też nie zastąpią większych programów pisanych w Scali. Pobieranie parametrów z konsoli po uruchomieniu skryptu odbywa się za pomocą listy argumentów args z numerem argumentu wpisanym w okrągłe nawiasy. Aby to sprawdzić podmieniamy zawartość skryptu na: println("Witaj " + args(0) + "!")Przy okazji widzimy, że napisy skleja się podobnie do C i Java.
Teraz uruchamiamy poleceniem: scala hello.scala JanieJeśli zapomnimy wpisać argumentu to pojawi się błąd i rzucony zostanie wyjątek, ponieważ próbujemy dostać się do pustej listy argumentów. Zamieńmy kod na poniższy:if(!args.isEmpty) println("Witaj " + args(0) + "!") else println("Witaj Anonimie!")Dzięki sprawdzeniu czy lista nie jest pusta unikamy problemów.

W systemach Uniksowych możemy uruchamiać skrypty podając tylko ich nazwę, ale dopisując w pierwszej linii za pomocą czego ma on być uruchomiony. W Ubuntu po instalacji Scali z pakietów będzie to:#!/usr/bin/scala !#Po nadaniu praw do uruchomienia plikowi możemy uruchomić skrypt poleceniem:./hello.scala

Krok piąty - pętla while i zwrotnica if

Wygląd pętli while jest dość standardowy. Napiszmy funkcję liczącą silnie z wykorzystaniem pętli while:def silnia(n:Int) = { var i = 1 var s = 1 while( i < n) { i += 1 s *= i } s } silnia(5)Nie jest to kod pokazujący typowy styl programowania w Scali ponieważ, nie unikamy tutaj iterowania po indeksie i co jest zbędne. W kodzie znajdziemy też znane z języka C i Javy skróty operacji: i += 1 to i = i + 1 oraz s *= i to s = s * i.

Umieśćmy teraz w pliku drukujargumenty.scala następujący kod: var i = 0 while (i < args.length) { if(i != 0) print(" ") print(args(i)) i += 1 } println()i uruchamiamy poleceniem: scala drukujargumenty.scala Scala jest fajnaInstrukcja if sprawdza warunek logiczny i podobnie jak w Javie nie przepuści innej operacji nie zwracającej prawdy lub fałszu. Instrukcje w bloku if muszą być ograniczone nawiasami klamrowymi gdy jest ich więcej.
Funkcja print drukuje napis na konsolę bez dodawania znaku nowej linii, a metoda length listy args sprawdza ilość elementów w liście (w tym przypadku ilość argumentów w konsoli).
Jeśli chcemy napisać kilka poleceń w jednej linii to możemy oddzielić je średnikami.

Krok szósty - pętla for i foreach

Realizacja funkcji silni za pomocą pętli for: def silnia(n:Int) = { var s = 1 for(i <- 1 to n) { s *= i } s } silnia(5)Jak widać nie jest to typowa dla języków C i Javy funkcja for. Bardziej podobna jest do pętli z Pythona. Generuje liczby od 1 do n ( 1 to n) i podstawia pod zmienną i.
Drukowanie argumentów z konsoli w pliku drukujargumenty.scala można skrócić do: for(arg <- args) print(arg + " ") println()

Foreach jest metodą którą posiadają kolekcje (sekwencje, listy, tablice itp.). Umożliwia ona pisanie kodu w zwarty sposób. Naszą funkcję silnia możemy napisać dzięki temu krócej:def silnia(n:Int) = { var s = 1 (1 to n).foreach(i => s *= i) s } silnia(5)We wnętrzu metody foreach użyta została funkcja anonimowa. Jest to skrócona forma, która mogłaby wyglądać tak:(i:Int) => {s *= i}
Do pełnej funkcji brakuje słowa kluczowego def, nazwy funkcji i zamiast znaku równości mamy =>.

W pliku drukujargumenty.scala możemy podmienić kod na:

args.foreach(arg => print(arg + " ")) println() Minusem jest fakt, że na końcu zostanie spacja. Można to rozwiązać jeszcze prościej używając metody mkString:print(args.mkString(" "))

Użycie metody foreach pokazuje styl programowania funkcyjnego.

Do zobaczenia w następnym odcinku ;)

 

programowanie

Komentarze

0 nowych
iluzion   5 #1 10.08.2014 20:54

Pierwszy fragment kodu łamie co najmniej dwie konwencje dobrego stylu http://docs.scala-lang.org/style/ --zasadę dotyczącą wcięć oraz stosowania nawiasów klamrowych ;)

  #2 10.08.2014 23:02

Mój borze! Jak tak można! Aż mnie skręca, gdy to widzę. Pętle? Po co pętle, gdy mamy taki fajny, funkcyjny język! Jeżeli ktoś nie umie programować i chce się nauczyć, to najgorzą krzywdą, jaką możemy mu wyrządzić, jest rozpoczęcie nauki od tak mechanicznych pojęć jak pętle. Byłbym w stanie to zrozumieć, gdyby to był kurs C albo Javy, ale na litość boską, jak bierzecie na warsztat Scalę, to pokazujcie na czym polega programowanie funkcyjne, trwałe struktury danych, typy wariantowe... A nie taki wstrętny imperatyw!

Frankfurterium   10 #3 10.08.2014 23:15

Scala nie łapie się pod definicję języka czysto funkcyjnego, więc dlaczego miano by ją tak właśnie traktować? No i co ci ten bór zrobił, że tak go wzywasz?

Savpether   6 #4 10.08.2014 23:27

Fajny artykuł, zachęcił mnie do wypróbowania Scali :)

  #5 10.08.2014 23:45

@Frankfurterium
Mam na myśli zmarnowaną szansę na pokazanie oblicza programowania innego niż to najpopularniejsze.

mikolaj_s   14 #6 11.08.2014 12:01

@karpik2 (niezalogowany): "Mam na myśli zmarnowaną szansę na pokazanie oblicza programowania innego niż to najpopularniejsze."

Spokojnie jeszcze do tego dojdziemy ;) Kurs się nie kończy, lecz dopiero zaczyna.

"Po co pętle, gdy mamy taki fajny, funkcyjny język! "

Jak bardzo słusznie napisał @Frankfurterium Scala jest raczej językiem hybrydowym. Nie jest czysto funkcyjna. Wynika to po części z faktu, że w założeniach miała umożliwić łatwe przejście z języków imperatywnych, w szczególności z Javy na język funkcyjny. Na początku możesz używać intensywnie pętli, a z czasem przechodzić coraz bardziej na styl funkcyjny, który jest zalecany, ale nie obowiązkowy. Bywają też miejsca w kodzie, gdzie chcąc uzyskać nieco większą wydajność musisz wykorzystać pętle.

Gdybyś przeczytał do końca wpis to zobaczyłbyś foreach, które nie jest pętlą tylko pokazuje nieco styl pisania funkcyjnego (chociaż prawdziwy styl funkcyjny polega bardziej na przetwarzaniu niemutowalnych obiektów, niż na takim czy innym zapisie).
Kurs jest kompilacją kursu jaki napisał twórca Scali Martin Odersky, więc pretensje miej do niego ;)

  #7 11.08.2014 14:23

Nie rozumiem takiego ciągłego krytykanctwa. Jesli cos nie spełnia twoich oczekiwań, chcialbyś zrobić coś lepiej lub poprostu inaczej to zrób to, dołacz do kogoś, kto już robi, dodaj swoje co nieco i wspolnymi silami moze wyjść cos naprawde dobrego. Jesli nie umiesz wspolpracować, to zrob wstawke że ty bys to zrobil tak a tak. W ten sposob wszyscy odnoszą korzyści, także ty bo mozesz byc dumny z swojej roboty. Z tego ze ciągle masz protensje nikt nie odnosi korzyści. Temu co wlozyl wklad jest przykro, innym co czytaja tez nie do smaku, a i sam siedzie wewnetrznie niszczysz poddajac sie tego typu negatywnym uczuciom.

cyryllo   17 #8 11.08.2014 16:15

Mi się kurs podoba :) Jest jasno i i dobrze wytłumaczone ;) Podchodziłem do scali już raz z pomocą książki ale nic z tego nie wyszło :P
Teraz widzę szanse na nauczenie się i zrozumienia programowania obiektowego i funkcyjnego ;) Oczywiście czekam na kolejną część ;)

  #9 09.09.2014 19:18

Jakbym widział kurs Pascala. Daj jeszcze operacje na wskaźnikach. :D