Ruby po kapkách (2.) – čísla, řetězce, pravda a nic

4. února 2009

V závěru předchozího článku jsme docílili spuštění irb – aplikace umožňující interaktivní práci s interpretem jazyka Ruby. V tomto pokračování budeme irb intenzivně využívat. Všechny dále uvedené ukázky kódu jsou přímo kopírované z irb.

Již jsme uváděli, že Ruby se inspirovalo různými paradigmaty softwarového vývoje. Nejvíce je však návrh jazyka ovlivněn objektově orientovaným programováním (OOP). Téměř vše v Ruby je proto objekt. Každý objekt je instancí určité třídy objektů. Přímo v jádru interpretu jsou implementovány třídy umožňující pohodlnou práci s nejčastěji se vyskytujícími podobami dat a datových struktur. Ukážeme si nyní na příkladech, které to jsou a jak je zapisovat v kódu programu.

Objektově orientované programování (OOP) využívá faktu, že v okolním světě přirozeně identifikujeme objekty a vztahy mezi nimi. Pod pojmem objekty rozumíme konkrétními výskyty určité obecné entity. Obecná entita (v terminologii OOP třída) „Pes“ může například zahrnovat objekty „Alík“ a „Brok“. V programu reprezentujeme objekt jako kombinaci stavu objektu (který je dán aktuálními vlastnostmi objektu) a sady funkcí (v terminologii OOP metod) umožňujících stav objektu měnit.

Zmínili jsme možnost využívání irb jako kalkulačky. Ruby zahrnuje podporu celých i reálných čísel. Celá čísla jsou reprezentována jako objekt třídy Fixnum. Větší celá čísla jsou ukládána jako objekt třídy Bignum. Bignum umožňuje pracovat s celými čísly, jejichž velikost je omezena jen velikostí paměti počítače. O použití konkrétní třídy se v tomto případě nemusíme starat. V případě potřeby ji zjistíme voláním metody class.

irb(main):001:0> 123.class
=> Fixnum
irb(main):002:0> 123 ** 7
=> 425927596977747
irb(main):003:0> (123 ** 7).class
=> Bignum

Operátor ** znamená umocňování. Další použitelné aritmetické operátory jsou následující:

  • + sčítání
  • – odčítání
  • * násobení
  • / dělení
  • % zbytek po dělení
  • & bitová operace AND
  • | bitová operace OR
  • ^ bitová operace XOR
  • << bitový posun doleva
  • >> bitový posun doprava

Zajímavé je, že díky důrazu na OOP je většina operátorů standardními metodami dané třídy a je možné je v případě potřeby předefinovat. Metodu objektu voláme nejčastěji pomocí tečkové konvence: objekt.metoda. Celá čísla je také možné zapisovat jako binární, oktalová nebo hexadecimální. To můžeme v irb využít k rychlé konverzi do dekadické soustavy.

irb(main):004:0> 0b1000000001
=> 513
irb(main):005:0> 01001
=> 513
irb(main):006:0> 0x201
=> 513

Reálná čísla jsou reprezentována jako objekty třídy Float a jsou uložena ve dvojnásobné přesnosti. V případě zápisu, ze kterého není zřejmé, že se jedná o reálné číslo, považuje interpret číslo za celé. Nicméně stačí ve výrazu použít jedno reálné číslo, aby celý výpočet probíhal v reálných číslech. Explicitně označíme číslo jako reálné, když v jeho zápisu použijeme desetinnou tečku.

