Problémy s JavaScript v praxi

Bacsa

Re:Problémy s JavaScript v praxi
« Odpověď #510 kdy: 10. 10. 2018, 00:46:27 »
Já si bežně z funkcí které čtou data vracím hodnotu false, pokud funkce selže, None pokud data nejsou nebo datový objekt - tedy tři různé datové typy. Není to o nic horší, než návratový číselný kód z C funkce, která možná změní obsah proměnné předané funkci a pro získání chybového textu je nutné volat zvláštní funkci.
Takové věci jdou otypovat několika způsoby, ovšem obecně to je zvěrstvo a vidět takový kód svědčí o junioritě nebo debilitě (v případě seniora) toho, co to spáchal.
Je to přirozené řešení na přirozenou potřebu, kdy z funkce potřebuješ vracet různé stavy a výsledky. Jazyky které to neumí to obchází různými méně čitelnými způsoby.
Nebo místo obcházení použijí již zmíněný součtový typ.
funkce vrací hodnoty různých datových typů
Nevrací, musíš použít příslušný konstruktor. To může překladač udělat za tebe, ale nevyhneš se při použití hodnoty matchingu. Ty fakt nevíš o typových systémech ani houno.
Vskutku neznám jazyk, který by používal součtový typ, byť aktivně těch jazyků používám několik. Pro mě je to okrajová záležitost, nikoliv typická  vlastnost statických jazyků
Aspoň teď už víme, proč píšeš takové kraviny. Nauč se Haskell nebo něco podobně rozumně typovaného (i když existují ještě mnohem silnější typové systémy), otevře ti to oči (pokud to pochopíš).
poskytujete rozporuplné informace typu, že dynamické jazyky jsou specální případ jediného součtového typu, který pokrývá všechny možne datové typy a když z toho vyjdu a odvozuji od toho jeho fungování, tak je všechno špatně
Kde tam vidíš rozpor? Bylo to napsáno správně.


andy

Re:Problémy s JavaScript v praxi
« Odpověď #511 kdy: 10. 10. 2018, 00:52:59 »
Rád bych tu viděl příklad, kde funkce vrací hodnoty různých datových typů (false, none, object), předává to nějaké proměnné a dále se program větví podle toho, jaká hodnota byla předána. Jestli to nejde, pak je z vaše zaklínání se součtovým typem pěkná blamáž.  :-).
Pominu tvoji terminologii, tady máš příklad:
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)

Bacsa

Re:Problémy s JavaScript v praxi
« Odpověď #512 kdy: 10. 10. 2018, 00:58:40 »
Rád bych tu viděl příklad, kde funkce vrací hodnoty různých datových typů (false, none, object), předává to nějaké proměnné a dále se program větví podle toho, jaká hodnota byla předána. Jestli to nejde, pak je z vaše zaklínání se součtovým typem pěkná blamáž.  :-).
Pominu tvoji terminologii, tady máš příklad:
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)
A teď v C++ ;)

andy

Re:Problémy s JavaScript v praxi
« Odpověď #513 kdy: 10. 10. 2018, 01:01:10 »
A teď v C++ ;)
No, přiznávám, že větší projekt v C++ jsem dělal někdy před 8 lety a od té doby jsem to neviděl...ale přes ty varianty bych to asi s velkou mírou vypětí a soubojem s kompilátorem (a za vydatné pomoci googlu) snad dal  ;D

eee

Re:Problémy s JavaScript v praxi
« Odpověď #514 kdy: 10. 10. 2018, 01:09:05 »
eee: když si definuju tohle:
Kód: [Vybrat]
data Value = VInt Int | VDouble Double | VStrint Text | VBool Boolean | VObject (Dict Text Value) | VNone
-- Čti: Typ Value může nabývat hodnot "VInt s parametrem celé číslo", "VDouble s parametrem double" etc.
-- To VInt, VDouble je de-fakto "tag"
Tak to je přesně ten typ, který se používá v JS, Pythonu etc. Všechny funkce potom budou typu ve stylu:
Kód: [Vybrat]
f: Value -> Value
-- Čti: vstupem do funkce je hodnota typu Value, výstupem je hodnota typu Value
No a třeba sčítání by se třeba definovalo jako:
Kód: [Vybrat]
(+) :: Value -> Value -> Value
(+) (VInt i) (VInt j) = VInt (i + j)
(+) (VDouble i) (VDouble j) = VDouble (i + j)
(+) (VInt i) (VDouble j) = VDouble (toDouble i + j)
(+) _ _ = error "crash"
Takže pak mám v programu jeden typ a hotovo, chová se to přesně stejně jako dynamické jazyky (teď ignoruju pure/non-pure, to je další level).

