Základy programování ve Squeaku (2)

Pavel Tišnovský 5. 8. 2010

V dalším článku o programovacích jazycích vhodných pro výuku programování si podrobněji popíšeme, jak spolu mohou objekty ve Squeaku komunikovat pomocí posílání zpráv. Taktéž si řekneme, jak se konstruují programové bloky, které lze použít například pro implementaci řídicích struktur.

Obsah

1. Unární zprávy

2. Umístění objektů na pracovní plochu Squeaku

3. Zřetězení unárních zpráv

4. Binární zprávy

5. Pořadí vyhodnocování unárních a binárních zpráv

6. Zprávy s obecným počtem parametrů

7. Nejčastější problémy při zápisu zpráv s obecným počtem parametrů

8. Programové bloky

9. Odkazy na Internetu

1. Unární zprávy

V předchozí části článku o programovacím jazyce Squeak jsme se již ve stručnosti zmínili o tom, že objekty (ať již se jedná o objekty vytvořené uživatelem či o systémové objekty, které například reprezentují prvky grafického uživatelského rozhraní) mezi sebou komunikují pomocí takzvaného „posílání zpráv“ a taktéž to, že ve Squeaku existují tři typy zpráv, které se od sebe odlišují především syntakticky, tj. způsobem zápisu. Jedná se o unární zprávy, binární zprávy a o zprávy s obecným počtem parametrů. Nejdříve se budeme zabývat unárními zprávami, protože práce s nimi je nejjednodušší. Unární zprávy poslané nějakému objektu neobsahují žádný parametr, objekt se tedy rozhoduje, jakým způsobem má na poslanou zprávu zareagovat, přímo podle toho, o jakou zprávu se jedná, tj. na základě jejího selektoru (zjednodušeně řečeno: podle toho jaké má zpráva jméno). Proč se však těmto zprávám říká „unární“? Je tomu tak z toho důvodu, že se při poslání tohoto typu zprávy pracuje pouze s jediným objektem – příjemcem zprávy.

Formát zápisu unárních zpráv je ze syntaktického hlediska velmi jednoduchý: selektor zprávy se zapíše přímo za jméno objektu (příjemce zprávy), jak je to ostatně patrné z následujících demonstračních příkladů. Poznámka: na prvním řádku ve výpisu je vždy uveden výraz zapsaný uživatelem, na řádku druhém objekt, který vznikl na základě reakce příjemce zprávy. Příklady je možné si vyzkoušet například v okně Workspace popsaném v předchozích dvou částech tohoto seriálu (po zapsání výrazu postačuje stlačit klávesovou zkratku CTRL+p, popř. z kontex­tového menu vybrat příkaz print it, aby došlo k vytištění výsledného objektu, resp. textové reprezentace tohoto objektu do okna Workspace):

42 factorial
1405006117752879898543142606244511569936384000000000
1405006117752879898543142606244511569936384000000000 digitLength
22
-42 abs
42
42 threeDigitName
'forty-two'
'www.root.cz' stringhash
157059795
true not
false
false not
true

Obrázek 1: Okno Workspace, v němž je možné jednoduše posílat zprávy různým objektům a vypisovat textové reprezentace objektů, které vzniknou na základě těchto zpráv.

Pokud příjemce zprávy nedokáže unární zprávu s daným selektorem zpracovat, dojde k chybě:

'www.root.cz' abs
" na tomto místě dojde k zahlášení chyby,"
" protože objekt 'www.root.cz' (tj. řetězec)"
" nedokáže zareagovat na zprávu se selektorem abs."

Obrázek 2: Výsledek pokusu o poslání zprávy se selektorem abs řetězci, který na tuto zprávu nedokáže korektně zareagovat. Z vypsaného chybového hlášení je patrné, že instance třídy ByteString nezná metodu abs.

2. Umístění objektů na pracovní plochu Sqeaku

