Squak Smalltalk [6 * 9 = 42] whileTrue: [World run]
Stopařův průvodce jedním převážně neškodným programovacím jazykem
smalltalk
Swiki
  • Domů
  • Zpět
  • Tento server

    Squeak
  • Úvod
  • Smalltalk
  • Články
  • Knihy
  • Dokumentace
  • FAQ
  • Tutoriály
  • Download
  • Odkazy

    Komunita
  • CSSUG
  • Oznámení
  • Projekty
  • O nás
  • Fórum
  • Kontakt

     

  • Kolekce

    Ve Smalltalku jsou datové struktury implementovány pomocí kolekcí, což jsou v podstatě klasické seznamy s různými vlastnostmi, aby se daly využít jako fronty, pole, množiny, zásobníky apod.

    Styl práce s kolekcemi se liší od tradičního způsobu např. C++, kde jsme odkázání pouze na indexování či operace specifické pro daný typ abstraktního datového typu (principielně trochu blíže práci s kolekcemi jsou iterátory v knihovně STL).

    Smalltalk se snaží, aby se programátor musel co nejméně zabývat indexováním a mohl se soustředit na provádění samotného algoritmu nad jednotlivými prvky.
    To si může dovolit díky tomu, že jako parametr se dá předávat blok kódu (toho se využívá i u mnoha dalších programových konstrukcí).

    Postupně si rozebereme jak správně používat kolekce v nejčastějších případech a přitom si popíšeme její nejdůležitější zprávy.
    Také se něco málo zmíním o hierarchii kolekcí.

    Přístup k jednotlivým prvkům kolekce

    at: anIndexOrKey

    Způsob identifikace objektu v kolekci je závislý na typu kolekce. Kolekce může být "indexována" číslem, klíčem tvořenými jiným objektem a podobně.
    kolekce at: 1
    kolekce at: #klic


    Práce s kolekcí jako celkem

    operátor čárka (,) pro spojování kolekcí

    Spojí dvě libovolné kolekce do jedné (někdy je důležité si dát pozor jestli je zaručeno zachování pořadí prvků jako například u spojování dvou množin apod.)
    kolekce1, kolekce2


    Iterace nad všemi prvky kolekce

    do: oneParameterBlock

    Nejjednošší a uniformní způsob jak postupně pro všechny prvky kolekce provést právě jednou nějakou akci, je použít zprávu do:. Co se bude s každým vybraným elementem provádět je zapsáno v bloku s jedním parametrem, který je předán jako parametr této zprávy.
    kolekce do: [:elem | Transcript show: elem asString; cr.]


    with:do:

    Potřebujete-li kombinovat prvky 2 kolekcí a to v tom samém pořadí, tak lze s výhodou využít tuto velmi pohodlnou zprávu:
    "součet dvou vektorů uložených jako čísla v kolekcích (s definovaným pořadím prvků)"
    vectorResult := OrderedCollection new: vector1 size.
    vector1 with: vector2 do: [:elem1 :elem2 | vectorResult addTail: (elem1 + elem2).].
    


    inject:into:

    Pokud je potřeba postupně vybírat prvky kolekce a počítat z nich nějakou finální/celkovou hodnotu a tato hodnota má vztah k předchozí hodnotě odvozené od již zpracované části kolekce.
    Tato funkce je poměrně složitá na jednoduché vysvětlení, takže na úvod pouze řeknu, že se jedná o funkci typu SCAN známou z funkcionálních jazyků a nabídnu hned několik praktických příkladů, které snad využití této zprávy dostatečně osvětlí.

    { příklad v mutaci pascalu - pro lepší pochopení i pro Squeakery-začátečníky }
    celkove := init_hodnota;
    for i := 1 to count(kolekce) do
    	celkove := operace(kolekce[i], celkove);
    "return celkove"
    
    "to samé ve Squeaku"
    kolekce inject: init_hodnota into: [:celkove :elem | elem operace: celkove].
    "případně opačné pořadí tj. celkove operace: elem"
    "pokud je operace komutativní, tak je to ale jedno jaké použijete pořadí"
    


    "příklad vlastního převodu kolekce na řetězec"
    kolekce inject: '' into: [:str :obj | str, obj asString].
    
    "příklad nerekurzivní implementace funkce 10 factorial (není však asi efektivní)"
    (1 to: 10) inject: 1 into: [:fact :n | fact * n].
    
    "suma čísel v kolekci"
    kolekce inject: 0 into: [:suma :cislo | suma + cislo].
    
    "nalezení a vrácení maxima z čísel v kolekci (kolekce může obsahovat i nečísla)"
    kolekce inject: -(Float infinity) into: [:maximum :num | num isNumber ifTrue: [maximum max: num.] ifFalse: [maximum]].
    
    "suma prefixů seznamu čísel (tj. pro #(2 1 3 0 2) bude výsledek #(2 3 6 6 8)"
    kolekce inject: (OrderedCollection new: kolekce size) into: [:res :cislo | res, (res last + cislo)].
    "pro pripomenuti, operator carka spojuje (konkatenuje) kolekce"
    


    TODO: hierarchie kolekcí a hlavně kdy je vhodné kterou použít (např. které umí bezproblémů růst, jak implementovat růst kolekce, která to nativně neumí (využití proudů dat) apod.)
    TODO: odzkoušet funkčnost příkladů :-)))


    Odkaz na tuto stránku

    • Články, poslední úprava dne 17 Únor 2010 v 11:18:52 uživatelem localhost





    Administrátoři: Pavel Křivánek, Zbyněk Křivka