Ve staticky typovaném jazyku můžu udělat něco, co v tom dynamickém nemůžeš: Můžu tu funkci omezit. Můžu říct: tahle funkce může vrátit jenom Int. A nic jiného.

Citace
Tady si imho odporuješ. Klidně přistoupím na tezi, že dynamický jazyk má jediný součtový typ, proč ne. Ale pořád v dynamickém jazyku platí, že funkce může vracet hodnoty různých datových typů (nebo variant v tvé terminologii). To ovšem rozporuješ o kus výše, kde uvádíš, že funkce vrací jeden součtový typ. Takže buď to není totožné s fungováním dynamických jazyků a nebo součtový typ vrací hodnoty různých datových typů (variant v tvé terminologii). Obojí současně platit nemůže, vyber si, co platí.
Varianta typu není typ. Prvek "enumu" taky není zvláštní typ - je to hodnota typu toho enumu.

Představ si součtový typ jako "Enum", kdy ale jednotlivé volby jsou "structy" (v C je tomu dost blízký union, ale překladač nevynucuje to "nebo"). Ad absurdum by se to dalo Enumem simulovat takhle (v C++?):
Kód: [Vybrat]
enum JsValue = { JSNull, JSTrue, JSFalse, Int0, Int1, Int2, Int3, Int4,.... }
Jak vidíš, typ je fakt jeden (JsValue), ale klidně ta funkce (i  v C) může vrátit "null", "true", "false", 0, 1.... atd.
Díky za vysvětlení. Chápu co se snažíš říct, že ten jeden typ vrací různé hodnoty. Ale nevím zda si uvědomuješ, že to neodpovídá chování dynamického jazyka, byť tvrdíš že jo.

a) dynamický jazyk je dynamický, dynamické jsou i typy, takže je nemůžeš předem staticky dát do výčtu, každá třída je novým typem
>>> class A(object): pass
>>> type(type(A()))
<class 'type'>


b) dynamický jazyk rozlišuje datové typy svých hodnot, což ten enum nedělá, v dynamickém jazyku ta varianta je datový typ. Nejde jen o to, že můžeš vrátit libovolnou hodnotu, ale že znáš její typ s kterým můžeš pracovat a s kterým pracuje jazyk. Co to udělá, když budes sčítat hodnoty 5 + '5' obě jednoho součtového typu? V pythonu ti to spadne na rozdílnost datových typů.

c) i v dynamickém jazyku můžeš funkci omezit, buď dekorátorem, což se kontroluje runtime a nebo type hintem, což se kontroluje při překladu.


eee

Re:Problémy s JavaScript v praxi
« Odpověď #515 kdy: 10. 10. 2018, 01:15:30 »
Já si bežně z funkcí které čtou data vracím hodnotu false, pokud funkce selže, None pokud data nejsou nebo datový objekt - tedy tři různé datové typy. Není to o nic horší, než návratový číselný kód z C funkce, která možná změní obsah proměnné předané funkci a pro získání chybového textu je nutné volat zvláštní funkci.
Takové věci jdou otypovat několika způsoby, ovšem obecně to je zvěrstvo a vidět takový kód svědčí o junioritě nebo debilitě (v případě seniora) toho, co to spáchal.
Je to přirozené řešení na přirozenou potřebu, kdy z funkce potřebuješ vracet různé stavy a výsledky. Jazyky které to neumí to obchází různými méně čitelnými způsoby.
Nebo místo obcházení použijí již zmíněný součtový typ.
funkce vrací hodnoty různých datových typů
Nevrací, musíš použít příslušný konstruktor. To může překladač udělat za tebe, ale nevyhneš se při použití hodnoty matchingu. Ty fakt nevíš o typových systémech ani houno.
Vskutku neznám jazyk, který by používal součtový typ, byť aktivně těch jazyků používám několik. Pro mě je to okrajová záležitost, nikoliv typická  vlastnost statických jazyků
Aspoň teď už víme, proč píšeš takové kraviny. Nauč se Haskell nebo něco podobně rozumně typovaného (i když existují ještě mnohem silnější typové systémy), otevře ti to oči (pokud to pochopíš).
poskytujete rozporuplné informace typu, že dynamické jazyky jsou specální případ jediného součtového typu, který pokrývá všechny možne datové typy a když z toho vyjdu a odvozuji od toho jeho fungování, tak je všechno špatně
Kde tam vidíš rozpor? Bylo to napsáno správně.
Už jsem ho popsal, funkce v dynamickém jazyku vrací hodnoty různých datových typů. Funkce vracející součtový typ to podle vás nedělá, ergo se to nechová stejně a dynamické jazyky nejsou implementovány jako případ jediného vše pokrývajícího součtového typu.

