Hm, zrovna před pár dny jsem podobnou věc ukazoval ve svém blogu (na konkurenčním) serveru pro Perl 6, ale neznal jsem terminologii, tak jsem mluvil o kontextu a vynucení kontextu a uvedl jsem, že mi to připomíná polymorfismus :)
Lze např. pro number to zapsat i nějak takto
(defmethod heading Number
[value]
(heading (str value))
tedy z ní volat tu verzi pro String?
Tak to je pěkná náhoda. Já to napsal hlavně jako reakci na tu recenzi (resp. ne přímo na ni, protože v knížce se multimetody přelítnou v jedné jediné sekci), ale na diskuzi pod článkem.
Nicméně ta úprava bude fungovat podle očekávání:
(defmethod heading Number [val] (heading (str "*** " val " ***")))
Potom v REPLu:
user=> (heading nil) ----------------- nothing ----------------- user=> (heading 42) ----------------- *** 42 *** ----------------- user=> (heading "Zdravime wambu!") ----------------- Zdravime wambu! -----------------
Já jsem rád, že se tu tento článek objevil, protože jsem měl pocit, že tato v Perlu běžná věc je tak trochu v ostatních jazycích tabu. Jsou přímo v jazyce Clojure zabudované funkce, které by parametrický polymorfismus využívali, resp. jak je to běžné? (Ono vlastně jde vidět v první verzi, že funkce write automaticky číslo převede na znak pomocí ASCII, což je právě tento princip.)
Popravdě v základní knihovně je to použito minimálně a zrovna pro výstupní funkce (modul pretty-writer a instant). Tam je to asi nejvíc potřeba, protože print/println musí zvládnout vypsat hodnoty různých typů, teď se dívám, že to umí i Date, DateTime, Timestamp atd.
Osobně jsem to použil jen několikrát, ale když nad tím přemýšlím, tak bych tak mohl vyřešit dispatch handlerů HTTP požadavků. Teď tam totiž mám něco takového:
(condp = [method (get-api-command request uri)] [:get "/info"] (rest-api/info-handler request (get-hostname)) [:get "/job-list"] (rest-api/get-job-list-handler request) (rest-api/unknown-call-handler uri method)))
A přesně toto by šlo řešit deklarativně přes multimetody a ne imperativně rozeskokem :)
jako priklad je kruh-elipsa pouzitelny, ale stejne si myslim, ze zde
hledaji problem kde neni.
hierarchie dedeni ma jit od obecnejsiho ke konkretnejsiho.
rodicovska trida je obecnejsi, potomek je konkretnejsi.
elipsa je obecnejsi nez kruh, ma dve ruzne osy. kruznice ma obe osy
stejne. kruh je potomek elipsy.
realne cislo je potomkem komplexniho cisla, realne cislo je zuzeni komplexniho cisla v tom, ze ma nulovou komplexni slozku.
myslim, ze v oop to lidi ale dedi naopak. kruznice ma jenom promenne x,y,r, zatimco elipsa jich ma vice x,y,l1,l2,uhel.
Pokud je kruh (nebo kruznice) potomek elipsy, tak to znamena, ze i pro kruh mas k dispozici treba setA(), setB(), navic k tomu setR() atd.? No to by prece bud rozbilo tvrzeni o stejne dlouhych osach, nebo bys settery nedelal (podle me nejlepsi reseni) nebo by to vyhazovalo vyjimky?
Navic i kdyby to takto fungovalo, tak si myslim, ze takto hierarchie trid v OOP nebyly mysleny :) Tam se spis tise predpoklada 'obecnejsi == nektere vlastnosti *neexistuji* nebo jsou tak obecne, ze ta obecna trida musi byt abstraktni'.
"Navic i kdyby to takto fungovalo, tak si myslim, ze takto hierarchie trid v OOP nebyly mysleny :) "
Myslím, že zcela původně hierarchie tříd v OOP nebyly myšleny vůbec nijak. Jen "buňky" a zprávy mezi nimi. Jinak samozřejmě že v jazycích, které nedokáží změnit třídu objektu za chodu, budou s rozhraními problémy.
Zajimavy pohled na vec nabizi Scott Meyers v More Effective C++ Item 31.
Na klasicke virtualni metody napr. v C++ se muzes divat jako na multimetody s jednim parametrem, ktere za tebe v C++ generuje prekladac (polymorfni vzhledem k this). S metodami, ktere jsou polymorfni vzhledem k vice parametrum, ti uz C++ nepomuze a musis si to naimplementovat sam, popr. pouzit jazyk, ktery multimetody podporuje, jako Clojure :-)
Zajímavě má polymorfismus vyřešen Common Lisp ve svém CLOS (Common Lisp Object System https://en.wikipedia.org/wiki/Common_Lisp_Object_System ) taky podporuje multiple dispatch a při čtení článku jsem si na něj vzpomněl :)
Řekněme politicky korektně, že Clojure se Common Lispem hodně inspirovalo :)
Ale fakt je, že CLOS je pojat zajímavě, je hodně dynamický, takže třeba ten problém kružnice-elipsa se tam řeší elegantně.
[tuším, že se CLOS pořád učí v Olomouci, bylo by zajímavé pokecat s někým, kdo se setkal jen s CLOSem a ne z třídním OOP ve stylu C++/Javy]
Paradigmata programovani?
http://vychodil.inf.upol.cz/kmi/pp1/
Je to snad posledni vysoka skola u nas, co to takto vyucuje :/
Neblazni, sice mam C svym zpusobem porad jeste strasne rad, ale delat v nem neco slozitejsiho je opruz. Porad pocitat s tim, kdy a jak velke alokovat stringy, vytvaret po X-te seznamy, stromy, hashmapy, vyjimky resit jumpem nebo if-ama, to uz pro oblast desktopu nebo serveru (vetsinou) ne prosim :)
Ostatne naprosta vetsina CVE-cek jsou typicky Cckoviny typu buffer overflow, problematicke chovani malloc/free apod.
Praveze v ruznych vysokourovnovych jazycich resis primo dany problem a ne low-level veci typu GC, datovych struktur apod.
To je pravda, díky za zpětnou vazbu. Já se někdy v budoucnu chystám napsat všeobecně o problematice Clojure a výpočetního výkonu, protože v praxi některé věci, které by například měly fungovat velmi dobře paralelně (například reducery), tak někdy nefungují, na rozdíl od staré dobré pmap (to je jen příklad). Dtto dynamické typování = to někdy nadělá dost paseku, co se týče výkonu.
Vždycky se mi vybaví tohle...
"Dealing with large numbers of interrelated types while still preserving modularity in the design of large systems is very difficult, and is an area of much current research. ... ... This statement, which also appears in the first edition of this book, is just as true now as it was when we wrote it twelve years ago. Developing a useful, general framework for expressing the relations among different types of entities (what philosophers call "ontology'') seems intractably difficult. The main difference between the confusion that existed ten years ago and the confusion that exists now is that now a variety of inadequate ontological theories have been embodied in a plethora of correspondingly inadequate programming languages. ... ... ... In fact, we suspect that these problems cannot be adequately addressed in terms of computer-language design alone, without also drawing on work in knowledge representation and automated reasoning."
(https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-18.html#footnote_Temp_289)