Pořád máš divnou terminologii. Nechápu, proč ji používáš. Shodnem se na tom, že číslo a string jsou různé datové typy? Ano, když sečtu číslo a string, tak to spadne na type error, proto mi není jasné, proč to označuješ za varianty jednoho datového typu. To jsou hodnoty různých datových typů. Na základě čeho to spadne u tebe, když to považuješ za jeden datový typ?
No úplně právě neshodneme. V dynamických jazycích jsou číslo a string vlastně stejný datový typ ("JSValue"), protože ty můžeš zavolat "3 + '6'" - a normálně se to zavolá. A pak někde v tom __add__ se to zkontroluje a případně spadne. Ty přece klidně můžeš sečíst 2 různé třídy a __add__se normálně zavolá, zkus si to, nikde tam k žádné kontrole nedochází. Typy jsou právě statická záležitost....
Tady to je z Pierce... a je to z knížky, která se celosvětově používá pro výuku teorie typovaných jazyků, takže být tebou se tak úplně nesnažím s tím polemizovat, pokud to nemáš nastudované....
To word "static" is sometimes added explicitly - we speak of a "statically types programming language," for example - to distinguish the sorts of compile-time analyses we are considering her from the dynamic or latent typing found in languages such as Scheme, where run-time type tags are used to distinguish differend kinds of structures in the heap. Terms like "dynamically typed" are arguably misnomers and shoudl probably be replaced by "dynamically checked", but the usage is standard.
Ještě se koukni na tu citaci předtím - typy se řeší
staticky. Pokud nejsi schopen ty typy řešit staticky, ale až runtime, tak už se tomu tak úplně neříká typ, ale třeba "tag". Python je naimplementovaný podobně jako ten příklad v C. A všechny ty funkce vrací JSValue (PyValue?? už jsem to API dlouho neviděl).
To je chybné vnímání dynamického jazyka. V něm nejsou proměnné důležité. Proměnná v dyn. jazyku je jen ukazatel na hodnotu, není na venek nositelem žádného datového typu a neobsahuje žádnou hodnotu. Je v tomto kontextu nezajímavá. V dynamickém jazyku se pracuje s hodnotami, datový typ je integrální součástí hodnoty, ne proměnné. Neřeš vnitřní implementaci, ta není podstatná a je poplatná optimalizacím, vnímej vnější prezentaci, vnější abstrakci.
No vždyť jo, v dynamickém jazyce obsahuje každá hodnota "tag", který jsi schopen v runtimu přečíst a zařídit se. Zkus si napsat vlastní implementaci __add__ na sečtení 2 objektů "tvého" typu (napiš si třeba komplexní číslo). Tipuju, že tam někde budeš mít:
def __add__(self, other):
# Tady by mohla byt kontrola na komplex cislo + normalni atd.
# Porovnej tagy... nebo treba pres isinstance...
if type(self) != type(other):
raise TypeError(...)
V Haskellu (i v tom C++) při běhu hodnoty ten tag neobsahují, nejsi schopen dělat introspekci, typy se po compile-time-kontrole normálně vymažou. Proto potřebuješ součtový typ, který tam ty tagy dodá, abys byl schopen ty různé typy rozlišit. No a dynamické jazyky tam ty tagy run-time mají a umíš se na ně run-time zeptat. Takže je to přesně ekvivalentní tomu, jako když ve statickém jazyku použiješ to JSValue... A jak vidíš výše, není to žádný implementační detail, ale normálně se s tím v tom jazyce pracuje (akorát ta terminologie je trošku jiná).
A proto tady protestujeme proti té ne-flexibilitě statického jazyka: přes součtový typ naprosto bez problému uděláš chování, které bude ekvivalentní dynamickým jazykům. Kompiler přestane řvát na chyby typů (kromě počtu parametrů) - všechno bude jeden typ. Nic se nebude kontrolovat compile-time, všechno spadne runtime. Při běhu se budeš moct zeptat na tag ("typ") té hodnoty, kterou tvoje funkce dostane...
Co ti typový systém přináší, je, že těch typů můžeš mít víc a při kompilaci ti to najednou vyhlásí: tahle funkce nemůže vracet číslo....