Bacsa

Re:Problémy s JavaScript v praxi
« Odpověď #516 kdy: 10. 10. 2018, 01:16:38 »
A teď v C++ ;)
No, přiznávám, že větší projekt v C++ jsem dělal někdy před 8 lety a od té doby jsem to neviděl...ale přes ty varianty bych to asi s velkou mírou vypětí a soubojem s kompilátorem (a za vydatné pomoci googlu) snad dal  ;D
Není to zrovna pastva pro oči:
Kód: [Vybrat]
std::variant<bool,std::string> sillyFunction(const std::string& s) {
    if (s == "true"s) return true;
    if (s == "false"s) return false;
    return s;
}

int main() {
    const auto& r = sillyFunction("C++ sux"s);
    std::visit(match {
        [](bool b) { std::cout << "we got a boolean: " << b << std::endl; },
        [](const std::string& s) { std::cout << "we got a string: " << s << std::endl; }
    }, r);
}

andy

Re:Problémy s JavaScript v praxi
« Odpověď #517 kdy: 10. 10. 2018, 01:30:33 »
a) dynamický jazyk je dynamický, dynamické jsou i typy, takže je nemůžeš předem staticky dát do výčtu, každá třída je novým typem
>>> class A(object): pass
>>> type(type(A()))
<class 'type'>

Ono se o Pythonu říká, že to je jeden velkej "symbol-table hack"... Prostě si tam do toho typu přidáš "VObject Name (HashMap String JSValue), nějak si inteligentně nadefinuješ "isinstance" funkci (aby nějak pracovala s Name), případně tu "type", aby vracela nějaký ten VObject a máš python. Fakt. Všechny ty třídy v pythonu jsou prakticky stejný, akorát se liší v tom, jaký mají __class__.
Citace
b) dynamický jazyk rozlišuje datové typy svých hodnot, což ten enum nedělá, v dynamickém jazyku ta varianta je datový typ. Nejde jen o to, že můžeš vrátit libovolnou hodnotu, ale že znáš její typ s kterým můžeš pracovat a s kterým pracuje jazyk. Co to udělá, když budes sčítat hodnoty 5 + '5' obě jednoho součtového typu? V pythonu ti to spadne na rozdílnost datových typů.
Podívej se na definici toho (+). Ty jednotlivé řádky jsou varianty podle těch typů, co to dostane. Buď takhle nebo přes "case" se můžeš zeptat, která z těch variant (to, co ty nazývaš "typ") to je. Když se pokusíš sečíst číslo a string, tak to slítne na ten "error".
Citace
c) i v dynamickém jazyku můžeš funkci omezit, buď dekorátorem, což se kontroluje runtime a nebo type hintem, což se kontroluje při překladu.
Tak runtime si to můžeš omezit s tím jedním typem jednoduše...prostě si zkontroluješ, jestli jsi dostal správnou variantu. Type hint už pak naopak dělá z dynamického jazyka statický, kdy už třeba některé funkce mají jiný typ než ten univerzální JSValue.

Jenom k terminologii - tohle je z knihy Types and Programming languages (Pierce), to je takový základní text:
Citace
A type system is a tractable syntactic method for proving the absence of certain program behaviours by classyfing phrases according to the kinds of values they compute.

eee

Re:Problémy s JavaScript v praxi
« Odpověď #518 kdy: 10. 10. 2018, 01:34:36 »
Rád bych tu viděl příklad, kde funkce vrací hodnoty různých datových typů (false, none, object), předává to nějaké proměnné a dále se program větví podle toho, jaká hodnota byla předána. Jestli to nejde, pak je z vaše zaklínání se součtovým typem pěkná blamáž.  :-).
Pominu tvoji terminologii, tady máš příklad:
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)
Nejsem si jist, zda ten zapis chapu spravne.
a) Promenna result je jakeho typu? Nevidim jeji deklaraci. A co je to fyzicky? Pojmenovana pamet kde je hodnota nebo pojmenovana pamet, kde je adresa pameti s hodnotou?
b) of dela co? zjistuje datove typy promenne nebo hodnoty? Podle ceho, odkud se ta informace bere?
c) kdyz funkci f spustim dvakrat a vysledky nactu do result1 (None) a result2 (Text), jaky datovy typ bude mit promenne result1 a result2 a co bude vysledkem?

