Any fool can make things bigger, more complex, and more violent. It takes a touch of genius and a lot of courage to move in the opposite direction. Albert Einstein

o Ruby

Nowości i zmiany w Ruby 1.9 #2 - nowa składnia Hasha

5 komentarzy | Kategorie: Ruby, Techblog | trackback
Tagi:
ruby 1.9 changes approved - logo

Wpis ten jest jedną z części cyklu pt "Nowości i zmiany w Ruby 1.9". Pełną listę wpisów znajdziesz pod adresem http://radarek.jogger.pl/2008/11/30/nowosci-i-zmiany-w-ruby-1-9/.

Tym razem chciałbym pokazać Wam nową zmianę w składni języka, która dotyczy także Hasha. Zmiana ta dotyczy nowej składni dla literału hasha, którego kluczami są symbole. Do tej pory taki hash definiowaliśmy w następujący sposób:

h = {:foo => 1, :bar => 2}
p h
# => {:foo=>1, :bar=>2}

Od wersji 1.9 można to zrobić trochę inaczej

h = {foo: 1, bar: 2}
p h
# => {:foo=>1, :bar=>2}

Jeszcze raz podkreślam, że nową składnię można zastosować tylko jeśli kluczami są symbole. Dla innych kluczy musisz użyć dotychczasowej składni. Wykonując mały eksperyment możesz przekonać się, że można równocześnie stosować nowy i stary sposób...

h = {foo: 1, bar: 2, "baz" => 3}
p h
# => {:foo=>1, :bar=>2, "baz" => 3}

...jednak z oczywistych powodów odradzam takie praktyki.

Przekazując hash jako jedyny lub ostatni parametr metody można ominąć nawiasy {}. Dzięki temu zyskujemy na czytelności bo zamiast

User.find(:all, {:order => "login", :limit => 5})

możemy napisać

User.find(:all, :order => "login", :limit => 5)

a stosując nową składnie

User.find(:all, order: "login", limit: 5)

Prawda, że przejrzyście to wygląda? A dwukropek dużo łatwiej się stawia niż znak "spacja, znak równości, znak większości".

Parametry nazwane - czy to już to?

Niektóre języki (np. Python) posiadają obsługę tzw. nazwanych parametrów. Dzięki temu wywołując możemy takie parametry podać w dowolnej kolejności. Od strony wywołania wygląda to podobnie jak ostatni przykład. Wbudowana obsługa takich parametrów pozwala na weryfikację przekazanych parametrów przez sam język. Dzięki nowej składni hashy możemy w pewien sposób symulować takie parametry, ale musimy wykonać dodatkową pracę by zweryfikować przekazane klucze.

Na pełną obsługę parametrów nazwanych musimy niestety poczekać przynajmniej do wersji 2.0.

Jeśli spodobał Ci się wpis to może umieścisz ten blog w swoim czytniku RSS?

Komentarze

1. avatar icon MacBury napisał(a) 02 Gru 2008 o godz. 20:55:

Mała zmiana a cieszy oko :)

2. avatar icon Psi napisał(a) 02 Gru 2008 o godz. 21:47:

User.find(:all, order: „login”, limit: 5)

Fajnee, podoba mi się :) tylko trochę szkoda że w środku funkcji dalej trzeba tego hasha options ręcznie wyciągać, a nie jak w Pythonie…

3. avatar icon hm napisał(a) 06 Gru 2008 o godz. 13:45:

Ostatnio przeglądałem zmiany wprowadzone w Pythonie 3.0. Wszystko zostało przedyskutowane i przemyślane. Język stał się jeszcze bardziej spójny. Super!

Jak wygląda to w Ruby? Weźmy nowego Hasha. Można po staremu i nowemu. Czym się różni stare od nowego? Tym że dwukropek damy po, a „strzałkę” opuścimy. Niezwykle przydatna zmiana. Ale hola, hola! Należy pamiętać dodatkowo że nową składnie można stosować tylko dla kluczy będących symbolami. Żeby było jeszcze ciekawiej oba sposoby można mieszać!