Výsledkem poslání unární zprávy může být dokonce i objekt, který se stane součástí grafického uživatelského rozhraní Squeaku, například bude umístěn na jeho pracovní ploše. Bez dalšího podrobnějšího popisu (k němu se však v tomto seriálu později ještě několikrát vrátíme) si můžete sami vyzkoušet následující demonstrační příklad. Po poslání zprávy se selektorem openAsMorph objektu (příjemci zprávy), jenž je instancí třídy String nebo některého jejího potomka, například ByteString, se na pracovní plochu do určeného místa umístí nový prvek grafického uživatelského rozhraní, s nímž je možné libovolným způsobem manipulovat, podobně jako s jakýmkoli jiným prvkem GUI Squeaku. Lze například provést přesun tohoto objektu, jeho zvětšení, zmenšení, otáčení, vytvoření kopie (klonu) atd. Tento objekt samozřejmě „přežije“ i ukončení virtuálního stroje a jeho opětovné nastartování, a to dokonce i v případě, že je znovuspuštění virtuálního stroje provedeno na zcela odlišné platformě:

'maly testik' openAsMorph

Obrázek 3: Poslání zprávy se selektorem openAsMorph řetězci. Ihned po poslání zprávy se vytvoří nový prvek grafického uživatelského rozhraní, který lze umístit pomocí myši na pracovní plochu.

Obrázek 4: S objektem umístěným na pracovní plochu lze manipulovat stejným způsobem, jako s jakýmkoli jiným objektem, například oknem. K objektu je samozřejmě také přiřazené kontextové menu i „obrázkové“ menu.

3. Zřetězení unárních zpráv

Vzhledem k tomu, že výsledkem poslání zprávy jejímu příjemci je vznik (většinou nového) objektu, je možné zprávy za sebou jednoduše zřetězit bez toho, aby se mezivýsledné objekty vzniklé voláním zpráv musely ukládat do pojmenovaných proměnných. Syntakticky se zřetězení zpráv podobá například volání uživatelských nebo systémových slov ve Forthu, ale to již trošku odbíháme od tématu. V následujícím demonstračním příkladu se nejdříve pošle zpráva se selektorem factorial příjemci, jenž je malým celým číslem (SmallInteger) a tento objekt zprávu zpracuje takovým způsobem, že vytvoří nový objekt (poněkud větší číslo, konkrétně instanci třídy LargePositive­Integer). Tomuto objektu je následně poslána unární zpráva se selektorem asWords. Příjemce tuto zprávu zpracuje a jako výsledek vrátí řetězec (což je samozřejmě taktéž objekt), který obsahuje slovní vyjádření vypočtené hodnoty (kvůli omezení šířky stránky v prohlížeči jsou do výsledku přidány konce řádků):

42 factorial asWords 'one sexdecillion, four hundred five quindecillion,
six quattuordecillion, one hundred seventeen tredecillion, seven hundred fifty-two duodecillion,
eight hundred seventy-nine undecillion, eight hundred ninety-eight decillion,
five hundred forty-three nonillion, one hundred forty-two octillion, six hundred six septillion,
two hundred forty-four sextillion, five hundred eleven quintillion,
five hundred sixty-nine quadrillion, nine hundred thirty-six trillion,
three hundred eighty-four billion'

Obrázek 5: Poslání unární zprávy se selektorem className různým typům objektů.

V předchozím odstavci jsem bez dalších důkazů tvrdil, že objekt 42 je instancí třídy SmallInteger, zatímco výsledek zprávy 42 factorial je instancí třídy LargePositive­Integer. Toto tvrzení lze velmi jednoduše dokázat, protože každému objektu je možné poslat unární zprávu se selektorem className a objekt (příjemce zprávy) vrátí textovou reprezentaci jména příslušné třídy:

42 className
'SmallInteger'
42 factorial className
'LargePositiveInteger'
'www.root.cz' className
'ByteString'
nil className
'UndefinedObject'