Bacsa

Re:Problémy s JavaScript v praxi
« Odpověď #519 kdy: 10. 10. 2018, 01:36:33 »
a) dynamický jazyk je dynamický, dynamické jsou i typy, takže je nemůžeš předem staticky dát do výčtu, každá třída je novým typem
>>> class A(object): pass
>>> type(type(A()))
<class 'type'>

Ono se o Pythonu říká, že to je jeden velkej "symbol-table hack"... Prostě si tam do toho typu přidáš "VObject Name (HashMap String JSValue), nějak si inteligentně nadefinuješ "isinstance" funkci (aby nějak pracovala s Name), případně tu "type", aby vracela nějaký ten VObject a máš python. Fakt. Všechny ty třídy v pythonu jsou prakticky stejný, akorát se liší v tom, jaký mají __class__.
Citace
b) dynamický jazyk rozlišuje datové typy svých hodnot, což ten enum nedělá, v dynamickém jazyku ta varianta je datový typ. Nejde jen o to, že můžeš vrátit libovolnou hodnotu, ale že znáš její typ s kterým můžeš pracovat a s kterým pracuje jazyk. Co to udělá, když budes sčítat hodnoty 5 + '5' obě jednoho součtového typu? V pythonu ti to spadne na rozdílnost datových typů.
Podívej se na definici toho (+). Ty jednotlivé řádky jsou varianty podle těch typů, co to dostane. Buď takhle nebo přes "case" se můžeš zeptat, která z těch variant (to, co ty nazývaš "typ") to je. Když se pokusíš sečíst číslo a string, tak to slítne na ten "error".
Citace
c) i v dynamickém jazyku můžeš funkci omezit, buď dekorátorem, což se kontroluje runtime a nebo type hintem, což se kontroluje při překladu.
Tak runtime si to můžeš omezit s tím jedním typem jednoduše...prostě si zkontroluješ, jestli jsi dostal správnou variantu. Type hint už pak naopak dělá z dynamického jazyka statický, kdy už třeba některé funkce mají jiný typ než ten univerzální JSValue.

Jenom k terminologii - tohle je z knihy Types and Programming languages (Pierce), to je takový základní text:
Citace
A type system is a tractable syntactic method for proving the absence of certain program behaviours by classyfing phrases according to the kinds of values they compute.
Python (a JS též) jsou hezké v tom, jak umožňují uzávěry nad třídami. Vnitřní implementace je sice zoufalá, ale kód je z akademického pohledu bjůtyfl.

Bacsa

Re:Problémy s JavaScript v praxi
« Odpověď #520 kdy: 10. 10. 2018, 01:39:10 »
Rád bych tu viděl příklad, kde funkce vrací hodnoty různých datových typů (false, none, object), předává to nějaké proměnné a dále se program větví podle toho, jaká hodnota byla předána. Jestli to nejde, pak je z vaše zaklínání se součtovým typem pěkná blamáž.  :-).
Pominu tvoji terminologii, tady máš příklad:
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)
Nejsem si jist, zda ten zapis chapu spravne.
a) Promenna result je jakeho typu? Nevidim jeji deklaraci. A co je to fyzicky? Pojmenovana pamet kde je hodnota nebo pojmenovana pamet, kde je adresa pameti s hodnotou?
b) of dela co? zjistuje datove typy promenne nebo hodnoty? Podle ceho, odkud se ta informace bere?
c) kdyz funkci f spustim dvakrat a vysledky nactu do result1 (None) a result2 (Text), jaky datovy typ bude mit promenne result1 a result2 a co bude vysledkem?
Radši bádej na tím kódem v C++, je názornější a bez monád.

andy

Re:Problémy s JavaScript v praxi
« Odpověď #521 kdy: 10. 10. 2018, 02:02:02 »
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)
Nejsem si jist, zda ten zapis chapu spravne.
a) Promenna result je jakeho typu? Nevidim jeji deklaraci. A co je to fyzicky? Pojmenovana pamet kde je hodnota nebo pojmenovana pamet, kde je adresa pameti s hodnotou?
Proměnná result je typu toho, co vrací funkce "f", tzn. JSValue (příklad type inference). No, fyzicky...fyzicky v podstatě ta proměnná neexistuje.... "let" je definice. Jako v matematice. V podstatě kdekoliv pak použiješ v kódu "result", tak se místo toho vloží "f vstup" (kvůli optimalizaci je to malinko jinak, ale to je podstata).
Citace
b) of dela co? zjistuje datove typy promenne nebo hodnoty? Podle ceho, odkud se ta informace bere?
"case .... of" je normální "case" jako z Javy, C apod. Ty řádký pod tím je tzv. Pattern match na hodnoty, které to může nabývat. "JSBool b" říká: je to varianta JSBool a do proměnné "b" dej ten parametr té varianty (tzn. true nebo false)

