Společnost OpenAI představila AI modely o3 a o4-mini (𝕏).
Canonical vydal Ubuntu 25.04 Plucky Puffin. Přehled novinek v poznámkách k vydání. Jedná se o průběžné vydání s podporou 9 měsíců, tj. do ledna 2026.
Desktopové prostředí LXQt (Lightweight Qt Desktop Environment, Wikipedie) vzniklé sloučením projektů Razor-qt a LXDE bylo vydáno ve verzi 2.2.0. Přehled novinek v poznámkách k vydání.
Vývojáři KDE oznámili vydání balíku aplikací KDE Gear 25.04. Přehled novinek i s náhledy a videi v oficiálním oznámení.
Nová čísla časopisů od nakladatelství Raspberry Pi zdarma ke čtení: Raspberry Pi Official Magazine 152 (pdf) a Hello World 26 (pdf).
Zajímá vás Open Build Service (OBS) a vývoj linuxového jádra pro IBM Mainframe? V rámci Informatických večerů na FIT ČVUT v Praze proběhne v pondělí 28. dubna přednáška Linux on Z Development s podtitulem „From packaging in the openSUSE Build Service until Linux Kernel Development at IBM“. Přednáška proběhne v anglickém jazyce. Vstup je zdarma a bez předchozí registrace.
Vyšla nová verze XMPP (Jabber) klienta Dino. Mezi novinky patří vylepšený přenos souborů (XEP-0447: Stateless file sharing), přepracované dialogy a další. Vyzkoušet lze i na (linuxových) telefonech.
Vyšla nová verze XMPP (Jabber) klienta Gajim, která přidává podporu nového způsobu synchronizace informací o přečtení zpráv (XEP-0490: Message Displayed Synchronization jako nástupce XEP-0333: Displayed Markers), dále centrální stránku pro přehled všech aktivit (Activity feed) nebo vylepšení přepínání mezi více účty. Přehled dalších změn je k dispozici na oficiálních stránkách.
Mobilní operátoři společně chrání zákazníky proti podvodným hovorům v pevné i mobilní síti. Vodafone, T-Mobile a O2 vybudovali proti takzvanému spoofingu vzájemně propojené zabezpečení. Podvodníkům zabraňuje schovávat se za čísla jiných lidí nebo institucí, jako jsou banky a policie.
Na minihoneypotech Turrisu se objevil poměrně rozsáhlý útok na FTP servery. Je zvláštní tím, že probíhá z mnoha IP adres zároveň, je relativně pomalý a k pokusům o přihlášení používá objemný slovník. Útok probíhá z rozsahu IP adres 45.78.4.1-45.78.7.254. Rozsah je registrován na společnost IT7 Networks Inc., která poskytuje hostingové služby. Mezi zasláním každé kombinace jména hesla může oběhnout od několika, do nižších desítek sekund
… více »Na druhé straně každá ukázka je v době odevzdání (Go se již mění pomaleji, ale ke změnám stále dochází) kompletní program, který je možno přeložit (pokud neukazuje úmyslně nepřeložitelnou chybu). Novinkou, přinejmenším snad v článcích o Go na AbcLinuxu, je možnost si na Go doopravdy „sáhnout“ a to i bez instalace jeho distribuce. Na domácí stránce Go je už nějaký čas tzv. Go playground. V něm je možné, v rámci některých pochopitelných omezení, zadávat a upravovat zdrojový kód v Go, následně jej nechat na vzdáleném serveru přeložit/sestavit a v případě úspěchu i provést. Pokud výsledný program úspěšně doběhne ve svém časovém limitu, zobrazí Go playground i vše, co zapsal program napsal do svého standardního výstupu.
Veškeré ukázky kódu jsou následovány odkazem, který příklad otevře v Go playgroundu. Tam je pak možné ukázku/program upravovat a nakonec klepnutím na tlačítko „COMPILE & RUN“ (nebo stiskem shift-enter) zkusit provést. Neověřoval jsem, ale předpokládám, že povolený Javascript bude nejspíše nutný. Pokud si „pískoviště“ zkusíte, může se Vám stát, že některá z dnešních ukázek bude hlásit timeout. Obvykle postačí ji v takovém případě zkusit provést ještě jednou, ale úspěch může záležet na zcela vnějších faktorech (možná dle okamžitého zatížení některého Google serveru), takže nic se v tomto směru nedá slíbit. Z diskuzí jinde pochází ještě jedna rada – někdy stačí v případě potíží (timeout provádění) jen pozměnit whitespace programu a tím ovlivnit použití kompilační cache playgroundu, která je v současné implementaci podezřelá, že je někdy příčinou problému.
V době odevzdávání článku se navíc ještě našla nemilá chyba (nahlášená), která se projevuje ve Firefoxu a (zatím) znemožňuje použití Go playground z FF. Doufejme, že chyba bude do doby vyjití článku opravena.
package main import "fmt" func f(x int, c chan string) { defer func() { if e := recover(); e != nil { c <- fmt.Sprintf("f(%d): %s", x, e) } }() if x == 2 { panic("x == 2 není podporováno") } c <- fmt.Sprintf("f(%d) == %d", x, 2*x) } func main() { c := make(chan string) for i := 1; i <= 2; i++ { go f(i, c) defer fmt.Printf("(%d) %s\n", i, <-c) } }
Výstup:
(2) f(2): x == 2 není podporováno (1) f(1) == 2
Klíčové slovo go spustí provádění dané funkce/funkčního literálu v nové gorutině (ř.22). Gorutina nemůže volajícímu přímo nic vrátit (ve smyslu funkční hodnoty), volající navíc pokračuje bez čekání na ukončení gorutiny. Pokud chceme s paralelně prováděnou gorutinou komunikovat, je standardním Go idiomem použití komunikačních kanálů. V ukázce je kanál vytvořen na ř.20, funkce f (ř.5) standardně tímto kanálem odpovídá, gorutina jej získala jako argument volání. Na ř.16 odpovídá normálně a na ř.8 při výjimce (k té za chvíli).
Na ř.23 hlavní fuknce programu vypisuje výsledky vrácené gorutinami kanálem. V tomto případě pomocí odloženého příkazu klíčovým slovem defer (k němu opět za moment). Důležité je si uvědomit, že pokud funkce main() programu spustí libovolný počet gorutin, ale nijak nepočká na jejich provedení (tj. kdybychom třeba zakomentovali ř.23), tak celý program skončí svoje provádění dříve než budou mít další/jiné gorutiny příležitost dokončit svoji práci nebo ji dokonce vůbec zahájit. Možná se to bude někomu zdát jako zbytečná poznámka, ale v diskuzích na golang-nuts je tato chyba v dotazech začínajících programátorů v Go vidět dost často. Podobně chybné, jen opačně, je na konci main kvůli tomu např. psát nějaké zpoždění odhadovaného počtu sekund (třeba pomocí time.Sleep). Pokud je pro správnou činnost programu třeba nechat tu či onu gorutinu dokončit práci, je nutné se k takové události synchronizovat. Čekáním na příchod signálu/hlášení/výsledku kanálem je automaticky takovou synchronizací.
V dané ukázce by bylo možné čekat na známý počet hlášení (tj. 2) třeba v dalším cyklu. Na ř.23 využíváme pro automatické spárování potřebného počtu synchronizací příkaz defer. Jeho sémantika je jednoduchá – defer příkaz, kterým musí být volání funkce – způsobí zřetězení volání takové funkce těsně před návratem z funkce, ve které provádíme příkaz defer. Defer je možné vyvolávat opakovaně, odložené volání se koná v LIFO pořadí. Teprve až poté, co je celý tento „lokální zásobník“ vyprázdněn, dojde k návratu z funkce. V našem případě z funkce main, dojde proto k ukončení celého programu, leč řádně, až po ukončení práce obou (instancí) gorutiny f.
Právě popsaný mechanismus defer, zvláště pak skutečnost, že odložené příkazy se provedou ještě před návratem z dané funkce, se využívají pro ošetřování výjimek. Na ř.7 vidíme volání zabudované funkce recover, v rámci odloženého volání funkčního literálu na ř.6. Recover() vrací za běžných okolností nil. Pokud bylo normální provádění funkce ukončeno výjimkou, pak recover, použitý v odloženě vyvolané funkci, vrací aktuální chybový objekt. Protože recover voláme odloženě (ř.6), tak v případě výjimky, během provádění ř.8, „vidíme“ v uzávěře odložené funkce ještě platné parametry funkce f. Proto můžeme bez obav na ř.8 poslat kanálem c chybové hlášení. Kanál typu string je zde použit jenom pro zjednodušení příkladu, v main() se o obsah hlášení nijak nezajímáme, jen je vypíšeme.
Na ř.12 uměle vytváříme chybu, představte si pod tím obecný případ neplatného argumentu/stavu/jiné chyby. Bylo by zde možné opět přímo poslat něco do kanálu c a provést return. Pokud už ale máme ošetřeno pomocí defer zachytávání výjimek, je pohodlnější toto zachycení vyvolat jednoduše pomocí panic. Navíc takto zachytíme i neošetřenou výjimku z libovolné nižší úrovně provádění (vizte příklad 2). Argumentem panic je chybový objekt. Tato zabudovaná funkce je generická, tj. chybový objekt může být jakéhokoli typu. Pro změnu chování funkce dle typu chybového objektu vizte následující příklad.
package main import ( "fmt" "os" ) func div(a, b int) int { if b == -2 || b&0xff == 0xaa { panic(fmt.Errorf("nepovolený argument %d", b)) } return a / b } var p *int func f(x int) (y *int, err os.Error) { y = new(int) defer func() { if e := recover(); e != nil { y = nil err = e.(os.Error) } }() switch x { case -1: *y = *p case 2: panic("TODO:f(2)") default: *y = div(0x12345678, x) } return } func main() { for i := -3; i <= 3; i++ { v, err := f(i) if err != nil { fmt.Printf("f(%d) – %s\n", i, err) continue } fmt.Printf("f(%d) == %d\n", i, *v) } }
Výstup:
f(-3) == -101806632 f(-2) – nepovolený argument -2 f(-1) – runtime error: invalid memory address or nil pointer dereference f(0) – runtime error: integer divide by zero f(1) == 305419896 panic: TODO:f(2) [recovered] panic: interface conversion: string is not os.Error: missing method String runtime.panic+0xac /tmp/sandbox/go/src/pkg/runtime/proc.c:1060 runtime.panic(0x45a1f0, 0xf84001fd90) itab+0x101 /tmp/sandbox/go/src/pkg/runtime/iface.c:134 itab(0x4547b0, 0x43ec38, 0x0, 0xf84003e048, 0x1, …) runtime.ifaceE2I+0xe3 /tmp/sandbox/go/src/pkg/runtime/iface.c:473 runtime.ifaceE2I(0x4547b0, 0x43ec38, 0xf840001320, 0x2b42b055cdf8, 0xf84000b780, …) runtime.assertE2I+0x43 /tmp/sandbox/go/src/pkg/runtime/iface.c:488 runtime.assertE2I(0x4547b0, 0x43ec38, 0xf840001320, 0xf84000b7b0, 0xf840001320, …) main._func_001+0x75 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:24 main._func_001(0xf8400000b0, 0xf840001330, 0x401f4f, 0x2b42b055c100, 0x2b42b055cfb8, …) ----- stack segment boundary ----- runtime.panic+0xf6 /tmp/sandbox/go/src/pkg/runtime/proc.c:1041 runtime.panic(0x43ec38, 0xf840001320) main.f+0x114 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:32 main.f(0x2, 0x642528660000000c, 0xf84000c740, 0x200000002, 0x12, …) main.main+0x39 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:41 main.main() runtime.mainstart+0xf /tmp/sandbox/go/src/pkg/runtime/amd64/asm.s:77 runtime.mainstart() runtime.goexit /tmp/sandbox/go/src/pkg/runtime/proc.c:178 runtime.goexit() ----- goroutine created by ----- _rt0_amd64+0x8e /tmp/sandbox/go/src/pkg/runtime/amd64/asm.s:64
Tato ukázka rozvíjí příklad 1 v oblasti výjimek. Na ř.10 vyvoláváme výjimku ve funkci div, zachytává se ale o úroveň výše, na ř.22 ve funkci f. Na ř.13 budeme občas dělit nulou bez kontroly, odchycení je ale stejné. Funkce f (ř.18) je modelová funkce vracející ukazatel a příznak chyby. Na ř.19 je častý případ, kdy na počátku provádění funkce vytváříme nový objekt (alokace). V případě zachycení výjimky chceme místo ukazatele na objekt zajistit (bezpečnější) vrácení hodnoty nil, to zajišťuje ř.23. Na ř.30 občas způsobíme další typ výjimky – dereferenci nil ukazatele. Na ř.32 opět občas „zpanikaříme“, tentokrát úmyslně s chybovým objektem odlišného typu, v tomto případě string. Na ř.24 totiž provádíme run time typovou kontrolu (type assertion) chybového objektu e. Pro typ string tato kontrola selže, způsobí opět další výjimku, která už ukončí běh celého programu. To je modelové schéma, kdy potřebujeme rozlišit výjimky, které vracíme volajícímu jako chybu (s nadějí na zotavení programu) a situace, kdy pokračovat nelze – zde modelově vstupujeme do části kódu, který je teprve třeba napsat. Proto nám ve výstupu neprojdou všechny hodnoty cyklu z ř.40 a pro i == 2 program skončí neošetřenou chybou a tedy výpisem zásobníku.
Vracení chyby typu os.Error je záležitost víceméně (ustáleného) zvyku. Na druhé straně os.Error není statický typ, je to rozhraní, takže v případě potřeby jemnějšího rozlišení kategorií chyb nebo když je nutné různé chyby doplnit o přidané informace – nám nic nebrání použít uživatelsky definovaný typ. Stačí bude‑li implementovat jedinou metodu rozhraní os.Error – String(), tj. převod na řetězec.
package main type bad interface{} func (b bad) foo() { println("Hi from bad") } type ok interface { foo() } type bar struct{} func (b bar) foo() { println("Hi from bar") } func main() { var iface bad iface.foo() bar{}.foo() }
Výstup:
prog.go:5: invalid receiver type bad prog.go:21: iface.foo undefined (type bad has no field or method foo)
Všechny pojmenované typy v Go mohou mít k sobě přidružené metody. Jednou z „optických“ ne ortogonalit tohoto pravidla je to, že typ rozhraní může metody pouze deklarovat avšak nikoli implementovat. Pro všechny ostatní typy je tomu právě naopak. Příklad 3 na ř.5 implementuje metodu rozhraní bad (ř.3) a to nám kompilátor nedovolí. Jako cvičení si lze vyzkoušet uvést tento příklad do přeložitelného stavu.
Ještě jedna (po)drobnost omezuje typy, ke kterým je možné definovat metody. Typ (přijímače metody) může být sám o sobě ukazatelem (ukazatelovým typem), ale jím odkazovaný typ už ukazatelem být nesmí. Vizte též specifikaci.
Říká se, vcelku oprávněně, že je dobré, když jedna sémantická konstrukce je v programovacím jazyce vyjádřitelná jenom jedním způsobem. Podíváme se nyní na tři verze skoro stejného schématu. Úmyslně je v Go napíšeme různými způsoby. Myslím ale, že v žádném příkrém rozporu s první větou tohoto odstavce nebudeme. Různé implementace v tomto případě přinášejí ne zcela shodnou sémantiku – byť rozdíly jsou, dle úhlu pohledu, spíše jen v menších detailech. Každá implementace se ale hodí pro trochu jinou situaci. Představme si třeba rozdíl mezi situací kdy jsme odkázáni na použití existující funkce/metody třetích stran vs. stav, kdy si „operátor“ můžeme/chceme a/nebo musíme napsat sami.
Modelové schéma v našem případě je nějaká abstraktní operace nad adresářovým stromem souborového systému, přesněji řečeno provedení nějaké činnosti nad jednotlivými adresáři stromu. Kdo chce, může v tom vidět i Visitor pattern. Ve standardní knihovně existuje funkce filepath.Walk, kterou se zde inspirujeme. Pro jednoduchost degenerujeme procházení stromu na návštěvu pouze jeho kořene a modelově chceme jedním mechanismem získávat dvě různé informace – počet souborů v adresáři nebo jejich celkovou velikost. Další možnosti konkrétní „operace“ (třeba v duchu příkazů cat, echo, mv, …) si jistě lze domyslet.
package main type visitor func(string) func files(dir string) { println(dir, "obsahuje celkem 42 souborů") } func bytes(dir string) { println(dir, "obsahuje celkem 524287 bajtů") } func walk(path string, v visitor) { v(path) } func main() { walk("/", files) walk("/bin", bytes) }
Výstup:
/ obsahuje celkem 42 souborů /bin obsahuje celkem 524287 bajtů
Příklad 4a je, volně řečeno, ve stylu Cčka. Bez použití (možnosti použití) rozhraní nebo třeba virtuálních metod objektů je použití funkčního typu pro „operaci“ jednoduchým řešením – a v případě C víceméně také jediným. Pomíjíme zde nepoměrně složitější možnosti, které přináší třeba GObject, protože to už nehovoříme o jazyku, ale o jeho knihovně. Ostatně nějaký mechanismus jako vtable a vcall jde s konečným úsilím implementovat snad vždy i v ne OOP programovacím jazyku.
Řešení (schématu) je zcela nekomplikované, jediná deklarace (funkčního typu visitor na ř.3), použitá v definici funkce walk na ř.13, je zde „nutná“ navíc jen v rámci snad dobrého stylu. Typ parametru 'v' by mohl být definován i typovým literálem – lze si ověřit na „pískovišti“ (nezkusíte si to?).
package main type visitor interface { visit() } type files string func (dir files) visit() { println(dir, "obsahuje celkem 42 souborů") } type bytes string func (dir bytes) visit() { println(dir, "obsahuje celkem 524287 bajtů") } func walk(path visitor) { path.visit() } func main() { walk(files("/")) walk(bytes("/bin")) }
Výstup:
/ obsahuje celkem 42 souborů /bin obsahuje celkem 524287 bajtů
Příklad 4b představuje obvyklý přístup, který by se asi dal nazvat Go idiomatický. Ostatně toto řešení je (schématicky) identické implementaci svého vzoru (vizte filepath.Walk a rozhraní filepath.Visitor). Na ř.3 deklarujeme rozhraní. Na ř.7 a 13 deklarujeme pojmenované typy, které toto rozhraní implementují (ř.9 a 15). Na ř.24 a 25 provádíme konverzi literálu typu string na typ files resp. bytes a tím volíme „operaci“, kterou od funkce walk požadujeme. Konverze je zde použita jen pro zkratku příkladu, jistě si snadno domyslíte obecnější případ entit různých typů.
package main type visitor func(string) func (v visitor) visit(dir string) { v(dir) } func (v visitor) walk(path string) { v.visit(path) } var files visitor = func(dir string) { println(dir, "obsahuje celkem 42 souborů") } var bytes visitor = func(dir string) { println(dir, "obsahuje celkem 524287 bajtů") } func main() { files.walk("/") bytes.walk("/bin") }
Výstup:
/ obsahuje celkem 42 souborů /bin obsahuje celkem 524287 bajtů
V příkladu 3 jsme si připomenuli, že metody může implementovat každý (pojmenovaný) typ, který není rozhraní. V příkladu 4c využijeme jeden, možná trochu překvapivý, důsledek tohoto pravidla. V Go můžou mít funkce metody, korektně řečeno – metody lze implementovat i pro (pojmenovaný) funkční typ. Autor nezná dostatečně dobře dostatečný počet jiných programovacích jazyků aby mohl posloužit příkladem „stejně/podobně jako jako v jazyce X“, jen odhaduje, že něco podobného by možná šlo „spáchat“ přinejmenším v Javascriptu?
Tato implementace nejvíce připomíná styl funkčních jazyků. Na ř.3 deklarujeme funkční typ visitor. Mimochodem deklarace je zcela stejná jako „C“ verzi v příkladu 4a. Na ř.5 a 9 definujeme metody typu visitor. Na ř.13 a 17 deklarujeme proměnné files a bytes typu visitor, v obou případech s inicializátorem pomocí funkčního literálu. Toto je implementační detail, mohli bychom definovat obyčejné funkce (s podpisem shodným s typem visitor), pak by ovšem přístup k jejich metodám byl možný pouze po konverzi ve stylu:
func files(dir string) { println(dir, "obsahuje celkem 42 souborů") } //... visitor(files).walk("/")
Mírně složitější verze s funkčním inicializátorem, použitá v příkladu 4c, se vyplatí, pokud budeme takovou funkci, tedy přesněji metody takového funkčního typu, volat častěji, protože taková volání jsou potom krátká a dobře čitelná jak vidno na ř.22 a 23.
Příklad 4c způsobuje v této zkratkovité podobě kontroverzní reakce – minimálně u kolegy, který Go nepoužívá, ale je ochotný tyto články před odevzdáním číst a kontrolovat. Podstatně podrobněji se tomuto „triku“ věnuje část Effective Go – Interface methods, na konci oddílu v diskuzi typu HandlerFunc a jeho metody ServeHTTP. Celý mechanismus popsaný v posledně uvedeném odkazu se reálně používá ve standardní knihovně.
Pokračování by mělo vyjít snad za měsíc. Bude-li mít někdo z čtenářů zvláštní zájem o nějaké téma ke zpracování pak nechť dá prosím vědět s dostatečným předstihem.
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:
y) a kdyby se dal občas vypnout GC a člověk by po sobě uklízel sám, to bych se taky nezlobil, nemluvě o podpoře assembleruTělo Go funkce může být (externě) napsáno v assembleru.
Ano, když něco nesnáším, jde o můj subjektivní názor - to snad není třeba komentovat...
Já často spojuji velké bloky zdrojáků z různých zdrojů a časů a tam přeskok na párovou závorku a letmá kontrola čísla sloupce hodně pomáhá, používám to prakticky denně. A dále - pokud je řádek delší než zobrazený text, pak se tato závorka dostane mimo obrazovku a já pak musím při vizuální kontrole spoléhat na to, že to je dobře odsazené. Jenže pokud se ke mne dostane zdroják, kde jsou mixované tabulátory a mezery a já mám tabulátory nastavené na jinou hodnotu než autor... Prostě python
To ušetření volného řádku nějak nechápu - co přesně se tím ušetří? Možná na malém monitoru, rozlišení.. No a ten dojem, že řádky následující za začátkem bloku do něj nepatří, tak to bude nejspíš ten 'dost subjektivní názor'
No a ten dojem, že řádky následující za začátkem bloku do něj nepatří, tak to bude nejspíš ten 'dost subjektivní názor'No, to jo, ale když vidím tu závorku na novém řádku, působí to nemocně. Jinak ať žije autoformater :)
Pro mě je nemocná ta 'schovaná' a "nepodstatná" závorka, která tak ztrácí část své funkčnosti. Ale určitě souhlasím, že čtení je věc zvyku. Problém je v tom, že ve své práci jsem ten autoformater často já sám.
Tonocí ve zdrojáku se i závorky chytá...
if(true) do();
{
//blok kodu
}
A presne v tuhle chvili by dle meho bylo velmi snadne treba prehlidnout nenapadnou metodu do() a myslet si, ze ten blok patri k podmince (zrovna treba ten pripad, kdy by vyraz v podmince byl delsi nez je sirka monitoru). Je to extrem, ale je to vec, ktera me vadi :) navic ta rozlezlost - ten radek navic me proste irituje :) je takovy chudak opusteny a vypada to, ze se k nicemu nevaze... (v tomto pripade se opravdu nevaze, a pokud bys prehledl do() tak si toho tak lehce nevsimnes)
if (true) do();prip. rovnou
if (true) { do(); }coz dost pomaha, pokud nechcete hledat nahodnou chybu ve ctyri rano pred odevzdanim...
if (neco) { blok; } else prikaz;a pak chtel pred prikaz doplnit ladici vypis, ale zapomnel puvodni prikaz u else dat do bloku, takze vypadl mimo if/else :( Od te doby jsem opatrny, a - kdyz nejsem rozmarny :) - radeji zavorkuju kde co. Taky, pokud treba odnekud kopiruju jen kus kodu a neupravuju cizi projekt, pouzivam formatovani v editoru - pak mam jakz-takz jistotu, ze se v tom da vyznat. Na druhou stranu - treba v jave pisu zavorky na konec, tam je to standard (a NB to tak automaticky formatuji :) ). Naopak MSVS formatuje tak, jak popisuju nahore. Zatim jsem se z toho jeste nezblaznil. Aspon myslim :)
takze v praci asi budes plateny od poctu riadkov, ze?
Pokud někdo formátuje zdroják takto, pak je jen na místě, aby si problémy s tím spojené pěkně odladil. Nepamatuji si ale, že bych při práci někdy viděl něco podobného v takové pozici, že by to znamenalo programátorovu chybu. Samozřejmě, že tam pro lepší čitelnost patří odřádkování a klidně bych uvítal komentář, proč je tam ten extra blok.
Já, když už při své práci více zasahuju do cizího kódu (oprava chyby), tak ho většinou poměrně dost lokálně asimiluju a tuhle (pozor nasleduje subjektivní názor ) chybu formátování okamžitě opravuju, stejně jako závorky na konci řádků, velmi dlouhé řádky (to si okamžitě zvětším okno, případně zmenším písmo), chybějící odřádkování, někdy dokonce absence formátování...
Dělám v týmu, ve kterém převážně vždy dodržujeme několik jednoduchých pravidel. Jedno z nich je primitivní: za if, for, while... se nemá schovávat NIC.
Mini anketa: já mám běžně nastavenou velikost okna tak, že vidím ze zdrojáku 50 řádků po 150 znacích. Kolik máte vy?