Obrázek 6: Metoda className existuje již ve třídě Object, proto ji dědí i všechny uživatelem vytvořené objekty.

Podobným způsobem se lze pomocí zprávy se selektorem basicType dotazovat na bázový typ objektu (výsledkem je v tomto případě symbol, nikoli řetězec):

42 basicType
#Number
true basicType
#Boolean
'www.root.cz' basicType
#String
nil basicType
#Object

4. Binární zprávy

Druhým typem zpráv, které je možné ve Squeaku použít, jsou takzvané binární zprávy. Jak již název těchto zpráv naznačuje, tyto zprávy pracují s dvojicí objektů. Prvním objektem je příjemce zprávy. Podobně jako u unárních zpráv se jedná o objekt, který zprávu musí přijmout a zpracovat; právě tento objekt tedy rozhoduje o tom, jak bude se zprávou naloženo (to může být zpočátku poněkud matoucí, protože binární zprávy se podobají, jak si ukážeme dále, zápisu aritmetických či logických výrazů, v nichž mají oba operandy binární operace shodný význam). Druhý objekt je použit jako parametr zprávy. Formát zápisu binárních zpráv vypadá následovně: příjemce_zprávy selektor parametr. Zatímco unární zprávy mohly mít takřka libovolně pojmenovaný selektor (nemohly v něm být použity pouze některé znaky se speciálním významem), jména (selektory) binárních zpráv jsou ve Squeaku a taktéž i v dalších dialektech Smalltalku omezena pouze na některé znaky a jejich kombinace, které jsou vypsány v následující tabulce:

Znak
+
*
/
\
~
<
>
=
@
%
|
&
?
,

Následují demonstrační příklady poslání binárních zpráv různým typům objektů. Z toho, že každý objekt může na zprávu se stejným selektorem reagovat různě taktéž vyplývá, že není žádný problém si některé ze selektorů binárních zpráv „přetížit“ ve vlastních třídách:

6 * 7
42
123456 \\ 78
60
true & false
false
true | false
true

Ve třídě Boolean můžeme nalézt metodu pro výpočet logické operace implikace zapisované pomocí znaků ==>:

false ==> false
true
false ==> true
true
true ==> false
false
true ==> true
true

Řetězce, tj. instance třídy String nebo některého potomka této třídy, lze lexikograficky porovnávat:

'www' < 'aaa'
false
'aaa' < 'www'
true
'aaa' == 'www'
false
'aaa' == 'aaa'
true

Obrázek 7: Posílání binárních zpráv různým typům objektů.

5. Pořadí vyhodnocování unárních a binárních zpráv

Podobně jako je možné řetězit unární zprávy (viz třetí kapitola), lze v jednom výrazu kombinovat zprávy unární i binární. Přitom vždy platí, že unární zprávy jsou vyhodnoceny nejdříve (zjednodušeně by se dalo říci, že jsou okolo nich vytvořeny implicitní závorky) a binární zprávy se vyhodnocují zleva doprava, bez ohledu na to, že se znaky používané jako selektory binárních zpráv podobají aritmetickým či logickým operacím, jenž mají rozdílnou prioritu (násobení má vyšší prioritu než sčítání atd.). V případě, že je zapotřebí změnit pořadí volání zpráv, lze pro tento účel použít kulaté závorky. V následujících příkladech je ukázán rozdíl mezi běžnými aritmetickými výrazy (které ve skutečnosti Squeak vůbec nezná a v podstatě ani znát nepotřebuje) a voláním binárních zpráv, popř. kombinace zpráv unárních a binárních. Povšimněte si především toho, že v prvních několika výrazech není brána v potaz priorita binárních zpráv, které se vyhodnotí, tj. postupně zavolají tak, jak jsou zapsány – zleva doprava:

2 + 4 * 10
60
(2 + 4) * 10
60
2 + (4 * 10)
42
2 + 3 factorial
8
(2 + 3) factorial
120
3 factorial + 2
8

