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.
Abychom mohli pokračovat dále, je
třeba se naučit něco o typech. Na znalosti typů závisí pak proměnné,
které jsou jedním z nejdůležitějších prvků jazyka. Typový systém D je o
něco jednodušší než ten z jazyka C nebo C++, ale neztrácí nic na síle. Tak,
jdeme na to
Každá hodnota musí mít nějaký typ, který reprezentuje, jak se taková hodnota bude chovat a jak je velká. K tomu se využívají datové typy. Ty si můžeme roztřídit na několik kategorií.
Nejprve se podíváme na základní
(atomické) typy, tzn. ty na
úplně
nejnižší
úrovni. Mezi ty patří celá čísla,
reálná čísla, boolovské hodnoty,
komplexní čísla a znaky. Kromě toho by se dal do této kategorie
zařadit
i typ void
, jakožto "prázdno" - v jazyce se také často
využívá a nemá
žádnou hodnotu.
D je staticky typovaný jazyk. To znamená, že kontrola typů probíhá při kompilaci, ne za běhu. To má za následek, že se různé hodnoty budou mít stále stejný typ, s jakým byly definovány. Takový jazyk je potom obvykle striktnější, ale zase se programátor vyvaruje typovým chybám za běhu.
Základní typy vždy mají nějakou velikost (kromě void
).
Ta se značí v
bitech (popř. bytech). Vyjadřuje, kolik místa v
paměti hodnota určitého
typu zabere. Teď si můžete říct "noj o, ale není to plýtvání, mít typ,
který pobere např. velké číselné hodnoty a místo nevyužít?". Ano,
samozřejmě. Ale jazyk nemá jen jeden číselný typ. Místo toho jich
existuje celá řada, s různými rozsahy hodnot.
Puristé budou protestovat, že "to přece nejsou vůbec celá čísla",
ale
počítejme s tím, že jsou. D definuje několik různě velkých
celočíselných (integrálních) typů, které jsou často analogické s těmi v
jazyce C. Základní, se kterým budeme pracovat, je int
. Int
je zkratka
pro integer. V jazyce C není
jeho velikost definována standardem. V
D ano - int
je vždy 32
bitů velký a zahrnuje jak záporná, tak
kladná čísla.
Pokud jsou třeba jen čísla kladná (nula a větší), tak pro tyto účely je
přítomen typ uint
(v C by se zapsal jako unsigned
int
, tzn.
"bezznaménkový int"). Ten může logicky jít více do kladných hodnot, než
standardní int
, ale je useklý v záporných hodnotách.
Vždy není vhodné pracovat s tak velkými čísly. Proto D poskytuje ještě
dva menší typy (oba mají i své unsigned protějšky, jen s předponou
u
). Těmi jsou short
a byte
.
Typ short
má vždy 16 bitů. Analogicky
typ byte
má velikost přesně jeden byte.
Stejně tak jsou
občas potřeba i větší hodnoty než jen 32 bitů. Ty reprezentují typy
long
(vždy 64 bitů, unsigned verze ulong
) a cent
(vždy 128 bitů,
ucent
pro unsigned, ale tento typ není ještě implementován
a je jen
rezervován pro pozdější užití).
Cčkaři vědí, že hodnoty různých typů se automaticky neinicializují a je
třeba explicitně specifikovat hodnotu. Toto neplatí v případě D.
Všechny integrální typy jsou implicitně 0
.
Občas celá čísla nestačí. Stejně jako pro celá čísla, D poskytuje několik typů s desetinnou čárkou.
Základním typem, se kterým se pracuje, je float
(od floating point).
Float má, analogicky k typu int
velikost 32 bitů (v Cčku
nedefinovaná). Menší neexistuje. 64bitový float
se
jmenuje double
(od "double precision" - dvojitá přesnost; velikost v Cčku logicky není
definována). Poslední typ real
nemá definovanou
velikost.
Představuje největší floating point číslo reprezentovatelné hardwarem
(80 bitů pro x86).
Výchozí hodnota je u těchto typů vždy TYP.nan
.
D má separátní typ bool
, který může reprezentovat vždy
jen 2
hodnoty
(je tudíž v podstatě jedním bitem). Tyto hodnoty se jmenují false
a
true
("pravda" a "nepravda"). Výchozí hodnotou je vždy false
.
Bool
hodnoty jsou implicitně konvertovatelné na jakýkoliv integrální typ
(konverze - viz další lekce). Při konverzi se false
stane
0 a true
1. Klasické aritmetické operátory se na bool hodnotách nepoužívají.
Bitové operátory, AND/OR a ternární operátor se s bool
hodnotami použít
dají.
D má zabudovaná komplexní čísla, která jsou analogická k floating
point
typům. Jedninou změnou je, že mají předponu c
(cfloat
,
cdouble
,
creal
). Protože komplexní čísla se skládají ze dvou
složek, je třeba
nějak reprezentovat tu imaginární složku. K tomu slouží typy ifloat
,
idouble
a ireal
. Výchozí hodnoty komplexních
typů se také liší.
Jsou vždy TYP.nan + TYP.nan * 1.0i
(např. float.nan
+ float.nan *
1.0i
).
Tyto typy jsou zajímavé tím, že jejich velikosti v podstatě kopírují
ty
celých čísel. Znakové typy jsou tři. Jmenují se char
,
wchar
a
dchar
. Všechny jsou integrální a unsigned. Typ char
má velikost 8
bitů (tudíž kopíruje ubyte
). Typ wchar
má
16 bitů (jako ushort
).
A dchar
má 32 bitů (jako uint
). Rozdíl je v
jejich výchozích
hodnotách.
Znakové typy reprezentují jednotky unicode. Typ char
je
jedna UTF-8 jednotka. Analogicky, wchar
reprezentuje
UTF-16 a dchar
UTF-32. Jejich výchozí hodnoty nejsou 0
ale 0xFF
(pro char
),
0xFFFF
(pro wchar
) a 0x0000FFFF
(pro dchar
).
Je jasné, že jen se základními atomickými typy si programátor nevystačí. D poskytuje několik odvozených typů. Základním odvozeným typem je pointer (ukazatel). Pointerů se hojně využívá v jazycích C a C++. V D ani nejsou pro vysokoúrovňové programování moc potřeba, ale D je samozřejmě univerzálním jazykem.
Pointer není nic jiného, než číselná
hodnota. Jeho velikost je
definována platformou. Na většině *nix systémů je pod x86 velký 32 bitů
a pod x86_64 64 bitů. Stejně velký jako pointer je typ size_t
,
což
je alias k číselnému typu stejně velkému jako pointer. Číselná hodnota
pointeru reprezentuje adresu v paměti.
Vzhledem k tomu, že pointer je
číslem, tak se k němu dá přičítat a odečítat, a tak měnit, kam v paměti
pointer ukazuje. Rozdíl dvou pointerů je typ ptrdiff_t
,
který je
stejně velký jako size_t
a je také aliasem, ale narozdíl
od něj je
znaménkový.
O pointerech se dál zmíním v pozdějších lekcích, teď je ještě brzy.
Dalším odvozeným typem v D je pole. Pole mohou být dvou typů. Statická pole se alokují na zásobníku (stack) a mají předem určenou délku. Je to v podstatě posloupnost hodnot určitého typu v paměti (jdou hned po sobě). Spousta lidí si plete v jazyce C pointery a pole. Jsou to ale dosti odlišné věci. Pointer se ale může chovat jako pole a může na něj ukazovat. V takovém případě pointer ukazuje na první hodnotu v poli. Vzhledem k tomu, že takové hodnoty jdou po sobě, tak přičítáním k pointeru je možné získat hodnotu na určitém indexu v poli (ale opět, o tom později, tohle už je pokročilejší látka).
Dynamická pole v D jsou alokována na haldě (heap).
Také je to posloupnost
hodnot, ale vzhledem k tomu, že není na fixním stacku, tak je možné
měnit délku takového pole. I na dynamické pole může ukazovat pointer.
Pro uživatele C++, dynamické pole v D má podobné použití jako vector
v C++, ale je lépe zabudované do jazyka.
Každá hodnota v poli má svůj index
(číslo, první hodnota má index 0
,
poslední DÉLKA-1
). Velikosti polí v paměti (neplést s
délkou pole!) je
DÉLKA*VELIKOST_HODNOTY
.
Kromě toho má D i asociativní pole. Asociativní pole nemají indexy. Místo toho má každá hodnota klíč, který může být různých typů (např. řetězec). Správně bych je neměl do této kategorie řadit, ale sedí tu. Řadit bych je neměl sem proto, že jsou uvnitř implementované jako hash tabulky, a tudíž jsou objektem, ne odvozeným typem od atomického typu.
Existují ještě dva další odvozené typy. Těmi jsou funkce a delegáty. Funkce reprezentují blok kódu - kontext funkce (scope). Funkce mohou manipulovat s hodnotami ve vlastním kontextu a s globálními hodnotami. Lokální hodnoty jiných funkcí (např. main) musí být poslány přes argumenty (o těch v další lekci). Funkce mají vlastní speciální typ pointerů (tzv. function pointery). Konverze mezi normálními pointery a FP znamená nedefinované chování (resp. definované platformou) ale většinou funguje (občas se toho i dost ošklivě využívá). Delegáty se jinak jmenují "fat pointer" ("tlustý pointer"). Jsou složeninou dvou pointerů. Jeden ukazuje na kontext funkce, ve které byl delegát definován (využívají se většinou jako lambda funkce, o této problematice později) a druhý na funkci samotnou (function pointer). Delegátům bude později věnována vlastní lekce.
To ale stále nestačí. Kromě předchozích kategorií, které se dají společně pojmenovat jako POD D má ještě uživatelské typy.
Nejjednodušším je alias
. Alias je jen jiný název pro
některý předtím
definovaný typ. Při kompilaci se takový alias expanduje na plný název
typu.
Dalším uživatelským typem je enumerace
(enum
). Je to v
podstatě
kolekce konstant. Později s
nimi budeme pracovat.
Struktury (struct
) a třídy (class
), další dva
uživatelské typy,
nejsou v jazyce C++ rozlišeny. V D ano, struktury jsou hodnotové typy,
třídy referenční typy (o
referencích opět později). Posledním
uživatelským typem je union
. To je typ, který definuje
několik hodnot
různých typů, ale naráz může obsahovat pouze jeden (všechny typy v
union
sdílí jednu část paměti).
Všemi uživatelskými typy se budeme zabývat v pozdějších kapitolách podrobně.
Zde bych skončil. Přejdeme na proměnné a už i napíšeme nějaký ten kód.
V předchozích lekcích jsme psali nějaké ty úvodní aplikace. Programování ale není pouze o vypisování "hello world" do konzole. Hodnoty si musíme i nějak ukládat a s nimi dále pracovat. K tomuto účelu musíme zavést tzv. proměnné.
Řekněme si, že máme číslo 150
. Toto číslo chceme vypsat
třikrát po
sobě. Přitom po změně tohoto čísla na jednom místě se změní i výstup
programu. K tomuto účelu si zavedeme proměnnou. Proměnné jsou jakési
"pojmenované instance typů". Zapíšeme je takto:
TYP název;
Např. pro typ int
zapíšeme:
int cislo;
Tomuto se říká deklarace proměnné. Proměnné se nikdy nesmí jmenovat jako nějaké rezervované klíčové slovo jazyka. Název proměnné (identifikátor) musí být vždy unikátní vzhledem k aktuálnímu kontextu, jinak dojde ke kolizi a program se nezkompiluje.
No jo, ale my chceme, aby proměnná měla i hodnotu. Deklarované proměnné
ji tedy přiřadíme pomocí operátoru =
. To se jmenuje definice
proměnné.
cislo = 150;
Deklarace i definice se dají kombinovat.
int x = 5;Proměnné, která už má hodnotu, se dá přiřadit jiná hodnota.
int x = 5; x = 10;
Hodnota jiné proměnné se dá přiřadit také:
int x = 5; int y = x;
Obě proměnné budou poté mít nezávislou hodnotu (kopii) (kromě non-POD typů).
Jak už jsem předtím zmínil, názvy proměnných musí být unikátní. Pro pochopení je nutné zavést pojmy globální proměnná a lokální proměnná. Globální proměnná je jakákoliv proměnná deklarovaná mimo kontext určité funkce (popř. třídy, struktury). Vezměme takový program:
import std.stdio; /* dvě globální proměnné, přístupné odkudkoliv */ int foo = 150; string bar = "baz"; void main() { /* lokální proměnná - lokální proměnné nikdy nekolidují s globálními */ string bar = "bah"; short baz = 65536; /* vypíše "150bah65536" */ writeln(foo, bar, baz); }
Dobrá, máme lokální proměnnou, která se jmenuje stejně jako globální. Ale co když je třeba ve funkci s lokální proměnnou přistoupit ke globální, která má stejný název? To je jednoduché:
import std.stdio; int foo = 150; void main() { int foo = 250; writeln(foo, .foo); }
Přidáním tečky před název proměnné se zdůrazní, že se přistupuje ke globální proměnné, nikoliv k lokální.
V jazyce D se rozlišují dva typy konverzí mezi typy, tzv. implicitní konverze a explicitní konverze. Implicitní konverze znamená, že hodnota jednoho typu se dá hned přiřadit proměnné jiného typu. Implicitní konverze je možné provádět hlavně u číselných typů, z typů s menší velikostí na typy s větší velikostí. Např. tato konverze je povolena:
int foo = 5; long bar = foo;
Obráceně už to ale nejde:
long foo = 5; int bar = foo;
Explicitní konverze, tzv cast, samozřejmě funguje správně, pokud se hodnota větší proměnné vejde do menší:
int foo = 5; /* "bar" bude 5 */ short bar = cast(short) foo;
Ale ne, když se nevejde:
int foo = 65537; /* "bar" bude "foo - největší_hodnota_ushort - 1", tzn. 1 */ short bar = cast(short) foo;
Explicitní konverze podnulových hodnot na unsigned hodnoty není možná. Kromě toho není možné převádět implicitně:
Tímto bych skončil tuto lekci. Látku budeme dále rozšiřovat s rozšiřujícími se znalostmi.
1) Napište program, který vytvoří proměnnou typu short s hodnotou 16 a
z ní udělá int, long, ushort, uint, ulong
proměnné a
vypíše je.
2) Vytvořte proměnnou typu long s hodnotou 10 a převeďte ji explicitně
na int, short, ulong, uint, ushort
a přesvědčte se, že
hodnota zůstává
zachována.
Čísla v D samozřejmě můžeme přičítat, odečítat, násobit, dělit, apod., stejně jako v ostatních programovacích jazycích. Ale nebudeme vždy pracovat jen s čísly. Abychom mohli začít dělat i něco s jinými typy, musíme definovat literály. Pak napíšeme i nějaký další kód.
Na hodnotách a proměnných můžeme provádět klasické aritmetické operace. Např. součet dvou čísel:
int foo = 5 + 10;
Samozřejmě, toto není moc užitečné. Stejně můžeme ale manipulovat s proměnnými:
int foo = 5; int bar = foo + 10;
Přičtení hodnoty k proměnné je tedy logicky:
int foo = 5; foo = foo + 10;
To je ale trochu zdlouhavé, takže se to dá skloubit s přiřazením:
int foo = 5; foo += 10;
Stejně tak můžeme odečítat, násobit a dělit.
Pro přičtení, resp. odečtení hodnoty 1
se dají použít i
operátory ++
a --
. Ty se dají zapsat buď před proměnnou nebo za
proměnnou.
int foo = 5; foo++; ++foo; foo--; --foo;
Proměnná foo
bude mít na konci opět hodnotu 5. Jaký je
v tom ale
potom rozdíl?
Při zapsání foo++
, tzv. post-inkrementaci, se přičte 1 a
vrátí se
hodnota před přičtením. Tudíž zápis:
int foo = 5; int bar = foo++;
vyjádří, že foo
na konci bude 6, ale bar
bude 5.
U ++foo
, tzv. pre-inkrementace, je to ale jinak:
/* foo i bar budou 6 */ int foo = 5; int bar = ++foo;
Stejná pravidla platí i pro --
.
Zbytek po celočíselném dělení získáme operátorem %
. Např.
zápis:
int foo = 11; writeln(foo % 3);
vypíše 2 (protože 10/3 se celočíselně dělit nedá, 9 ano, zbytek do 9 je 1). Ostatní operace jsou pak definovány knihovnou.
Při počítání platí určitá pravidla o výsledném typu. Popíšu je, jak jdou po sobě.
real
, tak se druhý
zkonvertuje
také na real
.
double
, tak se druhý
zkonvertuje
také na double
.
float
, tak se druhý
zkonvertuje
také na float
.
- bool => int - byte => int - ubyte => int - short => int - ushort => int - char => int - wchar => int - dchar => uint
Pro enum typy platí další pravidla. Těmi se budeme zabývat později.
Literály lze definovat jako prvky s hodnotou. Mohou být různých typů. My už použili číselné literály a řetězcové literály. Typů literálů je samozřejmě více.
D má několik typů číselných literálů. Základním je samozřejmě
klasické
celé číslo. Patří k němu typ int
. Literály lze dle
velikosti
přiřazovat k jakémukoliv celočíselnému typu. Zapíšeme jej takto:
int x = 5; /* 5 je samotný literál */
Lze zapsat i hexadecimální literály:
int x = 0xDEADBEEF;
Oktalové literály už nejsou podporovány. Místo nich se dají využít funkce standardní knihovny.
Pro unsigned čísla pouze přidáme koncovku u
popř U
.
uint x = 5u;
Pro literály typu long
přidáme l
nebo L
.
Unsigned long se pak
zapíše s ul
, popř. UL
. Float literály končí
s f
, popř. F
:
float a = 3.14f;
Bez koncovky je výchozím typem float literálů typ double
.
Implicitní
konverze je nicméně možná, takže zápis
float a = 3.14;
je možné stejně jako s double
. Literály typu real
mají koncovku L
nebo l
:
real a = 3.14L;Je lepší v takových případech používat raději velké
L
,
protože malé se
snadno splete s jedničkou.
Základním řetězcovým literálem je prostě řetězec uzavřený v dvojitých uvozovkách. Zapisuje se takto:
string a = "hello world";
Dva literály hned po sobě se chovají jako jeden:
string a = "hello " "world";
Takovéto literály mohou obsahovat escape sekvence, které se pak
převedou na jejich pravé reprezentace. Tomu se dá zamezit použitím
WYSIWYG literálů, které se zapisují stejně, jen s předponou r
:
string a = r"všechno\se\bude\zobrazovat\njak\píšu\r\t";
Tyto literály mají i alternativní syntaxi:
string a = `toto ta\ky fun\guje\`;
Dalším typem jsou hexadecimální řetězcové literály:
string a = x"0A"; /* jako "\x0A" */
Mezery a nové řádky jsou ignorovány. Počet hex čísel musí být násobkem
dvou.
Všechny tři typy literálů mohou mít postfix znak, který definuje jejich
typ. Normálně je to string
, což je alias k immutable(char)[]
(pole
imutabilních znaků). Takové pole se skládá z UTF-8 jednotek. Pokud
chceme UTF-16, zapíšeme:
wstring a = "utf-16 řetězec"w;
To samé pro UTF-32:
dstring a = "utf-32 řetězec"d;
Dá se specifikovat i c
, což vyústí v string
(je tudíž implicitně
výchozím nastavením).
Poslední dva typy literálů jsou tzv. delimited literály a token
literály. Delimited literály jsou podobné WYSIWYG, ale umožňují zvolit
dva znaky, mezi kterými může být napsáno cokoliv a nebude to mít žádný
efekt. Tyto znaky musí být napsány hned před/po "
a před
"..." je třeba
napsat q
:
string a = q"{hello world\blah/"bah"`na rozdíl od wysiwyg fungují i tyto znaky`````}";
Delimitery mohou být páry [], ()
, <>
nebo {}
. Delimited stringy
se dají taky použít pro jednoduché zapsání více řádků:
writeln(q"EOS První řádek Druhý řádek Třetí řádek EOS" );
Token literály musí obsahovat syntakticky validní D kód (nemusí být
ale
sémanticky validní). Mají využití např. pro string mixiny (později se
jimi budeme zabývat). Textové editory je považují za kus D kódu, takže
mohou mít zvýrazněnou syntaxi. Zapisují se mezi q{}
:
string x = q{ writeln("hello world"); }
Znakové literály se zapisují mezi '
, např:
char x = 'F';
Dalšími dvěma typy jsou funkční literály (o těch v další lekci) a delegátové literály (někdy příště). Kromě toho existují i literály polí a asociativních polí. Polím bude věnována samostatná lekce. Tímto bych asi tuto ukončil.
Toto všechno je sice hezké, ale v reálných programech nemáme vše v
jedné funkci main
. Tudíž se naučíme s funkcemi pracovat.
V této kapitole nestihneme o funkcích všechno. Pokračovat budeme příští
týden, kdy se podíváme na přetěžování (overloading),
funkce s variabilním počtem
argumentů, vnořené funkce
a delegáty.
Pomocí funkcí můžeme program rozdělovat do přehledných struktur. Struktura funkcí vypadá nějak takto:
NÁVRATOVÝ_TYP název (parametr1, parametr2, parametr3, ...) { tělo_funkce }
Pak funkci můžeme zavolat:
název();
Příklad:
import std.stdio; void foo() { writeln("hello world"); } void main() { foo(); }
Pokud z funkce nevracíme hodnotu, pak návratový typ je vždy void
. Pro
návrat hodnoty z funkce
využíváme return
:
int foo() { return 5; }
Pokud potřebujeme vyskočit z funkce, která nic nevrací, zapíšeme prostě
return;
(to se hodí při praci s podmínkami).
Argumenty funkce můžeme číst stejně, jako proměnné:
int foo(int a, int b) { return a + b; } writeln(foo(5, 10));
Argumenty funkcí mohou mít různé atributy
(in, out, ref, lazy, const,
immutable, scope
), např:
void foo(ref int x, in int y, out int z, int q);
in
je ekvivalentní s const scope
.
scope
znamená, že reference v argumentu nemohou "utéct"
(tzn. zůstanou v
aktuálním kontextu).
out
nastaví hodnotu parametru na výchozí hodnotu typu.
Např. zápis
void foo(out int x) {} ... int a = 5; foo(a);
způsobí, že po zavolání foo
bude a rovno 0.
Pokud by funkce přiřadila
x
parametru nějakou hodnotu, tak se změní i venku:
void foo(out int x) { x = 150; } ... int a = 5; foo(a); /* a je teď 150 */
ref
funguje podobně, ale nedojde ke změně hodnoty
venku, pokud se
explicitně nezmění vevnitř. ref
je zkratkou k
"reference". Reference
je v podstatě "alias" k typu. Chová se jako standardní proměnná, ale
nemá žádnou vlastní hodnotu a místo toho ukazuje na cizí hodnotu
(reference jsou většinou implementované pomocí pointerů, ale jako
pointery se nechovají, protože není možné změnit hodnotu, na kterou
ukazují a chovají se jako "pravé" hodnoty, referencemi se budeme
zabývat později).
lazy
argumenty nejsou vyčísleny při zavolání funkce, ale
až ve
funkci. Tím pádem lze takový argument zavolat nula nebo vícekrát. Např:
void delej_neco_nekolikrat(int n, lazy void f) { while (n--) f(); } ... int x = 0; delej_neco_nekolikrat(5, writeln(x++));
vypíše do konzole:
0 1 2 3 4
const
znamená, že hodnota bude konstantní podle aktuální
reference
(ale jiná reference na stejnou paměť může). immutable
se
nemůže
měnit, je pouze pro čtení. Problematikou const / immutable
se budeme
zabývat později.
Pokud argumenty nemají žádné atributy, pak se stanou mutabilními, lokálními kopiemi. Problematika atributů souvisí s ostatními funkcemi jazyka, takže v průběhu seriálu by se měly veškeré pochybnosti, popř. nepochopení vyjasnit.
Funkce samotné mohou mít různé atributy také.
Pure funkce je taková funkce, která nemá žádné vedlejší efekty. Tyto funkce proto nemohou zapisovat globální proměnné, volat funkce, které nejsou pure, popř. provádět jakýkoliv vstup/výstup. Mohou ale alokovat paměť, ukončit program a pokud se jedná o debug kód, tak mít i vedlejší efekty. O těch více v kapitole o funkcionálním programování v D.
Nothrow funkce nevrací žádné výjimky odvozené z třídy Exception. Výjimkami se budeme zabývat později.
Analogicky k ref
parametrům funkce se může reference i
vracet.
Příklad:
int a = 5;
ref int foo() { return a; }
....
foo() = 10;
Hodnota globální proměnné pak bude 10 (reference mohou být tzv. lvalue, tzn. hodnotami "vlevo", ke kterým přiřazujeme).
Tyto funkce využívají tzv. typové inference ke zjištění typu návratové hodnoty. Příklad:
auto foo(int i) { return i * 2; } /* typ návratové hodnoty se automaticky nastaví na int */
Chovají se podobně jako kombinace ref funkcí a auto funkcí, s jedním rozdílem - automaticky si zjistí, jestli návratová hodnota je lvalue, a podle toho vrací buď referenci, nebo hodnotu.
auto ref foo(int a) { return a; } /* není lvalue, vrací hodnotu */ auto ref foo(ref int a) { return a; } /* vrací referenci */ auto ref foo(out int a) { return a; } /* vrací referenci */ auto ref foo() { return 150; } /* vrací hodnotu */
První return
výraz ve funkci rozhoduje, jestli se
vrací reference,
nebo hodnota.
Těmi se budeme zabývat v kapitole o const a imutabilitě. Vyjadřují jednotný zápis tří variant jedné funkce, kde první vrací mutabilní hodnotu, druhá konstantní hodnotu a třetí imutabilní hodnotu.
U některých funkcí chceme, abychom nemuseli specifikovat všechny argumenty, ale aby měla funkce nějaké výchozí hodnoty. To uděláme snadno:
int foo(int a, int b, string c = "blah") { writeln(a, b, c); }
Potom při zavolání
foo(5, 3);
program vypíše "53blah", ale při
foo(5, 3, "foo");
vypíše "53foo". Pokud má některý argument výchozí hodnotu, všechny následující musí mít logicky také výchozí hodnoty.
To by bylo pro dnešek asi vše. Příští týden budeme s funkcemi pokračovat a uděláme i nějaké nové věci (viz začátek lekce).
auto ref
funkcí.
auto
funkce.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
sizeof()
,...).
Jinak ale práce s polem je opravdu jen pointerová aritmetika.
Tenhle kus kódu by to mohl snad objasnit, je to alternativní zápis přístupu k prvku pole:
#include <iostream>
using namespace std;
int main()
{
int a[3] = {1, 2, 3};
cout << 2[a] << endl;
return 0;
}
Záleží na tom, co si představíš pod pojmem pole; v mém případě je to ten soubor hodnot; v tvém případě je to de facto syntaktický prvek jazyka C (resp. interface k pointerový aritmetice na vyšší úrovni). O tom tvém alternativním zápisu vím, ale nepoužívám jej.
ref funguje podobně, ale nedojde ke změně hodnoty venku, pokud se explicitně nezmění vevnitřA za tým je potom:
reference jsou většinou implementované pomocí pointerů, ale jako pointery se nechovají, protože není možné změnit hodnotu, na kterou ukazujíčo sa celkom vylučuje.
No, je to myšleno tak, že posílání po referenci je v podstatě posílání aliasu; pokud se nezmění hodnota argumentu uvnitř funkce, tak se venku nic neděje; pokud ano, tak se projeví změna i venku.
Tudíž zápis:
void foo(ref int bah) { bah = 10; }; int x = 5; foo(x);
vyústí v to, že x bude pak 10, ale kdyby foo bylo
void foo(ref int bah) {}
tak se nic neděje, hodnota zůstává 5. Tak to není v případě "out" atributu, který by v prvním případě fungoval stejně, ale v druhém případě by po zavolání foo bylo x 0. Zápis:
void foo(ref int bah) { bah = 10; }; int x = 5; foo(x);
je ekvivalentní s
void foo(int* bah) { *bah = 10; }; int x = 5; foo(&x);
Reference jsou proto implementovány většinou pomocí pointerů, ale sémanticky se chovají jako aliasy.
reference jsou většinou implementované pomocí pointerů, ale jako pointery se nechovají, protože není možné změnit hodnotu, na kterou ukazujímyslim ze touhle vetou chtel rict ze neni mozne zmenit referenci tak aby ukazovala na novou adresu. Ale je pravda ze ta veta to nerika
Cčkaři vědí, že hodnoty různých typů se automaticky neinicializují a je třeba explicitně specifikovat hodnotu. Toto neplatí v případě D. Všechny integrální typy jsou implicitně 0.To je z poloviny pravda. Hodnoty nejsou inicializované, jedná-li se o lokální proměnou, čili proměnnou alokovanou na zásobníku, kdy hodnota je náhodná (viz vývojáři Debianu a generování certifikátů). Jde-li o globální, či statickou proměnnou, je inicializována na binární 0 (není-li hráno s přepínači překladače, apod.). Martin
Typ char je jedna UTF-8 jednotkaNie je mi to jasné. Vôbec mi to nie je jasné.
Jde o to, že znaky s diakritikou, jenž mají vyšší kód znaku než 127 (nikoliv 255, protože 1b se používá k signalizaci UTF-8 znaků s větší hodnotou, ten 1b říká že následující znak je součástí aktuálního) jsou zapsány jako vícero znaků typu char.Snažíš se zmást nepřítele termilologií z ASCII? V popisu UTF-8 nemůžeš používat slovo znak jako synonymum bajtu, když jeho základní vlastností je, že znak nemá vždy stejný počet bajtů.
Pokud použiješ UTF-16 (wchar), jedna jednotka představuje 16b, takže se ti do jedné jednotky vejde jeden český znak.Český znak sice jo (vlastně jakejkoli ne-obskurní
Utf-16 představuje dost dobrý paměťově-výkonový optimum při práci s řetězci.To jistě, hlavně při práci s východoasijskými jazyky. Ale ty výkonově-paměťové nároky podle mě nepřeváží rizika chyb včetně bezpečnostních, které UTF-16 může při špatném otestování na proměnnou délku představovat. A přecijen riziko neobjevení chyb daných proměnnou délkou znaku je u UTF-8 podstatně menší než u UTF-16, srovnej kolik uživatelů se nevejde do ASCII a kolik se nevejde do BMP.
Ale ty výkonově-paměťové nároky podle mě nepřeváží rizika chyb včetně bezpečnostních, které UTF-16 může při špatném otestování na proměnnou délku představovat.Jako vsechny bezpecnostni rizika pri praci s polem, toto neni argument.
A přecijen riziko neobjevení chyb daných proměnnou délkou znaku je u UTF-8 podstatně menší než u UTF-16, srovnej kolik uživatelů se nevejde do ASCII a kolik se nevejde do BMP.Od toho jsou unit testy, popripade jina forma testovani.
Jako vsechny bezpecnostni rizika pri praci s polem, toto neni argument.Díky za upozornění, že to není argument.
Od toho jsou unit testy, popripade jina forma testovani.Bylo na tom, co jsem napsal, něco nesrozumitelného? Mimochodem, doporučuju někdy konfrontovat teorii s praxí.
Na druhou stranu je UTF-16 z hlediska pameti nejlepsi volbatady nekdo po ranu jedl ftipnou kasi...
Na druhou stranu je UTF-16 z hlediska pameti nejlepsi volbaKecy nemaj cenu. Zkus si to tvrzení aspoň obhájit. Zjevně podle tebe platí obecně, tak to zkus třeba s češtinou, to je taková zlatá střední cesta. Nicméně, doporučím ti k přečtení ten příspěvek, u kterého jsi omylem klikl na odkaz „odpověďět“.
Q: How should I handle supplementary characters in my code? A: Compared with BMP characters, the supplementary characters are relatively uncommon in most contexts. That fact can be taken into account when optimizing implementations for best performance: execution speed, memory usage, and storage. This is particularly useful for UTF-16 implementations, and to a lesser degree in UTF-8 implementations.Utf-16 ti umožňuje rychlý stringy - v 99% procentech případů má přístup ke znakům složitost O(1), což výrazně zjednodušuje i další stringové operace. Zároveň oproti utf-32 zabírá pouze (téměř, v 99%) polovičku paměti. Takže pro práci s řetězci je to imho dost optimální. (Jinak ale na serializaci jsem osobně pro utf-8).
Ono ani nevim o runtime, kde by se UTF-32 vyuzivalo.Dart. Teda, tam jsou Stringy v paměti vždycky s fixní velikostí znaku, a to buď jednobajtovou, nebo dvoubajtovou, nebo čtyřbajtovou.
Utf-16 ti umožňuje rychlý stringy - v 99% procentech případů má přístup ke znakům složitost O(1), což výrazně zjednodušuje i další stringové operace.Což je právě až příliš dobrý výsledek, viz výše.
sorry ze to tak musim rict, ale tohle je fakt blabol. Proste mas kodovani s promenou delkou a tak s nim tak musis pracovat. A ne se to snazit zamest pod koberec, tvrdit uzivateli tridy ze operace maji slozitost O(1), pak tam nekdo zada "nespravny" retezec a cely se to sesype...Ale né, ve chvíli, kdy někdo zadá "nesprávný řetězec", tak se akorát změní ten flag, použijí se příslušné algoritmy a nic se nesesype...
dalsi vec je ze dost podcenujes overhead spojeny s udrzbou toho flagu. sice se tim nezmeni asymptoticka slozitost ale to neznamena ze se to nezpomali...Tak jasný, ten flag nějakou režii mít bude, pořád je to ale ještě imho o řád lepší než pracovat se všemi stringy jako by obsahovaly surrogate pairs...
for (i = 0; i < s.len(); ++i) { ... s[i] ... }a to ok v zadnym pripade neni, muzes si to prat sebevic... a pri nespravnym retezci se to sice technicky vzato nesesype, jenom se nedockas vysledku.
operator[]()
se přece postará o správné procházení stringem právě na základě toho flagu, od toho ten flag je. To vlastní pole, ve kterém jsou uložena syrová data, je zapouzdřeno.
(To se tady opravdu snažim sdělit tak složitou myšlenku, nebo co se děje?)
ok to neni protoze pri nespravnym retezci to ma kvadratickou slozitost misto linearni.Cože?!? Proč?
pritom je tady jednoduchy reseni - nepredstirat ze je to kodovani s pevnou delkou, kdyz neni, a pouzit iterator.Nic nepředstírám, plně počítám s tím, že to kódování s proměnnou délkou je, a pro (vhodně implementované) iterátory jsem všema deseti.
Cože?!? Proč?On asi myslel to, kdybys ten operator[] volal pro kazdy znak v poli (pouzil to jako iterator).
Přijde mi, že se nám tu snaží pánové pavlix a extremni lama dokázat, že když se utf-16 stringy špatně použijí, vzniknou potíže. Což je tedy skutečně objev...Jsem rád, že jsi to alespoň po takové době objevil. Teď ještě vypilovat porozumění textu, protože já jsem bohužel od začátku předpokládal, že toto ti bude jasné. Co se týče uživatele __dart__, tak tomu jsem vyvracel cca tři nesmyslná tvrzení: 1) Že UTF-16 má (obecně) nejmenší paměťovou náročnost z trojice UTF-8, UTF-16 a UTF-32, což je celkem triviální matematika. 2) Že se na Unicode.org tvrdí (1), nacož je myslím dostatečné to, že se to vůbec netvrdí v citaci, kterou on nakonec použil. Co se týče toho sdělení tobě. Už nevěřím, že bys to vůbec mohl či dokonce chtěl pochopit... ale ještě jednou, a jednodušeji: Implementace UTF-16 bude IMO obsahovat podstatě více extrémně málo používaného kódu než implementace UTF-8. A ten extrémně málo používaný kód se týká zpracování textových řetězců proměnné délky a výpočtu délky řetězcové proměnné v paměti. Případné chyby vedou na zranitelnosti v buffer overflow. Když bude do kódu zasahovat lama, která si v roce 2012 myslí, že v Unicode mají znaky 16 bitů neboli dva bajty (a že takových je!), tak je velká pravděpodobnost, že lama vytvoří bezpečnostní díru. U UTF-8 toto neplatí. Pokud u UTF-8 lama přecijen použije předpokladu, že počet kódových jednotek je stejný jako počet znaků, tak si toho možná angličtí kolegové bez zájmu o typografii nevšimnou. Ale všimnou si toho češtní, fracouzští, španělští, němečtí a jiní. A ty, jsi navrhl, že by se používaly dva různé algoritmy, jeden pro BMP řetězce a jeden pro řetězce s aspoň jedním ne-BMP znakem. A navíc jsi tvrdil, že tím je problém vyřešený, což je tak zřejmý nesmysl, že kdybys měl koule, tak bys to dávno uznal. Tím množství rizikového kódu zvyšuješ a pravděpodobnost objevení chyby, která se v něm nachází, snižuješ. Q.E.D.
vyvracel cca tři nesmyslná tvrzení:3) Že mu vyvracím nesmyslné tvrzení č. 1, protože jsem si na něj zasedl :).
Implementace UTF-16 bude IMO obsahovat podstatě více extrémně málo používaného kódu než implementace UTF-8. A ten extrémně málo používaný kód se týká zpracování textových řetězců proměnné délky a výpočtu délky řetězcové proměnné v paměti.S extrémně málo používaným kódem se setkáš v bezpečnosti na každém kroku. O tom v podstatě velká část bezpečnosti ošetření vstupu je. Viz např.
Když bude do kódu zasahovat lama, která si v roce 2012 myslí, že v Unicode mají znaky 16 bitů neboli dva bajty (a že takových je!), tak je velká pravděpodobnost, že lama vytvoří bezpečnostní díru. U UTF-8 toto neplatí.Pokud bude do kódu zasahovat lama, napáchá pravděpodobně řadu dalších problémů než jen zpracování textu. Pokud bude do kódu zasahovat lama, nedá se na bezpečnost toho kódu spolehnout. A to platí ať už použiješ utf-8, utf-16, utf-32, utf-over9000 anebo i když vůbec nebudeš zpracovávat text. Takže toto opravdu není argument.
A ty, jsi navrhl, že by se používaly dva různé algoritmy, jeden pro BMP řetězce a jeden pro řetězce s aspoň jedním ne-BMP znakem. A navíc jsi tvrdil, že tím je problém vyřešený, což je tak zřejmý nesmysl, že kdybys měl koule, tak bys to dávno uznal.Ale prd, tys akorát absolutně nepochopil, jak jsem to myslel. Místo toho tady mlátíš ostatní koulema...
Pokud bude do kódu zasahovat lama, napáchá pravděpodobně řadu dalších problémů než jen zpracování textu. Pokud bude do kódu zasahovat lama, nedá se na bezpečnost toho kódu spolehnout. A to platí ať už použiješ utf-8, utf-16, utf-32, utf-over9000 anebo i když vůbec nebudeš zpracovávat text. Takže toto opravdu není argument.Pokud rozdíl v náročnosti revize celého kódu i jednotlivých patchů, případně napsání smysluplných testů, a daších věcí nevidíš, tak to pak naprosto chápu tvé „ach jo“. Ona je jedna věc, když je to implementace unicode pro python, javu nebo jiné vysokoúrovňové jazyky, a jiná věc, pokud je to třeba pro céčko a programátor má přímý přístup ke všemu. V tom druhém případě jsi v prdeli asi podobně, jako jsi byl v prdeli s Pythonem 2 a automatickými konverzemi, s tím rozdílem, že ty vždycky vedly „jenom“ na vyhození výjimky a v případě neošetření „jenom“ na pád serveru.
Ale prd, tys akorát absolutně nepochopil, jak jsem to myslel.A čí je to chyba? Moje nebo tvoje?
Místo toho tady mlátíš ostatní koulema...Ty jsi schizofrenik, že pro sebe používáš množné číslo a slova jako „ostatní“? Nebo to má být plural majestaticus nebo jak se tomu říká?
Pokud rozdíl v náročnosti revize celého kódu i jednotlivých patchů, případně napsání smysluplných testů, a daších věcí nevidíš, tak to pak naprosto chápu tvé „ach jo“.Nějak se mi nedaří z týhle věty vydestilovat smysl. Rozdíl mezi čím a čím?
Ona je jedna věc, když je to implementace unicode pro python, javu nebo jiné vysokoúrovňové jazyky, a jiná věc, pokud je to třeba pro céčko a programátor má přímý přístup ke všemu.Tak, a teď se zeptej sám sebe: Týká se tento problém s nízkoúrovňovostí céčka pouze UTF-16, nebo se týká prakticky čehokoli v céčku? Já musím prostě souhlasit s kolegou Darkem v tom, že jsi zřejmě proti UTF-16 zaujatý, protože mi přijde, že sveřepě hledáš problémy, které s podstatou UTF-16 ani moc nesouvisí - jako například to, že programátor je lama nebo to, že v C je problematické zapouzdření. Tyto problémy jsou v zásadě off-topic.
A čí je to chyba? Moje nebo tvoje?Nejspíš na obou stranách...
pritom je tady jednoduchy reseni - nepredstirat ze je to kodovani s pevnou delkou, kdyz neni, a pouzit iterator. Sice tim programatora trochu omezis a u nekterych veci se bude muset trochu vic zamyslet, ale vysledek bude rychlejsi a bude mit predvidatelnou slozitost. Jenomze ve chvili kdy si prizname ze UTF-16 je kodovani s promennou delkou tak si taky musime priznat ze proti utf-8 a utf-32 ma jenom nevyhody... a to si tady nekdo nechce priznat ze...Tomuhle člověku říkáš troll? To je fakt jak házet perly sviním, takové pěkné vysvětlení. Už to nehul.
Co se týče druhého odstavce, tak bohužel ty "nevýhody utf-16" tady zatím ani jeden z vás moc nerozvedl - viz níže.UTF-8: + kompatibilni s ASCII + nizka spotreba pameti + nejsou problemy s little/big endian + nejsou potreba zadny konverze pro IO, v podstate staci zkopirovat blok pameti na vystup (souvisi s kompatibilitou s ascii) - variable length UTF-32: - nekompatibilni s ASCII - vysoka spotreba pameti - nevhodny pro IO (problemy s little/big endian, programy pracujici s ascii budou UTF-32 retezec povazovat za binarni data) + fixed length celkove UTF-32 muze byt za urcitych okolnosti vhodny pro interni reprezentaci a pro urcity algoritmy UTF-16: - nekompatibilni s ASCII - vysoka spotreba pameti - nevhodny pro IO (problemy s little/big endian, programy pracujici s ascii budou UTF-16 retezec povazovat za binarni data) - variable length jedina castecna vyhoda utf-16 je ze nektery knihovny to z historickych duvodu jeste stale pouzivaji...
Ok, dejme tomu, ale úplně férové to není, u UTF-8 jsi vůbec nevzpomněl na negativum hodně složitého algoritmu v porovnání s ostatními dvěma (ano, i v porovnání se zpracováním surrogate pairs v UTF-16).Od toho tu jsi ty, abys to doplnil, ne? Jak jsem říkal, nehledej hned špatný úmysl. Ale když jsem ho implementoval, tak vůbec složitý nebyl, aspoň při použitá shl a and to bylo úplně na pohodu. Ale ve srovnání s UTF-16 či bych ti to uznal. Ve srovnání s UTF-32 to je přímo obsaženo v tom, že UTF-32 je fixed.
No a UTF-8, pokud máš smůlu, zabere víc než UTF-16.Tak ta smůla dost závisí na volbě jazyka.
Že je UTF-16 nevhodný pro I/O, to určitě souhlasim, osobně bych také serializoval do UTF-8.Pokud serializuju do UTF-8, tak potřebuju vážný důvod, abych v paměti měl něco jiného :).
Jestli jste ty nebo lama měli dojem, že se snažim tvářit, že je utf-16 fixed-wdithMy ten dojem ještě máme, že se pro 99% procent případů chceš chovat k UTF-16 jak fixed width, a na ten zbytek dělat special case. Mimochodem, doporučuju ti se podívat na dohady o special casing konverze mezi čísly a jejich textovou reprezentací v různých soustavách v Pythonu. Tam je to čistě kvůli optimalizaci a už teď jsou ohlasy, že je tam special cases tolik, že pokrývají celou škálu reálného užití té funkce (jsou tam special cases pro mocniny dvou a pro desítku :D). Jen zajímavost.
Co se týče druhého odstavce, tak bohužel ty "nevýhody utf-16" tady zatím ani jeden z vás moc nerozvedlOk, tedy nevýhody nasazení UTF-16 oproti UTF-8 1).Nevýhodou je paměťová náročnost, to lama pokud vím psal. U češtiny možná o 70%, nepočítám, jen odhaduju. 2) Nevýhodou je naprostá nekompatibilita s ASCII. Kde UTF-8 funguje samo od sebe, UTF-16 se musí doimplementovat. Příkladem budiž programovací jazyky. ASCII znaky fungují, non-ASCII znaky se při kompilaci vůbec nemusí řešit. Navíc to tak už funguje díky dlouhé tradici osmibitových kódování kompatibilních s ASCII. 3) Nevýhodou je problém s endianess při serializaci. 3a) Tím pádem nemůžeš identický formát používat v souboru i v paměti, což způsobuje, že musíš konvertovat data při čtení i zápisu. 3b) Tím pádem potřebuješ udržovat informaci o kódování souboru, například ve značce na začátku souboru, čímž ztratíš funkcionalitu klasických shellovských příkazů včetně třeba
cat
!
3b) Ztratíš všeobecně uznávaný předpoklad, že nulový bajt ukončuje řetězec, což asi není tak zásadní, ale je to nepříjemnost.
4) Mnou zmíněný special casing, který ty jako nevýhodu neuznáváš.
Nicméně děláš chybu, protože v případě nízkoúrovňových jazyků
se to dotýká bohužel i kódu aplikací.
5) Takovou menší nevýhodou je že si programátoři UTF-16 pletou se starším šestáctibitovým Unicode, a při použití aplikace v běžných jazycích si toho nikdo nemá šanci všimnout. Ale jde to proti smyslu Unicode.
Jsem si jistý, že by se těch nevýhod našlo i víc, ale mě osobně 2 a 3 přijdou kritické, 4 zásadní, 5 nepříjemná, a 1 zbytečná, když není vyvážena dostatečnou výhodou.
Kvůli kterékoli z 2, 3 a 4 bych u nového projektu volil UTF-8. U staršího projektu bych měnil kódování jedině při nějakém velkém rewritu, jinak bych upgradoval starý unicode na UTF-16 a zakázal vývojářům zpracovávat UTF jinak než jednou sadou otestovaných rutin
a snažil se vymyslet další způsoby, jak jim zabránit v tom to zkurvit.
Když se podíváš normálníma očima, zjistíš, že se __dark__ projevuje jako troll a když ho s tím pošleš do háje ty, akorát tím stoupneš. Já na tebe nebudu používat argumenty typu „my jsme dva, tak víme líp“, tak špatně na tom ještě nejsem :).
Extremni lama se jako troll nechová a má u mě oběd za trpělivost, pokud se někde potkáme třeba na konferenci.
Když se podíváš normálníma očima, zjistíš, že se __dark__ projevuje jako troll"Normální oči" bych chtěl vidět, ty budou asi vedle prototypu metru v Paříži (sarkastický smajlík). Jinak mně Darkovy komentáře nepřijdou o nic víc trolující než tvoje Lorem Ipsum nebo lamův kód s operátorem
[]
, který byl zcela mimo mísu - uznávám, že to ale bylo možná jen nedorozumění.
Ad 1. Ano, utf-16 je náčročnější na paměť, považuju to za výměnu za rychlost.Zase vágní kecy. Ve spoustě věcí je UTF-8 rychlejší :).
Ad 2. a 3. Souhlasím, pro serializaci preferuju utf-8. Konverze utf-8/utf-16 při čtení/zápisu mi nepřipadá jako problém...Před chvíli jsi psal něco o tom, že dáváš přednost rychlosti :).
4. Proč vnímáš special casing jako takovou nevýhodu? A tím myslim konkrétně u utf-16, ne obecně...Special casing je nevýhoda obecně kvůli náchylnosti na chyby. Konkrétně u UTF-16 jsem to několikrát popsal, ale že seš to ty... protože v tomhle případě je to special casing pro velikost přidělené paměti a zavání to stack overflow a podobnými.
Jinak mně Darkovy komentáře nepřijdou o nic víc trolujícíTo je mi líto.
Lorem IpsumLipsum jsem ti napsal jen jednou a měl bys uznat, že to bylo na příspěvek, ve kterém nešlo najít souvislost s příspěvkem, kde jsi kliknul na tlačítko odpovědět. Ale dejme tomu, že to bylo na hraně :). Zase mě omlouvá to, že aspoň vím, o čem píšu.
lamův kód s operátorem [], který byl zcela mimo mísu - uznávám, že to ale bylo možná jen nedorozumění.Pokud nevíš, máš předpokládat dobrý úmysl, ne špatný. V tomhle případě neshledávám jediný náznak špatného úmyslu. IMO má k trollování dál než ty, který opakovaně tvrdíš, že jsi neviděl žádný argument, když jsi ho opakovaně dostal :). Sáhni si taky do vlastního svědomí. Dokonce mi ani jeho příklad nepřipadá jako blbost, prostě chtěl jenom nějakou ukázku, na které to půjde porovnat. Její relevanci jste ani moc nediskutovali.
Zase vágní kecy. Ve spoustě věcí je UTF-8 rychlejší :).A tohle vůbec není vágní tvrzení, že...
Před chvíli jsi psal něco o tom, že dáváš přednost rychlosti :).Při serializaci je imho typicky úzké hrdlo jinde.
Special casing je nevýhoda obecně kvůli náchylnosti na chyby. Konkrétně u UTF-16 jsem to několikrát popsal, ale že seš to ty... protože v tomhle případě je to special casing pro velikost přidělené paměti a zavání to stack overflow a podobnými.Sorry, ale ani teď ani předtím jsi to nepopsal dostatečně konkrétně. Že to někomu něčím "zavání" to je možné, ale jestli to má mít váhu, budeš opravdu muset být konkrétnější. V jakém případě by tam mohl nastat ten overflow? (Ad trolling: myslim, že nemá smysl se přetahovat o to, kdo víc troluje...)
A tohle vůbec není vágní tvrzení, že...Je :). Ale nejsou to takové kecy, jako že přechodem na UTF-8 získáš rychlost. To by totiž byl úplně stejný kec jako že ji získáš přechodem na UTF-16. Něco je rychlejší a něco je pomalejší, nehledě na to, že pochybuju, že by to bylo nějak významné (v obou případech).
Sorry, ale ani teď ani předtím jsi to nepopsal dostatečně konkrétně. Že to někomu něčím "zavání" to je možné, ale jestli to má mít váhu, budeš opravdu muset být konkrétnější. V jakém případě by tam mohl nastat ten overflow?Kolikrát ti to mám ještě napsat? Overflow hrozí ve chvíli, kdy se zamění počet kódových jednotek s počtem znaků. Když se budeš snažit, najdeš to minimálně v pěti komentářích, spíš více. Nepřipadáš si trochu natvrdlý? Mě teda v téhle diskuzi docela jo. Budu pomalu končit, už se mi zobrazují příspěvky po slovech, což naznačuje, že jsem se pustil do jirsákovské diskuze a to mi přijde jako ztráta času.
Kolikrát ti to mám ještě napsat? Overflow hrozí ve chvíli, kdy se zamění počet kódových jednotek s počtem znaků.Ale vždyť ten special casing nic takového nedělá... Pouze interně volí různé algoritmy pro výpočet počtu znaků pro různé stringy, to je všechno... Ne, asi máš recht, tohle opravdu ztrácí smysl...
Nejdulezitejsi knihovny/prostredi pouzivaji UTF-16 (vcetne API ruznych mobilnich zarizeni) a pavlix ani extremni lama s tim nic neudelaji.Nemůžu mluvit za lamu, kterýžto vůbec lamou není, ale mě nijak nevadí, že knihovny, které jsou pro tebe nejdůležitější, používalí z historických důvodů původní šestnáctibitový Unicode, a možná některé znich už stihli cestou nejmenšího odporu upgradovat na UTF-16, ale dost možná z nich většina o UTF-16 ještě ani nezavadila. Nejdůležitější knihovni s jejichž kódem jsem se setkal, používají UTF-8, a ani __dark__, který tak rád převádí IT oblast na emocionální úroveň, aby nedej bože nemusel používat kritické myšlení, natož přiznat, že napsal totální blbost, která by platila jen pokud by 1.2 bylo větší než 2.0.
UTF-16 je zkratka zlaty stred - pametove nejefektivnejsi:) nejvykonnejsi:) nejodolnejsi vuci chybam:) Nejbezpecnejsi (neplati pro pavlixe:))Prostě něco jako Windows (co si tak pamatuju instalační obrazovky).
A jako bonus, nepouzivaji ho silenci:)Chápu, že ti připadám jako šílenec, když si umím spočítat relativní četnosti a takové věci. Holt „vyšší level“ (z mého pohledu ale základy).
Používají to Windows (emocionální argument)Moc se ti omlouvám, za to, že jsem ti výše ptal slušně a chápavě. Takže pokud teď nenajdeš citaci, kde tvrdím, že UTF-16 je špatné, protože to používají Windows, budu tě považovat za blbce.
Když to použije lama, je dost možné, že to zkazíTo není argument, ale platný předpoklad pro argument, který záměrně vynecháváš, protože sis zřejmě už vnitřně uvědomil, že mám pravdu. Jinak bys rozporoval můj skutečný argument.
V jazyce C jsou s tím podobné problémy jako se vším ostatnímTo slova tvá jsou.
(Zapomněl jsem na něco?)Napsal jsi tři argumenty, které jsi mi lživě přisoudil pro to, abys mě následně mohl shodit. Jenže, tady nejsi před šéfem, kde potřebuješ sbírat laciné body za to, že někoho neprávem shodíš. Tady shazuješ jen sebe a to nejen odborně, ale i charakterově.
Kromě toho, opravdu by mě zajímalo, jak by to dopadlo, kdyby lama implementovala UTF-8. Imho by to nebylo lepší, možná spíš ještě horší, ono UTF-8 taky není úplně triviální dobře implementovat a má svoje záludnosti.Na UTF-8 se IMO dřív umlátí vlastníma testama na nějakém Evropském jazyce. Na UTF-16 ne. Ale to je detail, spíš než problém v UTF knihovně bych viděl problémy v aplikaci, kde v 99% půjde použít oběcně mylný předpokad, že počet kódových jednotek je stejný jako počet znaků. U dynamických jazyků mě zajímá prakticky jenom API, takže vnitřní UTF-16 implementace mi přijde sice zbytečná, ale pokud se to neprojevuje navenek ani na bezpečnostních chybách, je mi to upřímně jedno.
Místo toho tady mlátíš ostatní koulema...Tak to bych fakt chtěl vidět v praxi. Je to jedna z těch věcí, u které mi vůbec nedochází jak by se měly prakticky implementovat. Možná kdyby si uřízl péro a jednu nohu, nebo nevim :) PS: Teď mě napadá že by mohl mít nějaké ufiklé na provázku/klacku a mlátit s nimi ostatní, což by mohlo být docela efektivní.
Jenomze ve chvili kdy si prizname ze UTF-16 je kodovani s promennou delkou tak si taky musime priznat ze proti utf-8 a utf-32 ma jenom nevyhody... a to si tady nekdo nechce priznat ze...Myslím, že teď jsi na to kápnul :).
Mam pocit, ze tve reakce se spis zameruji na mou osobu, nez na dane tema.Nemám ponětí kdo jsi, ani co jsi, takže neshledávám žádný důvod zaměřovat své reakce osobně. Zato tvé obvinění z mé zaujatosti mi osobní připadá, takže se můžeš představit a sdělit mi, co jsem ti udělal zlého :). Teda teď už o tobě vím, že neumíš počítat, což lze přímo odvodit od toho, že považuješ UTF-8 za obecně efektivnější než UTF-16. Ale takových, co neumějí počítat znám mnoho, takže ani to ti nezajišťuje jedinečnost.
O prednosti UTF-16 je zminka i na unicode.org, ale to jsou asi jenom kecy.Argumentum ad verecundiam. Tím zde neoslníš. Vzhledem k tomu, že jsi necitoval konkrétní znění, a vzhledem k tomu, že mi ještě nedorazila křišťálová koule, kterou jsem si objednal, můžu jenom tipovat. A osobně tipuju, že zrovna toto na unicode.org mají napsáno správně, pouze že jsi to špatně pochopil.
Nemám ponětí kdo jsi, ani co jsi, takže neshledávám žádný důvod zaměřovat své reakce osobně. Zato tvé obvinění z mé zaujatosti mi osobní připadá, takže se můžeš představit a sdělit mi, co jsem ti udělal zlého :).Tak si asi zaujaty jen vuci UTF-16
Teda teď už o tobě vím, že neumíš počítat, což lze přímo odvodit od toho, že považuješ UTF-8 za obecně efektivnější než UTF-16. Ale takových, co neumějí počítat znám mnoho, takže ani to ti nezajišťuje jedinečnost.Nechapu, proc sem pises takove vylevy a jeste mi podsouvas neco, co jsem nikde nenapsal.
Argumentum ad verecundiam. Tím zde neoslníš....
Vzhledem k tomu, že jsi necitoval konkrétní znění, a vzhledem k tomu, že mi ještě nedorazila křišťálová koule, kterou jsem si objednal, můžu jenom tipovat. A osobně tipuju, že zrovna toto na unicode.org mají napsáno správně, pouze že jsi to špatně pochopil.Stacilo napsat, ze chces link, treba v poznamkach UTF-16: http://unicode.org/notes/tn12/ . Mi osobne z hlediska zpracovani textu prijdou nejzajimavejsi tento:
UTF-8 was mainly designed to store Unicode filenames in an ASCII-friendly way. It is suitable for processing, but it is significantly more complex to process than UTF-16. Lead bytes have a relatively complex encoding, and up to three trail bytes (or five to cope with the original definition) must be counted, read and range-checked, then the resulting code point must be range-checked as well.a
UTF-16: From a programming point of view it reduces the need for error handling that there are no invalid 16-bit words in 16-bit Unicode strings. By contrast, there are code unit values that are invalid in 8/32-bit Unicode strings. All pairs of lead/trail surrogates in UTF-16 represent valid supplementary code points, and reading 16-bit Unicode requires to look ahead at most one unit.Conclusion:
Unicode is the best way to process and store text. While there are several forms of Unicode that are suitable for processing, it is best to use the same form everywhere in a system, and to use UTF-16 in particular for two reasons:At si to kazdy prebere jak chce.
The vast majority of characters (by frequency of use) are on the BMP.
For seamless integration with the majority of existing software with good Unicode support.
Tak si asi zaujaty jen vuci UTF-16Kolik takových uhozených teorií máš ještě v zásobě?
Nechapu, proc sem pises takove vylevy a jeste mi podsouvas neco, co jsem nikde nenapsal.Zapomněl jsem tam napsat „z hlediska paměti“, jinak viz tvé:
Na druhou stranu je UTF-16 z hlediska pameti nejlepsi volbaNebo to psal někdo jiný pod tvoji přezdívkou?
At si to kazdy prebere jak chce.Díky za prostor k interpretaci. Vidím to tak, že můj tip byl naprosto správný. Že je UTF-16 z hlediska paměti nejlepší, se tam nepíše ani zdaleka. Naopak se tam píše o důvodu z hlediska kompatibility s původním, jinak definovaným, Unicode, což se týká právě serializace. Řetězce v programovacích jazycích můžou používat abstrakci, která interní reprezentaci vůbec neexponuje (pole znaků například tak jak se používá v Pythonu 3).