N sposobów na pętlę while, M na pętlę for. Różne nazwy na metody dające taki sam wynik. Różne sposoby na wykonanie jednej czynności. Zaczyna się robić niezły śmietnik. Nie ułatwia to w żaden sposób czytania kodu. Skąd mam pewność że metoda size i length zwracają to samo. Może pierwsza zlicza elementy nilowe a druga nie? Nie mam wyjścia muszę zobaczyć do dokumentacji! Okazuje się że obie metody służą dokładnie do tego samego. Do zliczania elementów nienilowych służy metoda o jakże intuicyjnej nazwie nitems.

Jestem zdania że język Ruby nie jest przygotowany na sukces jaki odniósł. Czekam na wydanie 2.0. Całą sytuację ratuje community, dostępne narzędzia i wiele ciekawych projektów :) Sam język jest ciekawy pod względem teoretycznym ale do The Zen of Python się nie umywa IMHO.

4. avatar icon Psi napisał(a) 06 Gru 2008 o godz. 13:52:

Z „Zen of Python” nie podoba mi się jedna rzecz: explicit is better than implicit… Bo według mnie explicit „self” nie jest better than implicit :) Najbardziej explicit to jest Java, ale wydawało mi się że właśnie od tego uciekaliśmy…

5. avatar icon Radarek napisał(a) 07 Gru 2008 o godz. 12:35:

hm, nie da się ukryć, że nie wszystkie zmiany są dobre, a część z nich sprawia wrażenie jakby nieprzemyślanych. Niestety nigdy tak nie będzie, że wszyscy będą zadowoleni. Przykładowo o nowej składni dla Hashy większość komentarzy jest pozytywnych. Oczywiście, można się zastanowić czy ta zmiana była warta, ale jednoznacznej odpowiedzi nie uzyskamy. Pewne jest to, że twórcy języka nie przeszkadza „powielanie” rzeczy. Cóż, osobiście mogę z tym żyć :).
Python sprawia wrażenie lepiej prowadzonego języka, ale też nie jest bez wad. To o czym wspomniał choćby Psi też mnie irytuje.

Wracając jednak do Rubiego. Jakby popatrzeć na suche fakty, to można nawet pomyśleć, że język gorszy niż php ;-). Mogę zmienić praktycznie wszystko (nadpisać istniejące metody w każdej klasie), dodać metodę tylko do konkretnego obiektu (przez co tylko jeden konkretny obiekt będzie zachowywać się inaczej), mogę robić aliasy do tej samej metody (przy czym nadpisanie metody powoduje zasłonięcie tylko jednej z nich), usuwać wybrane metody (undef_method :foo), nadpisywać, usuwać stałe (Object.send(:remove_const, „Array”)). Można tak długo wymieniać.

Kiedyś na prezentacji Rubiego (SFI 2008) Chad Fowler powiedział „Sometimes it’s ok to be weird” (http://www.flickr.com/photos/leobard/2333834948/in/set-72157604067113071/) i podpisuję się dwoma rękoma. Piękno Rubiego polega na tym, że odpowiednio wyciągając i układając te różne dziwactwa tworzymy piękne rzeczy. Przykład?

Nawiasy Rubiego. Można je opuszczać, ale nie trzeba. Zatem puts(„Hello”) jest równoważne puts „Hello”. Wkurzające, prawda? Szkopuł tkwi w szczegółach. Chodzi o to by konsekwentnie, w zależności od sytuacji użyć takiej a nie innej formy. Railsy nam pokazały piękny przykład:

class User < ActiveRecord::Base
  has_many :friends
  # a może tak?
  has_many(:books)
  # albo bardziej "explicite" (python!)
  self.has_many(:pages")
end

Myślę, że nie trzeba tłumaczyć, która forma jest preferowana, a wręcz „jedyna słuszna”.

Piękno Rubiego polega na tym, że język nie narzuca takich rzeczy. To już robi społeczność kreując pewien styl Rubiego.

Dodaj coś od siebie

Możesz korzystać ze składni Textile.

Pola oznaczone * są wymagane.

Proszę o dodawanie komentarzy związanych z tematem postu, sprawy osobiste proszę załatwiać przez maila bądź gg.

Zastrzegam sobie prawo do moderacji komentarzy (edycja, usuwanie).