Obrázek 8: Výsledek volání různých kombinací unárních a binárních zpráv.

Ve chvíli, kdy zapomeneme na to, že ve Squeaku neexistují aritmetické a logické operace, ale „pouze“ posílání zpráv s pevně daným pořadím vyhodnocování, můžeme v programu použít zdánlivě korektní výraz, který však ve skutečnosti povede k chybě. Jeden z typických chybně zapsaných výrazů je například: 42 == 2 + (4 * 10). Tento zápis totiž znamená poslání zprávy se selektorem ==, jejímž příjemcem je objekt 42 a parametrem objekt 2. Výsledkem je objekt false, který je příjemcem zprávy se selektorem +… – a právě zde dojde k chybě, protože objekt false nedokáže na tuto zprávu korektně zareagovat. Náprava je snadná – buď je možné prohodit pořadí zpráv nebo lze použít závorky:

42 == 2 + (4 * 10)
" chyba - objekt typu Boolean nedokáže zpracovat zprávu se selektorem + "
2 + (4 * 10) == 42
true
42 == (2 + (4 * 10))
true

Obrázek 9: Výsledek pokusu o vyhodnocení výrazu 42 == 2 + (4 * 10).

6. Zprávy s obecným počtem parametrů

Třetím a současně i posledním typem zpráv, pomocí nichž mohou objekty ve Squeaku (nebo i jiném dialektu programovacího jazyka Smalltalk) navzájem komunikovat, jsou zprávy s proměnným počtem parametrů, někdy také nazývané keyword messages. V těchto zprávách může být použito libovolné množství klíčových slov ukončených dvojtečkou, přičemž za každým klíčovým slovem následuje parametr. To mj. znamená, že počet parametrů zprávy odpovídá počtu použitých klíčových slov. Selektorem těchto zpráv jsou všechna klíčová slova. Tento typ zpráv má nejnižší prioritu, což znamená, že nejdříve jsou vyhodnoceny zprávy unární, posléze zprávy binární a teprve poté zprávy s proměnným počtem parametrů (samozřejmě je možné v případě potřeby použít závorky, které pořadí volání zpráv mění). Porovnání syntaxe binární zprávy (popsané v předchozích kapitolách) a zprávy s proměnným počtem parametrů je zobrazeno na desátém obrázku.

Obrázek 10: Syntaxe binární zprávy a zprávy s proměnným počtem parametrů.

Příklady zpráv používajících klíčová slova:

42 gcd: 123456
6
1024 log: 2
10.0
42 raisedTo: 42
150130937545296572356771972164254457814047970568738777235893533016064
42 between: 0 and: 100
true
42 between: 100 and: 200
false

V posledních dvou příkladech je between:and: metoda definovaná ve třídě Magnitude, která je předkem tříd Integer a SmallInteger.

7. Nejčastější problémy při zápisu zpráv s obecným počtem parametrů

Při používání zpráv s proměnným počtem parametrů je nutné si uvědomit, že se příjemci zprávy skutečně posílá celá zpráva, jejíž selektor je složen ze všech klíčových slov a počet parametrů odpovídá počtu těchto slov. To například znamená, že následující zápis:

2 raisedTo: 3 raisedTo: 4

Squeak pochopí tak, že se objektu 2 (tj. instanci třídy SmallInteger) posílá zpráva se selektorem raisedTo:raised­To: a s parametry 3 a 4; tudíž dojde při pokusu o vyhodnocení tohoto výrazu k chybě, pokud si tedy sami nerozšíříme chování třídy SmallInteger takovým způsobem, aby dokázala tuto zprávu korektně zpracovat. Náprava je v tomto případě jednoduchá – v závislosti na tom, jakou aritmetickou operaci máme skutečně na mysli (zda 2(34) nebo (23)4), je nutné použít uzávorkování:

2 raisedTo: (3 raisedTo: 4)
2417851639229258349412352
(2 raisedTo: 3) raisedTo: 4
4096

8. Programové bloky

Poslední vlastností Squeaku, o které se dnes zmíníme, je podpora takzvaných programových bloků, bez nichž by například nebylo možné tvořit programové smyčky ani struktury s podmínkami (tyto řídicí struktury ve Squeaku neexistují jako samostatná syntaktická kategorie právě díky tomu, že se dají nahradit pomocí bloků). Programové bloky se skládají z nepovinných parametrů následovaných posloupností výrazů. Ze sémantického hlediska se programový blok chová jako uzávěr (closure), který je (ve Squeaku) považován za plnohodnotný objekt. To mj. znamená, že bloku lze posílat různé zprávy a blok může vystupovat jako parametr zpráv, což je v mnoha případech důležitější vlastnost. Z hlediska syntaktického je blok uzavřen do hranatých závorek [] a jeho případné parametry jsou od těla bloku (seznamu výrazů) odděleny pomocí znaku roury (pipe, |). Pokud blok žádné parametry nemá, není použit ani oddělovač. Následuje příklad jednoduchého bloku bez parametrů:

[ 6 * 7 ]

Jak jsme si již řekli v předchozím odstavci, lze blokům posílat zprávy. V následujících příkladech je ukázáno, jak lze blok vyhodnotit (zavolat výrazy, které se v jeho těle nachází), jak lze zjistit, kolikrát se blok vyhodnotí za 5 sekund (jednoduchý benchmark), jak dlouho trvá jedno vyhodnocení bloku (v tomto případě prakticky neměřitelné) a jak lze vytvořit nekonečnou smyčku (prakticky měřitelné :-)

widgety

[ 6 * 7 ] value
42
[ 6 * 7 ] bench
'722571.4857028595 per second.'
[ 6 * 7 ] durationToRun
0:00:00:00
[ 6 * 7 ] repeat
" není dobrý nápad tento kód spouštět, protože blok"
" neobsahuje explicitiní příkaz pro jeho zastavení"

Programový blok může vystupovat jako parametr nějaké zprávy, čehož se poměrně často využívá například při programování smyček nebo struktur s podmínkami. Na následujících příkladech je ukázáno, jak lze využít zprávy se selektorem ifTrue: a ifFalse:, které jsou implementovány jako metody ve třídách Boolean, True a False, pro tvorbu části kódu, jenž se provede pouze v případě splnění či naopak nesplnění nějaké podmínky:

true ifFalse: [ 6 * 7 ]
nil
false ifFalse: [ 6 * 7 ]
42
1 == 1 ifFalse: [ 6 * 7 ]
nil
1 == 2 ifFalse: [ 6 * 7 ]
42
true ifTrue: [ 6 * 7 ]
42
false ifTrue: [ 6 * 7 ]
nil
1 == 1 ifTrue: [ 6 * 7 ]
42
1 == 2 ifTrue: [ 6 * 7 ]
nil

Podrobnější informace o použití bloků, které tvoří jednu z nejzajímavějších částí Squeaku, si uvedeme příště.

