Zprávy s proměnným počtem parametrů jsou vlastně obdobou klasického volání metod s různým počtem parametrů že? Proč je to vlastně ve Squeaku řešeno tak syntakticky „podivně“?
Není například:
color r: 10 g: 20 b:20
to stejné jako:
color(10,20,30)
?
nebo je to spíš podobné Pythonovskému způsobu „pojmenování“ parametrů (teď nevím, jak se tomu přesně nadává)?
Není například:
color r: 10 g: 20 b:20
to stejné jako:
color(10,20,30)
?
Je to stejne, ale kdyz si na to clovek zvykne, tak citelnejsi a hlavne zrejmejsi. Co napr. udela v nahodnem C-like jazyku
Rectangle (10, 10, 20, 20)?
To same co ve smalltalku
Rectangle top: 10 left: 10 bottom: 20 right: 20
nebo
Rectangle top: 10 left: 10 width: 20 height: 20
nebo neco jineho? Ve smalltalku je to daleko zrejmejsi.
Od pythonovskeho
Stooge2(1, 2, shemp=3, curly=4)
se to lisi tim, ze v pythonu by slo napsat i
Stooge2(1, 2)
kde shempu a curly by se priradily defaultni hodnoty. To ve smalltalku nejde, zadne defaultni hodnoty nezna, musela by se implementovat nova zprava s pouze dvema parametry. Nelze vynechavat casti selektoru zpravy. V praxi to nevadi.
Pravda, taky mě po napsání dotazu „docvaklo“, že ten Squakovský nebo chcete-li Smalltalkovský způsob je vlatně v mnoha ohledech „samodokumentující“, protože v Javě například musím pěkně počkat, až mi vyběhne nápověda, co který parametr znamemá (zrovna u Rectangle nebo drawOval atd.) nebo mrknout do JavaDocu popř. přímo do zdrojaků :-)
Zasílání zpráv se dá řešit různými způsoby:
algolovská
person.name() person.name("Pepa") person.name("Pepa". "Vopršálek") (person.name("Pepa". "Vopršálek")).age()
algolovská s properties (rozsáhlejší definice)
person.name person.name("Pepa") person.name("Pepa". "Vopršálek") (person.name("Pepa". "Vopršálek")).age
smalltalkovská
person name person name: 'Pepa' person name: 'Pepa' surname: 'Vopršálek' (person name: 'Pepa' surname: 'Vopršálek') age
lispovská
(person-name person name) (person-setName person 'Pepa) (person-setName person 'Pepa 'Vopršálek) nebo něco jako (setFields person :name 'Pepa :surname 'Vopršálek) (person-age (person-setName person 'Pepa 'Vopršálek))
prefixová
person name person setName 'Pepa person setFullName 'Pepa 'Vopršálek (person setFullName 'Pepa 'Vopršálek) age
postfixová
person person-Name person "Pepa" person-setName person "Pepa" "Vopršálek" person-setFullName person "Pepa" "Vopršálek" person-setFullName age
postfixová s příjemcem na vrcholu zásobníku
name person "Pepa" setName person "Pepa" "Vopršálek" setFullName person age "Pepa" "Vopršálek" setFullName person
Smalltalkovská mi příjde jako rozumný kompromis. Jestli vás napadá nějaký další způsob, sem s ním :-)
Ve výše uvedeném případě se jedná o jednu zprávu s třemi argumenty, která se jmenuje r:g:b: a NELZE ji volat třeba jako
color b: 30 g: 20 r: 10
Ve Smalltalku neexistují zprávy s proměnným počtem parametrů, musí se v takovém případě předat nějaká kolekce, např.
Color from: {10. 20. 30}
(složené závorky jsou tzv. výrazové pole, ne všechny implementace Smalltalku je mají)
Jestli jsem to dobre pochopil tak bloky by se mely dat vyuzit k linemu vyhodnocovani.
Rekneme ze chci napriklad C-style OR. Tedy a || b nejdriv vyhodnoti a, a teprve kdyz je false tak se snazi vyhodnotit i b. Predpokladam ze smalltalk nejdriv vyhodnoti kdo je prijemce a jake jsou parametry zpravy a pak ji teprve posila. Cili a || b bude znamenat ze se vyhodnocuje nejdriv a pak b a naknec se tomu na co se vyhodnotilo a posle zprava s obsahem toho na co se vyhodnotilo b (predstavte si ze a i b jsou nejake slozite uzavorkovane vyrazy).
Kdyz ale napisu a || [b], tak se b nevyhodnocuje a do acka se posle ‚zdrojak‘ bcka, ktery teprve muzu vyhodnocovat uvnitr zpracovani zpravy ||, kdyz mu poslu zpravu value. Takze jestli se navic pro normalni objekty chova value jako identita, tak muzu psat oboji a||b i a||[b], kde prvni ma semantiku jako v pasacalu a druhy zapis jako v Ccku.
Je to tak? Bylo by to docela elegantni…
Ten blok [ b ] se skutecne nevyhodnocuje do te chvile, nez ho k tomu donutis, je to neco jako apostrof v Lispu :-). Takze bloky=normalni objekty si muzes predavat kam chces, pouzivat je jako parametry zprav a teprve ve vhodne chvili se vyhodnoti a popr. se jim „dosadi“ parametry – opet poslanim zpravy.
Ono je to ve Smalltalku vyřešeno trochu jinak:
& vyhodnocuje vždy obě strany
and: vyhodnocuje líně.
Takto je na první pohled vidět, jestli má být vyhodnocování líné nebo ne. To, co chcete, by vypadalo takto:
True >> && alternativeBlock ^ alternativeBlock value False >> && alternativeBlock ^ alternativeBlock isBlock ifTrue: [self] ifFalse: [alternativeBlock value. self]
Zpráva value u normálních objektů vráti volaný objekt.
Binární zprávu pojmenovanou || nelze ve Smalltalku vytvořit kvůli kolizi s definici dočasných proměnných.