Troy Hunt představil Have I Been Pwned 2.0, tj. nový vylepšený web služby, kde si uživatelé mohou zkontrolovat, zda se jejich hesla a osobní údaje neobjevili v únicích dat a případně se nechat na další úniky upozorňovat.
Microsoft představil open source textový editor Edit bežící v terminálu. Zdrojové kódy jsou k dispozici na GitHubu pod licencí MIT.
V Seattlu a také online probíhá konference Microsoft Build 2025. Microsoft představuje své novinky. Windows Subsystem for Linux je nově open source. Zdrojové kódy jsou k dispozici na GitHubu pod licencí MIT.
Z příspěvku Turris Sentinel – co přinesl rok 2024 na blogu CZ.NIC: "Za poslední rok (únor 2024 – únor 2025) jsme zachytili 8,3 miliardy incidentů a to z 232 zemí a z jejich závislých území. Tyto útoky přišly od 6,2 milionu útočníků (respektive unikátních adres). SMTP minipot je stále nejlákavější pastí, zhruba 79 % útoků bylo směřováno na tento minipot, 16 % útoků směřovalo na minipot Telnet, 3 % útoků směřovaly na minipot HTTP a 2 % na minipot FTP. Dále jsme zaznamenali 3,2 milionu unikátních hesel a 318 tisíc unikátních loginů, které útočníci zkoušeli."
Byla vydána (Mastodon, 𝕏) nová verze 3.0.4 svobodné aplikace pro úpravu a vytváření rastrové grafiky GIMP (GNU Image Manipulation Program). Přehled novinek v oznámení o vydání a v souboru NEWS na GitLabu. Nový GIMP je již k dispozici také na Flathubu.
Byla vydána nová stabilní verze 7.4 webového prohlížeče Vivaldi (Wikipedie). Postavena je na Chromiu 136. Přehled novinek i s náhledy v příspěvku na blogu.
Spolek vpsFree.cz vydal statistiky týkající se distribucí nasazených na serverech členů. V dlouhodobém pohledu je zřejmé, že většina uživatelů z původního CentOS přechází na Rocky Linux. Pozoruhodný je také nárůst obliby distribuce NixOS, která dnes zaujímá třetí místo po Debianu a Ubuntu.
Google minulý týden představil Material 3 Expressive, tj. novou verzi svého designového jazyka Material Design pro Android 16 a Wear OS 6.
Byl vydán Debian 12.11, tj. jedenáctá opravná verze Debianu 12 s kódovým názvem Bookworm. Řešeny jsou především bezpečnostní problémy, ale také několik vážných chyb. Instalační média Debianu 12 lze samozřejmě nadále k instalaci používat. Po instalaci stačí systém aktualizovat.
Makepad dospěl do verze 1.0 (𝕏). Jedná se o multiplatformní open source UI framework pro Rust napsaný v Rustu.
Budeme se věnovat pouze tomu, jak se instance „tříd“ chovají (metody), nikoli tomu jak „vypadají“ (položky struktur). To druhé bylo již v minulosti probíráno a možná se podrobněji objeví jako některé z dalších témat. Poznamenejme, že v Go jsou navíc definice „rozložení“ obsahu typu a popis jeho chování, ortogonální koncepty – lze je studovat i navrhovat (téměř) nezávisle na sobě. Výhradu slovem „téměř“ ponechejme sémantice typu – často je prostě význam (pro programátora) oněch dvou tváří typu spolu provázán – i když o tom kompilátoru nic neříkáme. Příklady jsou, pro lepší přiblížení se stávajícím programátorům v jiných jazycích, „opřeny“ o strukturované typy, rád bych připomenul, že v Go lze metody definovat i pro další, např. číselné typy (pojmenované).
V příkladech si prosím v řetězcových literálech místo \x25 představte znak procenta (%). Je to jen způsob jak obejít chybu 1770.
Budeme implementovat jednoduché OOP zadání: Chceme čistě abstraktní základní třídu a napsat její různé konkrétní implementace. Jak vidno, z pohledu (zjednodušené) OOP klasiky, všechny metody „třídy“ budou (muset být) virtuální.
package main import ( "fmt" ) type Base interface { M() } type T struct { i int } func (t *T) M() { fmt.Printf("ř.16: \x25#v\n", t) } type U struct { s string } func (u *U) M() { fmt.Printf("ř.24: \x25#v\n", u) } func main() { var t, u Base = &T{42}, &U{"foo"} t.M() u.M() }
Výstup
ř.16: &main.T{i:42} ř.24: &main.U{s:„foo“}
Na ř.7 definujeme (veřejné – s velkým písmenem na začátku) rozhraní a na ř.8 deklarujeme jeho jedinou metodou M. Metody veřejného rozhraní, které má být možné implementovat i v jiných modulech, musí být také veřejné, opět tedy s velkým písmenem na začátku. Celá definice rozhraní Base je v tomto případě sémanticky shodná s definicí abstraktní třídy v jiném typickém OOP jazyku.
Na ř.11 a 19 definujeme typy, které na ř.15 a 23 implementují všechny (jednu) metodu/y rozhraní Base. Díky tomu je zde sémantika shodná s „klasickým“ popisem tříd, která dědí z/jsou v typové hierarchii potomkem „třídy“ Base. Jen zde, v typickém Go OOP duchu, u typů implementujících rozhraní Base (čti např. „extends Base“), nemusíme tento fakt oznamovat. Kompilátor se pouze při typové kontrole na ř.28 ujistí, že typy T a U implementují Base a lze je tedy přiřadit do proměnných 't' a 'u'.
Na ř.29 a 30 už jen zavoláme metodu M instancí 't' a 'u' a na výstupu programu si ověříme, že vše proběhne dle předpokladu.
Rozhraní v Go mají klasickou OOP dědičnost (úplnou a vícenásobnou), viz též poslední část specifikace. Pokud je někdo zvyklý uvažovat v třídách/hierarchii tříd a potřebuje pouze virtuální metody (situace velmi blízká Javě), může je v Go nahradit pomocí rozhraní docela snadno a největší rozdíl je „záměna“ klíčových slov class vs interface, v sémantice je shoda podle mě úplná. Go programátor jen nebude vůbec mluvit o třídách, takže si s „klasickým“ OOP programátorem chvilku nebudou rozumět – i když oba vlastně budou v tomto případě dělat totéž.
Neboli „Don't repeat yourself“. Na ř.16 a 24 příkladu 1 děláme vlastně totéž. Jeden příkaz na aplikaci principu DRY asi nestačí, ale teď jde jen o schémata přístupu a řešení. Výpis (pomocný/ladící) instance, s rozlišením jak typu tak obsahu je často používaný pomocník. Nebyl by problém si napsat zcela ne-OOP funkci, která – díky Go reflection (Javaisté vědí, C++ RTTI by nám také ale v tomto případě také stačilo) – vypíše takové informace. Proč si ale zaplevelovat jmenný prostor, když to může být metoda, že? Čeho ale metoda? Rozhraní Base? Jistě by to tak být mohlo, ale to bychom si nic nového neukázali. Prostě by k metodě Base.M přibyla nějaká metoda Base.Show a tu bychom museli dvakrát implementovat pro typy T a U (a všechny další typy implementující Base). Napsat tohoto pomocníka jako statické metody T a U také moc nepomůže, opět bychom se dvakrát téměř opakovali. Nyní nastává vhodná příležitost pro Go styl dědičnosti. Řekněme, že pomocná metoda bude jen dočasná/ladící a neveřejná (to není podmínkou). Z pohledu „tříd“ T a U dědí z Base, z pohledu Go T a U implementuje Base a dědí z 'base' (zvolené jméno 'base' není ničím podstatné).
package main import ( "fmt" "path" "runtime" ) type Base interface { M() } type base struct{} func (b base) show(me interface{}) { pc, file, line, ok := runtime.Caller(1) if !ok { panic(":-/") } fmt.Printf("\x25#x \x25s.\x25d: \x25#v\n", pc, path.Base(file), line, me) } type T struct { base i int } func (t *T) M() { t.show(t) } type U struct { base s string } func (u *U) M() { u.show(u) } func main() { var t, u Base = &T{i: 42}, &U{s: "foo"} t.M() u.M() }
Výstup:
0x400deb prog.go.30: &main.T{base:main.base{}, i:42} 0x400e3b prog.go.39: &main.U{base:main.base{}, s:„foo“}
Na ř.13 definujeme typ 'base' a na ř.15 jeho metodu 'show'. Na ř.25 a 34 uvádíme 'base' jako položku struktur typu T a U. Pole bez jména, pouze s názvem typu je v Go struktuře (myšleno klíčové slovo struct) způsob, jak zdědit obsah takto děděného typu a současně i jeho metody. Alternativně by šlo totéž i s ukazatelem (viz diskuzi „“anonymous field“), ale to nyní pomineme. Oproti OOP klasice ale přijímač (obvykle prostě ukazatel) metody takového předka má typ pouze onoho předka, nikoli typu, který jej dědí. Proto na ř.30 a 39 metodě show předáváme i přijímač metody M.
Další „standardní situací“ v OOP je případ, kdy dědíme téměř všechno od předchůdce až na jednu nebo jen několik málo metod. Ta/ty pak nějak modifikují chování zděděné/ých metod/y Zcela schematicky to v Go lze řešit takto:
package main type base struct{} func (b *base) m1() { println("m1()") } func (b *base) m2() { println("m2()") } type successor struct { base } func (o *successor) m2() { println("taky m2(), ale jinak") } func main() { b, s := &base{}, &successor{} println("typ base") b.m1() b.m2() println("typ successor") s.m1() s.m2() }
typ base m1() m2() typ successor m1() taky m2(), ale jinak
Na ř.3 definujeme základní typ/předchůdce 'base', na ř.5 a 9 jeho metody m1 a m2. Na ř.14 definujeme odvozený typ/následníka 'successor' a na ř.15 dědíme vše z předchůdce 'base'. Na ř.18 předefinováváme metodu m2, samozřejmě pouze pro typ 'successor'. Z výstupu programu vidno, že dle očekávání typ následníka podědil metodu m1, ale používá vlastní metodu m2. Mimochodem, pokud bychom v této 'overriden' metodě potřebovali volat metodu m2 předchůdce, (jako v Javě pomocí super), napsali bychom třeba před ř.19 „o.base.m2()“. Možná si to budete chtít vyzkoušet v Go playgroundu. U všech příkladů stačí klepnout na odkaz „Upravit/Spustit“.
Dnešní díl byl určen hlavně programátorům, kteří jsou navyklí na implementaci OOP mechanismů ve stylu C++ a/nebo Javy. Go je OOP jazyk, ale právě jmenovaní mají často při prvním pohledu na Go pocit, že jsou ztraceni, protože v Go nenacházejí svoje oblíbené, protože skoro neustále používané, třídy a jejich dědičnost. Pokusili jsme se ukázat, že většinu dobrého, co lze v OOP najít, Go implementuje, jen tak trochu jinak. Jestli možná v něčem i snad o trochu lépe nechť posoudí laskavý čtenář sám.
Jan Mercl, autor textu, pracuje v Laboratořích CZ.NIC jako programátor pro výzkum a vývoj.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
def add(a:Int, b:Int) = a + bdynamický python:
def add(a, b): return a + bdynamický scheme:
(define (add a b) (+ a b))statický F#:
let add a b = a + bna scale mi vadí hlavne ten balast zbytočné zátvorky a aj zložené zátvorky označujúce začiatok a koniec bloku, ktoré len zneprehľadňujú kód, tektiež type inference v scale nefunguje najoptimálnejšie pretože u argumentov funkcií musím tak či tak zadávať názvy typov, pritom by si ich mohol prekladač automaticky odvodiť.
(1 to 100).map{i => i * i}.filter{i => (i % 2) == 0} psát třeba (1 to 100) .map i => i * i .filter i => (i % 2) == 0nebo jak si to vlastně představuješ? U argumentů funkcí typy dovodit nejdou, protože při překladu dané funkce nevíš, ze kterých všech modulů bude zavolaná. Nebrání to ovšem dělat generické funkce
scala> def joinStrings[T](x: T, y: T) = {x.toString + y.toString} joinStrings: [T](x: T, y: T)java.lang.String a tady už inference typů argumentů funguje, místo scala> joinStrings[Int](1, 2) klidně stačí napsat scala> joinStrings(1, 2) res0: java.lang.String = 12Jinak jo, staticky typovaný jazyk může působit úsporně :)
let add a b = a + bak funkcii add priradím 2 parametre rovnakého typu tak si z nich prekladač automaticky odvodí typy argumentov... ak ale jednému argumentu priradím trebárs string a druhému trebárs integer tak prekladač vyhodí chybu. rovnako prekladač vyhodí chybu aj ked 2x zavolám funkciu v vždy s iným typom argumentov.
jazyk se statickým typováním vždycky bude ukecanýrekl clovek, ktery v zivote neslysel o Haskellu...
protože je to takové C++ done right.To mi připomíná Linusovu hlášku o tom, že SVN je "CVS done right" ...
Btw, "CVS dnone right" není Linusova hláška, ale přímo moto Subversion. A je to dost přesné, SVN je oproti CVS poklad, ale v porovnání s Gitem neobstojí. Proto se tomu Linus posmíval."Posmíval" není asi to pravé. Ta citace zní: if you start with that kind of slogan, there's nowhere you can go. There is no way to do CVS right. Což je přesně jak já to vidím s C++, není jak ho "udělat dobře", špatné jsou už ty koncepty za tím. Nejlepší je se na to kompletně vykašlat a udělat to celé jinak, nejlépe přesně naopak. (Analogicky k Take CVS as an example of what not to do; if in doubt, make the exact opposite decision.)
zrovna to D je perfektní jazykZa prvé nic takového neexistuje - existují jen jazyky které jsou nepoužitelné, a méně nepoužitelné... a za druhé, který případ nastal z těchto dvou se uvidí až tak za 10 let, jak u Go, tak u D. (U C++ už se vidí :P )
Což je přesně jak já to vidím s C++, není jak ho "udělat dobře", špatné jsou už ty koncepty za tím.to ze necemu nerozumis neznamena ze je to spatne
to ze necemu nerozumis neznamena ze je to spatneTo samozřejmě ne, ale oba jevy najednou nastat můžou. A to je právě případ C++.
mám jednu otázku na autora článku:
panic("<img alt="" class="emo" src="/images/smile/smutek.gif" />")
ako prekladač jazyka zistí kde končí reťazec keď aj vo vnúti reťazca sa používa znak ukončenia reťazca bez escapovania?