9. Odkazy na Internetu

  1. Squeak home page
    http://www.squ­eak.org/
  2. XO: The Children's Machine
    http://wiki.lap­top.org/go/The_Chil­dren's_Machine
  3. Squeak na Wikipedii EN
    http://en.wiki­pedia.org/wiki/Squ­eak
  4. Squeak na Wikipedii CZ
    http://cs.wiki­pedia.org/wiki/Squ­eak
  5. Squeak by Example
    http://squeak­byexample.org/
  6. Squeak Land
    http://www.squ­eakland.org/
  7. SqueakNotes
    http://squeak­.zwiki.org/Squ­eakNotes
  8. Squeak FAQ
    http://wiki.squ­eak.org/squeak/471
  9. Learning Squeak
    http://c2.com/cgi/wi­ki?LearningSqu­eak
  10. Scratch home page
    http://scratch­.mit.edu/
  11. Scratch (programming language)
    http://en.wiki­pedia.org/wiki/Scrat­ch_(programmin­g_language)
  12. Lazarus (Software)
    http://en.wiki­pedia.org/wiki/La­zarus_%28softwa­re%29
  13. FreePascal
    http://www.fre­epascal.org/
  14. „Why I Love Python“ slides
    http://www.min­dviewinc.com/dow­nloads/pub/ec­kel/LovePython­.zip
  15. „Why I love Python“ (presentation)
    http://www.sli­deshare.net/di­dip/why-i-love-python
  16. První jazyk: Python
    http://macek.san­dbox.cz/texty/prvni-jazyk-python/
  17. Programovací jazyk Python
    http://www.py­.cz/FrontPage
  18. Python – Wikipedia CS
    http://cs.wiki­pedia.org/wiki/Pyt­hon
  19. IPython
    http://en.wiki­pedia.org/wiki/I­python
  20. IPython: an interactive computing environment
    http://ipython­.scipy.org/mo­in/
  21. Category:Python
    http://rosetta­code.org/wiki/Ca­tegory:Python
  22. Educational programming language
    http://en.wiki­pedia.org/wiki/E­ducational_pro­gramming_langu­age
  23. Seriál Letní škola programovacího jazyka Logo
    http://www.ro­ot.cz/serialy/let­ni-skola-programovaciho-jazyka-logo/
  24. Logo Tree Project:
    http://www.eli­ca.net/downlo­ad/papers/Logo­TreeProject.pdf
  25. Language Poster (O'Reilly):
    http://www.ore­illy.com/news/grap­hics/prog_lan­g_poster.pdf
  26. Informace o Comenius Logu:
    http://www.com­logo.input.sk/in­dex.html
  27. Stránka nabízející stažení Comenius Loga:
    http://www.com­logo.input.sk/nas­tiahnutie.html
  28. Seminární práce o Comenius Logu:
    http://nwit.ped­f.cuni.cz/rotal9ap/lo­go/
  29. Informace o LEGO/Logu:
    http://educati­on.otago.ac.nz/nzlnet/L­ogo/legologo.html
  30. Informace o systému Elica:
    http://www.eli­ca.net/site/in­dex.html
  31. Informace o systému NetLogo:
    http://ccl.nor­thwestern.edu/ne­tlogo/
  32. Stažení NetLoga:
    http://ccl.nor­thwestern.edu/ne­tlogo/download­.shtml
  33. Uživatelský manuál NetLoga ve formátu PDF:
    http://ccl.nor­thwestern.edu/ne­tlogo/docs/Net­Logo%20User%20Ma­nual.pdf
  34. NetLogo FAQ:
    http://ccl.nor­thwestern.edu/ne­tlogo/docs/faq­.html
  35. Domácí stránka Daniela Azumy (autora implementace Turtle Tracks):
    http://alumnus­.caltech.edu/~da­zuma/home/
  36. Informace o aUCBLogu:
    http://www.phy­sik.uni-augsburg.de/~miche­ler/
  37. Domácí stránka MSW Loga:
    http://www.sof­tronix.com/lo­go.html
  38. Karel online
    http://karel.ol­dium.net/
  39. EDU-SIG: Python in Education
    http://www.pyt­hon.org/commu­nity/sigs/curren­t/edu-sig/
  40. Guido van Robot
    http://en.wiki­pedia.org/wiki/Gu­ido_van_Robot
  41. The Guido van Robot Programming Language
    http://gvr.sou­rceforge.net/
  42. An Introduction to Programming with Karel J. Robot
    http://blog.thin­goid.com/2003/10­/karel-intro/
  43. Teaching a young robot new tricks
    http://blog.thin­goid.com/2003/11­/karel-new-tricks/
  44. Karel and Company – More Robots
    http://blog.thin­goid.com/2003/12­/karel-and-company/
  45. Karel heads for the stars
    http://blog.thin­goid.com/2004/03­/karel-star/
  46. Karel programming language documentation
    http://mormegil­.wz.cz/prog/ka­rel/prog_doc.htm
  47. Karel J. Robot
    http://www.ma­inlandregional­.net/dklipp/Ho­nors%20Computer%20Sci­ence%20Java.htm
  48. Karel (programming language)
    http://en.wiki­pedia.org/wiki/Ka­rel_(programmin­g_language)
  49. Richard E. Pattis
    http://en.wiki­pedia.org/wiki/Richar­d_E._Pattis
  50. XKarel home page
    http://xkarel­.sourceforge.net/en­g/
  51. XKarel – screenshoty oken
    http://xkarel­.sourceforge.net/en­g/program.php#Ok­na
  52. Greenfoot
    http://www.gre­enfoot.org/abou­t/whatis.html
  53. Computer programming – Educational programming languages
    http://www.kid­slike.info/com­puter_program­ming_educatio­nal_programmin­g_languages
  54. Making Great Programmers: Why BASIC is Still Relevant
    http://kidbasic­.sourceforge.net/en/why­.html
  55. Gambas Wiki
    http://en.wiki­books.org/wiki/Gam­bas
  56. Free tool offers ‚easy‘ coding
    http://news.bbc­.co.uk/2/hi/tec­hnology/6647011­.stm
  57. Scratch Lowers Resistance to Programming
    http://www.wi­red.com/gadge­tlab/2009/03/scrat­ch-lowers/
  58. Základy želví grafiky
    http://www.ro­ot.cz/clanky/za­klady-zelvi-grafiky/
  59. Bill Kendrick's Web Turtle
    http://www.so­nic.net/~nbs/web­turtle/
Našli jste v článku chybu?
Lupa.cz: Proč jsou firemní počítače pomalé?

Proč jsou firemní počítače pomalé?

120na80.cz: Pálení žáhy: která jídla ne a co nás uzdraví?

Pálení žáhy: která jídla ne a co nás uzdraví?

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

Lupa.cz: Další Češi si nechali vložit do těla čip

Další Češi si nechali vložit do těla čip

Lupa.cz: Jak levné procesory změnily svět?

Jak levné procesory změnily svět?

Vitalia.cz: Tahák, jak vyzrát nad zápachem z úst

Tahák, jak vyzrát nad zápachem z úst

Vitalia.cz: Test dětských svačinek: Tyhle ne!

Test dětských svačinek: Tyhle ne!

Vitalia.cz: Jsou vegani a vyrábějí nemléko

Jsou vegani a vyrábějí nemléko

DigiZone.cz: Funbox 4K v DVB-T2 má ostrý provoz

Funbox 4K v DVB-T2 má ostrý provoz

DigiZone.cz: Numan Two: rozhlasový přijímač s CD

Numan Two: rozhlasový přijímač s CD

Podnikatel.cz: Instalatér, malíř a elektrikář. "Vymřou"?

Instalatér, malíř a elektrikář. "Vymřou"?

Vitalia.cz: dTest odhalil ten nejlepší kečup

dTest odhalil ten nejlepší kečup

120na80.cz: Co je padesátkrát sladší než cukr?

Co je padesátkrát sladší než cukr?

Podnikatel.cz: Tyto pojmy k #EET byste měli znát

Tyto pojmy k #EET byste měli znát

Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

Vitalia.cz: 5 chyb, které děláme při skladování potravin

5 chyb, které děláme při skladování potravin

Podnikatel.cz: Letáky? Lidi zuří, ale ony stále fungují

Letáky? Lidi zuří, ale ony stále fungují

Vitalia.cz: Fyzioterapeutka: Chůze naboso? Rozhodně ano!

Fyzioterapeutka: Chůze naboso? Rozhodně ano!

DigiZone.cz: Parlamentní listy: kde končí PR...

Parlamentní listy: kde končí PR...

Lupa.cz: Jak se prodává firma za miliardu?

Jak se prodává firma za miliardu?