irb(main):009:0> 5 / 3
=> 1
irb(main):010:0> 5.0 / 3
=> 1.66666666666667
irb(main):011:0> 1 / 0
ZeroDivisionError: divided by 0
   from (irb):11:in `/‘
   from (irb):11
irb(main):012:0> 1.0 / 0
=> Infinity

V příkladu vidíme, že zatímco při počítání s celými čísly došlo při dělení nulou k chybě, při počítání s reálnými čísly získáme stejnou operací hodnotu nekonečno. Zmiňme ještě krátce, že ve standardní knihovně poskytuje Ruby podporu pro racionální čísla (vyjádřená zlomkem) a komplexní čísla.

irb(main):001:0> require ‚rational‘
=> true
irb(main):002:0> Rational(5, 3) * 2
=> Rational(10, 3)
irb(main):003:0> Rational(10, 6)
=> Rational(5, 3)
irb(main):004:0> require ‚complex‘
=> true
irb(main):005:0> 1.im
=> Complex(0, 1)
irb(main):006:0> 1.im ** 2
=> Complex(-1, 0)
irb(main):007:0> 5 + 3.im
=> Complex(5, 3)

Jak je vidět racionální nebo komplexní číslo vytvoříme pomocí názvu příslušné třídy a složek čísla uvedených v závorkách. Pro práci s racionálními a komplexními čísly je třeba příslušnou knihovnu příslušnou knihovnu načíst pomocí volání require. Tím říkáme také pro celá i reálná čísla metodu im, která vrací komplexní číslo s odpovídající imaginární složkou. Výraz zahrnující komplexní čísla je vyhodnocen jako komplexní číslo.

Snad ještě častěji než s čísly pracují programy s řetězci. Ty jsou v Ruby reprezentovány mocnou a flexibilní třídou String. Do verze interpretu 1.8.x je řetězec ukládán jako posloupnost bajtů. V jen několik dní staré verzi 1.9.1 je v tomto ohledu zapracována velká změna, která umožňuje podporovat větší množství jazyků. Řetězce jsou ukládány jako sekvence znaků v určitém kódování, kdy znak může vyžadovat pro svou reprezentaci jeden nebo více bajtů. Na dopady této změny budeme v dalším textu upozorňovat podle potřeby.

V programu jsou jako řetězce chápány znaky uzavřené mezi uvozovkami nebo apostrofy. Tyto dvě varianty se liší mírou zpracování, kterou interpret při načítání řetězce provádí. Řetězec obklopený apostrofy je zpracován minimálně: dvě zpětná lomítka za sebou jsou vyhodnocena jako jedno zpětné lomítko a zpětné lomítko následované apostrofem je vyhodnoceno jako apostrof. V řetězci obklopeném uvozovkami se navíc interpretují další sekvence se zpětným lomítkem jako speciání znaky. V neposlední řadě jsou vyhodnoceny výrazy ve tvaru #{...}.

irb(main):001:0> ‚jedna a jedna je #{1 + 1}‘
=> „jedna a jedna je \#{1 + 1}“
irb(main):002:0> „jedna a jedna je #{1 + 1}“
=> „jedna a jedna je 2“

Nejdůležitější sekvence pro speciální znaky jsou:

  • \n nový řádek
  • \r návrat vozíku – návrat kurzoru na začátek řádky
  • \t tabelátor

Ruby nabízí pohodlnou cestu k inicializaci dlouhých, několikařádkových řetězců.

irb(main):001:0> <<KONEC
irb(main):002:0″ a b
irb(main):003:0″ c d
irb(main):004:0″ e f
irb(main):005:0″ KONEC
=> „a b\n c d\ne f\n“

Takto zapsaný řetězec může mít několik řádků a končí až slovem, které je uvedeno za znaky ‚<<‚. Počítá se do něj i případné odsazení řádků. Víceřádkový řetězec je vyhodnocován stejně jako řetězec mezi uvozovkami, pokud není ukončovací slovo za znaky ‚<<‚ obklopeno apostrofy, kdy je i řetězec brán jakoby byl mezi apostrofy.

Pro práci s řetězci můžeme využívat některé operátory a velké množství metod třídy String.

irb(main):001:0> ‚ahoj‘ + ‚!‘
=> „ahoj!“
irb(main):002:0> ‚ahoj ‚ * 2
=> „ahoj ahoj „
irb(main):003:0> ‚ahoj‘.upcase
=> „AHOJ“
irb(main):004:0> ‚AHOJ‘.downcase
=> „ahoj“
irb(main):005:0> ‚ahoj‘.size
=> 4
irb(main):006:0> ‚ahoj‘.length
=> 4
irb(main):007:0> ‚ahoj‘.include?(‚ho‘)
=> true
irb(main):008:0> ‚ahoj‘.include?(‚oh‘)
=> false
irb(main):009:0> ‚ahoj‘.index(‚ho‘)
=> 1
irb(main):010:0> ‚ahoj‘.reverse
=> „joha“
irb(main):011:0> ‚ahoj‘.capitalize
=> „Ahoj“
irb(main):012:0> ‚ahoj‘.center(20)
=> “ ahoj „
irb(main):013:0> ‚ ahoj ‚.strip
=> „ahoj“

Význam volaných metod by měl být s pomocí uvedených příkladů a minimální znalosti angličtiny jasný. Pro podrobnější popis doporučuji oficiální dokumentaci třídy String na odkazu uváděném na konci předchozího článku. Pro úplnost uveďme, že význam těchto metod zůstává stejný i v nejnovějších verzích interpretu s podporou vícebajtových kódování. Všechny tyto metody pracují se znaky. Ve verzi interpretu 1.9 a vyšší je pak k dispozici metoda bytesize, která určuje velikost řetězce v bajtech.

K jednotlivým znakům řetězce se můžeme dostat pomocí indexovacího operátoru v podobě hranatých závorek.

irb(main):001:0> ‚ahoj lidi'[1] => 104
irb(main):002:0> ‚ahoj lidi'[1, 1] => „h“
irb(main):003:0> ‚ahoj lidi'[1..5] => „hoj l“
irb(main):004:0> ‚ahoj lidi'[3..-1] => „j lidi“
irb(main):005:0> ‚ahoj lidi'[-3..-1] => „idi“

Zde dochází ke změně mezi verzemi v prvním případě, který vrací znak s indexem 1 (indexování je od 0). Uvedený příklad je z interpretu verze 1.8.6 a navrácená hodnota je kód 8bitového znaku. Ve verzi 1.9 a vyšší je návratová hodnota tohoto výrazu jednoznakový řetězec – „h“. Toho samého docílíme druhým voláním, kde požadujeme řetězec začínající na znaku 1 o délce 1. Další příklady pracují s rozsahy indexů znaků, které chceme vrátit. Indexování zápornými čísly se počítá od konce řetězce, přičemž -1 je poslední znak.

Na závěr se ještě podívejme na tři speciální hodnoty, kterými je v Ruby reprezentována hodnota pro pravdu pro nepravdu a absence hodnoty. Jsou to:

  • true pro pravdu (jediná instance třídy TrueClass)
  • false pro nepravdu (jediná instance třídy FalseClass)
  • nil pro absenci hodnoty – doslova nic (jediná instance třídy NilClass)

Hodnota nil je kromě hodnoty false jediná, která se v logických výrazech vyhodnocuje jako nepravda. Všechno ostatní je vyhodnoceno jako pravda. Ve výše uvedených příkladech jsme mohli tyto hodnoty vidět jako návratové hodnoty některých metod.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Další článek cdh.cz
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *