Jednou jsem potřeboval pro potřeby jednoho projektu z oblasti teoretické informatiky vygenerovat permutace velké kolekce prvků. Doba výpočtu byla v řádu dnů a na noc počítač vypínám, takže jsem opravdu ocenil možnost pozastavovat výpočet (Alt+tečka) a ukládat image.
Až na vstupní množinu ten kód vypadal nějak takhle:
| result |
result := Set new.
#(a b c d e f) permutationsDo: [:p | result add: p copy ].
^result size asString, ': ', result asString.
Mohl jsem sice použít třeba VMWare apod. nebo si přerušování výpočtu naprogramovat sám, ale...
Pro uplnost - GNU Smalltalk ma docela hezke, v praxi normalne pouzitelne GUI. Je zalozeno na 'blox-tk' balicku, coz je v podstate smalltalkska vazba na tcl/tk. Existuje take vazba na gtk, nicmene ta je zrejme teprve v pocatcich. Screenshot blox-tk oken lze videt napriklad zde: http://freshmeat.net/projects/gnusmalltalk/
Jeste chci autorovi podekovat za serial. Podobny jsem marne hledal jiz delsi dobu. Vrtaji mi ted hlavou ty vykricniky v *.st souborech. Kde se lze docist proc a na zaklade jakych pravidel se ten kod takto rozdeluje a preklada po castech?
Diky a hodne zdaru do dalsich dilu. Tesim se, ze nas ceka nejaka hezka ukazkova aplikace, na ktere si probranou teorii vyzkousime :)
Vykřičníky jsou dány gramatikou pro tyto soubory.
http://www.gnu.org/software/smalltalk/gst-manual/gst_8.html
http://www.delorie.com/gnu/docs/smalltalk/gst_97.html
Povšiměte si, že např. vytvoření třídy je volání zprávy, nicméně vytvoření metod pro větší přehlednost už klasické volání zprávy není. Při nahrávání zdrojového souboru je tak nutno průběžně měnit režim zpracování.
Soubory *.st slouží jako zdrojové soubory, scriptovací soubory i jako kombinace zdrojových a scriptovacích souborů.
Pokud do nich napíšete nějaký kód, přeloží se a provede. Vykřičníky pak oddělují jednotlivé části. Např.:
| a |
a := 1.
Transcript show: a; cr.
!
| a |
Transcript show: a; cr.
a := 2.
Transcript show: a; cr.
Každá část oddělená vykřičníkem se kompiluje a provádí zvlášť. Proto se do Transcriptu vypíše 1, nil a 2.
Kompilátor musí vědět, zda to, co mu předhazujeme, je kód nějaké metody či sekvence příkazů k provedení.
"Kompilátor musí vědět, zda to, co mu předhazujeme, je kód nějaké metody či sekvence příkazů k provedení. "
1) Proc to musi vedet, kdyz vse je objekt a vse co lze ve smalltalku delat je posilat zpravu?
2) Proc se to dozvida zrovna pomoci vykricniku, tela metod by preci sla predavat kompilatoru jako bloky, treba
MojeTrida addMethod: #sampleMethod body: [ 'metoda' ].
Tim se slo vyhnout zcela vykricnikum. Pokud ne, v cem se mylim?
Problém bude v tom, že kompilace metody není jen otázkou příkazu typu MojeTrida addMethod: #sampleMethod body: [ 'metoda' ].
Při kompilaci metody ještě sehrávají úlohu speciální objekty zajišťující odchytávání chyb kompilátoru apod.
Nicméně i tak si lze představit, že by to tímto způsobem bylo možné udělat. Pak je třeba vzít ještě v potaz fakt, že úplně stejný formát má celý soubor *.sources. Pokud by u každé metody byl uveden přímo přikaz pro její vytvoření, obsahovaly by tyto zdrojové soubory spoustu zbytečných informací navíc a oddělování pár vykřičníky je přece jenom úspornější.
Oni st soubory nejsou ani primarne urceny k prohlizeni a editaci kodu, na to je (mnohem prehledejsi) browser. Jsou vicemene jen na prenos kodu.
Trochu odbocka - skripty pro Smalltalk/X jsou sice take podobneho formatu, ale vetsinou v nich neni takovy vykricnikovy zmatek, tam se vykricnikem jen oddeluji bloky kodu (tj. znamena doIt).
V tom pripade mi neni zcela jasny rozdil mezi zdrojovym a skriptovacim souborem. Na vykricnicich se mi vpodstate nelibi, ze se castecne vymykaji tomu, co bylo doposud o smalltalku receno. Narusuji transparentnost a homogenitu puvodni predstavy, ze programovani ve smalltalku je pouze a jen zasilani zprav nejakym jiz existujicim objektum. Ukazuje se, ze pridani metody neni klasicka zprava. S vytvorenim metody se poji nejaka "magicka operace" (tou je zrejme zminene prepnuti kompilatoru do jineho modu).
Nemyslím si, že by *.st soubory narušovaly transparentnost jazyka. Samozřejmě nemáte jinou možnost, než vytvářet metody pomocí volání zprávy. Nicméně pokud ve zdrojovém souboru uvedete pouze text metody s tím, že u ní specifikujete navíc pouze kategorii, třídu, čas a iniciály autora, pak to bude určitě lepší, než když do zdrojáku napíšete přímo příkaz pro její vytvoření, protože dáte tomu, kdo bude zdrojový soubor číst, příležitost, aby si sám specifikoval překladač a odchytávače zpráv. Navíc byste si jen komplikovali práci, pokud byste si chtěli zdrojový soubor procházet v browseru bez toho, abyste jej nafajlovaly do image. Vykřičníky nejsou jedinou možností, jak toho docílit. Některé Smalltalky například umožňují přenos zdrojových textů v xml. Ani když programujete v browseru, nemají metody formát volání zprávy, jako je tomu u tříd.
Vytvoření třídy je naprosto odlišná operace. V podstatě jde o tvorbu nového objektu. Vytvoření metody je sice také tvorba nového objektu (instance třídy CompiledMethod), ovšem je nejdříve třeba vygenerovat odpovídající bytekód pomocí kompilátoru.
Když necháváte provést nějaký výraz (např. ve Workspace nebo třeba fileinujete definici třídy), je za běhu přeložen do bytekódu kompilátorem a vykonán.
Když necháváte vytvořit nějakou metodu, uděláte to výrazem, který je také přeložen do bytekódu a vykonán, ovšem uvnitř tohoto vykonávaného výrazu musíte vytvářet další instanci kompilátoru, který musí nějakým způsobem hlásit chyby apod. Proto je ve vytváření tříd a metod rozdíl.
Vaše dotazy samozřejmě vítám.