Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: fortran1986 15. 08. 2019, 11:34:34

Název: Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: fortran1986 15. 08. 2019, 11:34:34
Pozeral som si zdrojaky OO jazykov ako smalltalk s posielanim sprav. Jednou z ich zakladnych crt je ze aj prikazy ako if maju riesene ako spravy posielane objektom (konkretne keyword message ifTrue, ifFalse posielane objektu boolean) ako je to mozne? nerozumiem tomu ako to funguje.

ked porovnam posielanie sprav s volanim metod


najblizsie ku keyword spravam maju metody s pomenovanymi parametrami. Ale pri takomto volani metody sa najprv vyhodnotia argumenty, s ktorymi sa potom vola metoda, to znamena ze kod sa musi vykonat este pred poslanim spravy. pri poslani spravy ak by sa parametre vyhodnotili uz pred poslanim spravy tak sa obidve vetvy ifu musia vykonat zaroven a az potom si iba vyberem podla boolu len ich vysledok... ak by som mal trebars takyto kod:

Kód: [Vybrat]
(a > 5)
ifTrue:
   [ Transcript show: 'a je vacsie ako 5' ]
ifFalse:
   [ Transcript show: 'a je mensie ako 5' ]

prepiseme trebars do do C# (ten ma pomenovane parametre), ale kludne aj do ineho jazyka (Za predpokladu ze tam mame nadefinovanu metodu EvalCondition)

Kód: [Vybrat]
(a > 5).EvalCondition(
    ifTrue: MessageBox.Show("a je vacsie ako 5"),
    ifFalse: MessageBox.Show("a je mensie ako 5")
)

Tak sa vypise aj "a je vacsie ako 5" a za tym aj "a je mensie ako 5". Jediny sposob ako si viem predstavit ze by sa dal naemulovat smalltalkovsky if pomocou volania metody je namiesto bloku ako argument predat lambdu, ktora sa vykona neskor. pripadne novsie jazyky maju async bloky, promises, alebo lazy bloky, ktorymi by sa to dalo emulovat tiez, ale vlastne v principe ide o to iste.

takze viete mi vysvetlit ako to funguje v smalltalku?
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Idris 15. 08. 2019, 13:48:05
Však ve Smalltalku se předává lambda výraz (instanci pravdivostního typu).
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: tecka 15. 08. 2019, 14:31:53
Zase hledáš paralely tam, kde nemají smysl.
Kód: [Vybrat]
b = a.gt(5)
b.ifTrue(lambda: ...)
b.ifFalse(lambda: ...)
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: registrovany_ava 15. 08. 2019, 16:16:40
C# ekvivalent tveho prikladu by vypadal

Kód: [Vybrat]
(a > 5).EvalCondition(
    ifTrue: () => MessageBox.Show("a je vacsie ako 5"),
    ifFalse: () => MessageBox.Show("a je mensie ako 5")
)

Z typu by melo byt jasne jak to funguje.