Citace
c) kdyz funkci f spustim dvakrat a vysledky nactu do result1 (None) a result2 (Text), jaky datovy typ bude mit promenne result1 a result2 a co bude vysledkem?
Výsledkem funkce f je vždycky hodnota typu JSValue. Na tu je potřeba udělat ten pattern match a na základě toho se dopídit k tomu, kterou variantu jsi dostal. Já zkusím kód v nějakým pseudo-C, který v zásadě dělá to samý (ale hrozně ošklivě a z hlavy):

Kód: [Vybrat]
enum TType = { JSBool, JSText, JSNone}
struct JSValue {
  TType tag;
  union {
     bool boolVal;
     String stringVal;
  }val;
}
JSValue f(String vstup) {
   struct JSValue result;
   if (vstup == "true") {
       result.tag = JSBool;
       result.boolVal = true;
   } else ...
   return result;
}

int main() {
   JSValue result = f("true");
   switch (result.tag) {
      case JSBool:
         bool b = result.val.boolval;
         if (b) printf("Dostali jsme true...");
         break;
      case...
   }
}
Tímhle způsobem můžeš snadno vracet hodnoty různých typů i v C. Ale výhoda jazyků, které přímo součtové typy podporují, je samozřejmě výrazně jednodušší syntaxe a hlavně kontrola jazyka, že jsi třeba nějakou variantu nezapomněl ošetřit, že jsi nezapomněl nastavit ten result.val, že jsi tam opravdu dal správný typ atd.. Popravdě, co mě na většině jazycích štve je právě absence součtových typů, dost výrazným způsobem to usnadní práci a zvýší bezpečnost programu.

eee

Re:Problémy s JavaScript v praxi
« Odpověď #522 kdy: 10. 10. 2018, 02:05:11 »
a) dynamický jazyk je dynamický, dynamické jsou i typy, takže je nemůžeš předem staticky dát do výčtu, každá třída je novým typem
>>> class A(object): pass
>>> type(type(A()))
<class 'type'>

Ono se o Pythonu říká, že to je jeden velkej "symbol-table hack"... Prostě si tam do toho typu přidáš "VObject Name (HashMap String JSValue), nějak si inteligentně nadefinuješ "isinstance" funkci (aby nějak pracovala s Name), případně tu "type", aby vracela nějaký ten VObject a máš python. Fakt. Všechny ty třídy v pythonu jsou prakticky stejný, akorát se liší v tom, jaký mají __class__.
Citace
b) dynamický jazyk rozlišuje datové typy svých hodnot, což ten enum nedělá, v dynamickém jazyku ta varianta je datový typ. Nejde jen o to, že můžeš vrátit libovolnou hodnotu, ale že znáš její typ s kterým můžeš pracovat a s kterým pracuje jazyk. Co to udělá, když budes sčítat hodnoty 5 + '5' obě jednoho součtového typu? V pythonu ti to spadne na rozdílnost datových typů.
Podívej se na definici toho (+). Ty jednotlivé řádky jsou varianty podle těch typů, co to dostane. Buď takhle nebo přes "case" se můžeš zeptat, která z těch variant (to, co ty nazývaš "typ") to je. Když se pokusíš sečíst číslo a string, tak to slítne na ten "error".
Citace
c) i v dynamickém jazyku můžeš funkci omezit, buď dekorátorem, což se kontroluje runtime a nebo type hintem, což se kontroluje při překladu.
Tak runtime si to můžeš omezit s tím jedním typem jednoduše...prostě si zkontroluješ, jestli jsi dostal správnou variantu. Type hint už pak naopak dělá z dynamického jazyka statický, kdy už třeba některé funkce mají jiný typ než ten univerzální JSValue.

Jenom k terminologii - tohle je z knihy Types and Programming languages (Pierce), to je takový základní text:
Citace
A type system is a tractable syntactic method for proving the absence of certain program behaviours by classyfing phrases according to the kinds of values they compute.
Jak funguje python mi nemusíš vysvětlovat. Implementace není podstatná, důležité je, jakou abstrakci ti to poskytuje na venek.

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?