smalltalkovske zpravy a volani metod v jinych jazycich je v zasade to same, jen je
 
 - jina terminologie (zaslani zpravy vs volani metody)
 - jina syntaxe (smalltalkovske nullarni/binarni/keyword zpravy)
 - ve smalltalku je mozne poslat zpravu (volat metodu), kterou receiver (objekt na kterem ji volam) neimplementuje (neni staticke typovani). V takovem pripade se na receiveru zavola metoda #doesNotUnderstand: (volana zprava), ktera by default vyhodi vyjimku, ale je mozne ji pretizit a zpracovat specialne (napr. se takto daji implementovat ruzne genericke proxy objekty).
 - volana zprava (tj. selektor aka "nazev metody" v novem OOP + argumenty) je zapouzdrena (smalltalkar by asi rekl reifikovana) do objektu Message, dostat se k ni lze napr. prave treba v #doesNotUnderstand:. Nebo je mozne ji programove vytvorit, treba na zaklade uzivatelskeho vstupu, a poslat nejakemu objektu

Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Idris 15. 08. 2019, 16:31:33
Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
To doesNotUnderstand má i Java, ale ještě jsem to neviděl v praxi.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: gill 15. 08. 2019, 17:11:06
https://rosettacode.org/wiki/Respond_to_an_unknown_method_call
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Johnny 15. 08. 2019, 17:40:46
Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
To doesNotUnderstand má i Java, ale ještě jsem to neviděl v praxi.
To není tak úplně pravda, lze obalit volání metody s try/catch a odchytit výjimku NoSuchMethodException, ale to volání musí jít přes reflexi! Takže jedině udělat si vlastní method-lookup (vyhledat požadovanou metodu přes Class.getMethods), vyhodit tu výjimku, + zavolat si nějaké vlastní doesNotUnderstand.
Nic "out-of-the-box" Java ve standartní knihovně nemá.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Idris 15. 08. 2019, 20:06:07
Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
To doesNotUnderstand má i Java, ale ještě jsem to neviděl v praxi.
To není tak úplně pravda, lze obalit volání metody s try/catch a odchytit výjimku NoSuchMethodException, ale to volání musí jít přes reflexi
Nemusí, Java má mechanismus pro proxy.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Johnny 15. 08. 2019, 20:33:54
Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
To doesNotUnderstand má i Java, ale ještě jsem to neviděl v praxi.
To není tak úplně pravda, lze obalit volání metody s try/catch a odchytit výjimku NoSuchMethodException, ale to volání musí jít přes reflexi
Nemusí, Java má mechanismus pro proxy.
Budiž, lze použít i proxy, ale libovolnou metodu si takhle potom nezavolám.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Idris 15. 08. 2019, 20:44:35
Vetsinou to jsou veci, ktere jdou napr. i v pythonu apod., ale v smalltalku je to vsechno tak nejak prirozene, od zacatku se s tim pocita v syntaxi jazyka, standardni knihovne, i vyvojovem prostredi, takze se to snadno a prijemne pouziva. Treba #doesNotUnderstand neni vec, kterou by clovek pretezoval kazdy den (nebo mesic), ale kdyz je to nahodou potreba, je prijemne ze to je k dispozici.
To doesNotUnderstand má i Java, ale ještě jsem to neviděl v praxi.
To není tak úplně pravda, lze obalit volání metody s try/catch a odchytit výjimku NoSuchMethodException, ale to volání musí jít přes reflexi
Nemusí, Java má mechanismus pro proxy.
Budiž, lze použít i proxy, ale libovolnou metodu si takhle potom nezavolám.
Ono jde spíše o odchycení, a právě k tomu slouží InvocationHandler, což je ten ekvivalent doesNotUnderstand.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Johnny 15. 08. 2019, 21:05:59
Ono jde spíše o odchycení, a právě k tomu slouží InvocationHandler, což je ten ekvivalent doesNotUnderstand.
Pokud jde o mechanismus odchycení poslané zprávy/volané metody, pak ano. Ale není to ekvivalent doesNotUnderstand ve Smalltalku. Tam se zachytí zpráva, kterou daný objekt neumí zpracovat (neexistuje), zatímco v Javě takovou zprávu nelze zavolat. Až teprve přes tu reflexi můžu zjistit, zda nějaká metoda existuje.
Ale myslím, že si rozumíme. Podle mě ten detail, v čem se to liší je dost podstatný.
Název: Re:Smalltalk, Self a podobne jazyky - mechanizmus posielania sprav
Přispěvatel: Bystroushaak 19. 08. 2019, 11:10:05
Jak už tu psali ostatní, funguje to protože bloky ve smalltalky implementují late binding a jsou vyhodnoceny nikoliv na místě definice, ale teprve když je jim poslána zpráva ala value (https://www.gnu.org/software/smalltalk/manual/html_node/Invoking-code-blocks.html). Bloky jsou cosi jako lambda funkce, i když tohle přirovnání úplně nesedí, protože jsou to zároveň objekty. Třeba v Selfu se chovájí běžně jako klasický code-object, jen mají namapovaný scope parent do místa kde byly definovány, místo do místa kde jsou použity, jak je to běžné u klasických objektů.

Ta implementace ifů je mimochodem krásná, třeba v mé reimplementaci Selfu (https://github.com/Bystroushaak/tinySelf/) to vypadá takhle:

Kód: [Vybrat]
    init_true = (| true_mirror |
        true_mirror: primitives mirrorOn: true.

        true_mirror toSlot: 'ifTrue:' Add: (| :block | block value).
        true_mirror toSlot: 'ifFalse:' Add: (| :block | nil.).
        true_mirror toSlot: 'ifTrue:False:' Add: (| :true_block. :false_block |
            true_block value
        ).
        true_mirror toSlot: 'ifFalse:True:' Add: (| :false_block. :true_block |
            true_block value.
        ).
    ).

    init_false = (| false_mirror |
        false_mirror: primitives mirrorOn: false.

        false_mirror toSlot: 'ifTrue:' Add: (| :block | nil).
        false_mirror toSlot: 'ifFalse:' Add: (| :block | block value.).
        false_mirror toSlot: 'ifTrue:False:' Add: (| :true_block. :false_block |
            false_block value
        ).
        false_mirror toSlot: 'ifFalse:True:' Add: (| :false_block. :true_block |
            false_block value.
        ).
    ).

Smalltalk a Self používají model extension method (https://en.wikipedia.org/wiki/Extension_method), který umožňuje zpětně přidávat do tříd další metody. Díky tomu jsou některé věci přirozeně obrácené, než na co jsme zvyklí z jazyků jako Java, C# a Python. Tedy například to poslání ifu objektu bool, ale i spousta dalších věcí. Dost mě například konsternovalo, když jsem začal dělat ve smalltalku, že se považuje za běžné například začít přidávat metody do intu, či stringu.