Type hint z jazyka nedělá statický, statičnost není o deklaraci typů, ale o způsobu práce s pamětí. Python i s type hintem zůstává dynamický, type hint jen pomáhá lépe odhalovat chyby při překladu.

eee

Re:Problémy s JavaScript v praxi
« Odpověď #523 kdy: 10. 10. 2018, 02:31:08 »
Kód: [Vybrat]
data JSValue = JSBool Boolean | JSNone | JSText String

-- Funkce f: parametr typu "String", vraci typ "JSValue"
f :: String -> JSValue
f "true" = JSBool True
f "false" = JSBool False
f "none" = JSNone
f t = JSText t

mojeFunkce :: IO () -- (treba...)
mojeFunkce = do
   vstup <- readLine -- neco precti ze vstupu
   let result = f vstup -- Zavolame nasi funkci 'f'
   case result of -- Pattern match na jednotlive varianty
       JSBool b -> if b then putStrLn "dostali jsme true" else putStrLn "dostali jsme false"
       JSNone -> putStrLn "dostali jsme None"
       JSText t -> putStrLn ("Dostali jsme nejaky jiny string: " <> t)
Nejsem si jist, zda ten zapis chapu spravne.
a) Promenna result je jakeho typu? Nevidim jeji deklaraci. A co je to fyzicky? Pojmenovana pamet kde je hodnota nebo pojmenovana pamet, kde je adresa pameti s hodnotou?
Proměnná result je typu toho, co vrací funkce "f", tzn. JSValue (příklad type inference). No, fyzicky...fyzicky v podstatě ta proměnná neexistuje.... "let" je definice. Jako v matematice. V podstatě kdekoliv pak použiješ v kódu "result", tak se místo toho vloží "f vstup" (kvůli optimalizaci je to malinko jinak, ale to je podstata).
Citace
b) of dela co? zjistuje datove typy promenne nebo hodnoty? Podle ceho, odkud se ta informace bere?
"case .... of" je normální "case" jako z Javy, C apod. Ty řádký pod tím je tzv. Pattern match na hodnoty, které to může nabývat. "JSBool b" říká: je to varianta JSBool a do proměnné "b" dej ten parametr té varianty (tzn. true nebo false)

Citace
c) kdyz funkci f spustim dvakrat a vysledky nactu do result1 (None) a result2 (Text), jaky datovy typ bude mit promenne result1 a result2 a co bude vysledkem?
Výsledkem funkce f je vždycky hodnota typu JSValue. Na tu je potřeba udělat ten pattern match a na základě toho se dopídit k tomu, kterou variantu jsi dostal. Já zkusím kód v nějakým pseudo-C, který v zásadě dělá to samý (ale hrozně ošklivě a z hlavy):

Kód: [Vybrat]
enum TType = { JSBool, JSText, JSNone}
struct JSValue {
  TType tag;
  union {
     bool boolVal;
     String stringVal;
  }val;
}
JSValue f(String vstup) {
   struct JSValue result;
   if (vstup == "true") {
       result.tag = JSBool;
       result.boolVal = true;
   } else ...
   return result;
}

int main() {
   JSValue result = f("true");
   switch (result.tag) {
      case JSBool:
         bool b = result.val.boolval;
         if (b) printf("Dostali jsme true...");
         break;
      case...
   }
}
Tímhle způsobem můžeš snadno vracet hodnoty různých typů i v C. Ale výhoda jazyků, které přímo součtové typy podporují, je samozřejmě výrazně jednodušší syntaxe a hlavně kontrola jazyka, že jsi třeba nějakou variantu nezapomněl ošetřit, že jsi nezapomněl nastavit ten result.val, že jsi tam opravdu dal správný typ atd.. Popravdě, co mě na většině jazycích štve je právě absence součtových typů, dost výrazným způsobem to usnadní práci a zvýší bezpečnost programu.

Takže už ti začínám rozumět. Je to přesně o tom, co jsem tu povídal na začátku o omezeném (bez urážky) myšlení statických programátorů, kteří se nedokáží dívat na program jinak než přes proměnné. Ty stále řešíš datový typ proměnné, nikoliv hodnoty, datový typ hodnoty je pro tebe jen varianta dat. 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.

andy

Re:Problémy s JavaScript v praxi
« Odpověď #524 kdy: 10. 10. 2018, 08:20:02 »
Citace
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é....
Citace
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).

Citace
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:
Kód: [Vybrat]
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....