LINUXZONE






 >> Hlavní stránka

(1713/30.07.2010)


 >> Administrace

(160/29.07.2010)


 >> Literatura

(305/28.07.2010)


 >> Bezpečnost

(340/30.07.2010)


 >> Programování

(307/19.04.2010)


 >> Distribuce

(97/09.06.2010)


 >> Síťování

(86/03.06.2010)


 >> Lokalizace

(10/15.09.2004)


 >> Aplikace

(175/12.04.2010)


 >> Multimedia

(32/31.03.2006)


 >> Hardware

(45/02.03.2007)


 >> Začínáme

(228/24.06.2010)


 >> Aktuálně

(556/27.07.2010)


 >> RELAX

(201/26.07.2010)


 >> Jinde vyšlo

přehled ostatních serverů




 Přihlášení




Login:
Heslo:
 uložit v prohlížeči


Nejste-li ješte zaregistrováni, můžete tak učinit zde.





 Vyhledávání




Hledaný výraz:
v klíčových slovech
v titulku
v anotaci
v textu








 Reklama









 Servis




*   Vaše náměty a připomínky
Máte k Linuxzone.cz nějaké připomínky nebo náměty? Našli jste na stránkách chybu? Dejte nám o tom vědět pomocí formuláře nebo v diskuzi.
Komentářů: 30
*   Podpořte Linuxzone.cz
Chcete podpořit náš server umístěním odkazu nebo zveřejněním backendu? Zde najdete vše potřebné.
*   Pište pro Linuxzone.cz
Máte zájem podílet se na obsahu Linuxzone.cz ať už jako redaktoři nebo i jinak? Dejte nám o sobě vědět!





 Aktuálně z bezpečnosti




-- 
6.12.2005, 19:01
Na serveru informit.com vyšla ukázková kapitola týkající se práce s řetězci z knihy Secure Coding in C and C++. (lz)

-- 
3.12.2005, 12:34
Bugtraq: Format String Vulnerabilities in Perl Programs. (lz)

-- 
3.12.2005, 12:32
Linux Advisory Watch December 2nd 2005. (lz)

-- 
23.10.2005, 13:28
Rozhovor na téma klasické zálohování versus CDP. (lz)

-- 
23.10.2005, 13:24
Linux Advisory Watch October 21st 2005. (lz)

další >>





 Aktuálně o software




-- 
6.12.2005, 19:07
Potřebujete-li pod linuxem rozchodit bezdrát založený na čipsetech Broadcom 43xx, konečně existuje linuxový ovladač. (lz)

-- 
6.12.2005, 19:04
Byla uvolněna verze Xen 3.0.0 virtualizační technologie XEN. (lz)

-- 
6.12.2005, 18:59
Byla uvolněna verze X11R6.9/X11R7 RC 3 grafickérho rozhraní X Window System. (lz)

-- 
3.12.2005, 12:45
Co je nového okolo projektu Amanda (open source zálohovací software)? Více na osnews.com. (lz)

-- 
3.12.2005, 12:40
Jak to akuálně v linuxu vypadá s podporou SATA.. (lz)

další >>





 Aktuálně z IT




-- 
3.12.2005, 12:51
Novellu se daří prodej linuxových produktů, oproti loňskému roku se Novell dočkal výrazného nárůstu. (lz)

-- 
3.12.2005, 12:48
Třetí verzi licence GPL by měla být publikována během jara 2007. (lz)

-- 
23.10.2005, 13:20
V Peru nyní mají zákon, který umožňuje nasazení open source software ve vládní správě. (lz)

-- 
23.10.2005, 13:14
Proč se Microsoft bojí Google? (lz)

-- 
27.9.2005, 22:01
Peru má zákon podporující free software. (lz)

další >>





 Nejčtenější články




-- 
Hurd včera dnes a zítra

-- 
XEN aneb virtualizujeme (3/6)

-- 
Security Digest (15/2010)

-- 
Fotografický ateliér

-- 
XEN aneb virtualizujeme (4/6)

-- 
Novinky ze světa svobodného software (16/2010)

-- 
Gamesárium [138]

-- 
Proč používat svobodný software?

-- 
Velká kniha sportovní fotografie

-- 
Security Digest (16/2010)






 Nejlepší články




-- 
Gamesárium [138]

-- 
XEN aneb virtualizujeme (4/6)

-- 
Datové struktury bez předchozích znalostí

-- 
XEN aneb virtualizujeme (3/6)

-- 
Security Digest (16/2010)

-- 
Novinky ze světa svobodného software (17/2010)

-- 
Velká kniha sportovní fotografie

-- 
XEN aneb virtualizujeme (5/6)

-- 
Security Digest (15/2010)

-- 
Proč používat svobodný software?






 Anketa




Používáte nějaké rozšíření bezpečnostního modelu linuxového jádra?

Openwall (18%)

LIDS (12%)

Pax/Grsecurity (3%)

SELinux (6%)

RSBAC (1%)

jiné (1%)

používám standardní jádro (59%)







Linuxzone.cz - server o Linuxu pro programátory, administrátory a fanoušky.
Provozuje společnost Impossible.
ISSN: 1213-8738





Kouzlo maker

Proč céčkoví programátoři při příchodu objektově orientovaného programování museli vymýšlet nové programovací jazyky? Proč kvůli zavedení operátoru if-then-else v Pythonu probíhaly sáhodlouhé debaty na vývojářském mailing listu? Proč v Javě musíme neustále opisovat tytéž programové konstrukce? Odpověď je jednoduchá: V těchto prostředích chybí kvalitní makra.

Co jsou makra?

Každý programovací jazyk disponuje určitou množinou programových konstrukcí, pomocí kterých lze instruovat počítač k provádění kýžené činnosti. V mnoha programovacích jazycích existují situace, kdy je užitečné nebo dokonce nezbytné provádět před překladem kódu jeho přepis. K tomuto účelu slouží makra, která provádí transformaci kódu ještě před jeho překladem. Výsledkem aplikace maker na zdrojový kód je opět zdrojový kód v daném programovacím jazyce.

Člověka mohou napadat otázky jako k čemu je užitečné přepisovat zdrojový kód a proč na tuto činnost nelze použít obecný makroprocesor. Pokusme se tedy na problematiku maker podívat trochu podrobněji.

Jazyky bez maker

Některé jazyky nedisponují standardními prostředky pro práci s makry vůbec. Příkladem takových jazyků může být Python nebo Java. U těchto jazyků narazíme na překážky již velmi brzy.

Co kdybychom si kupříkladu chtěli definovat nový příkaz until, který je analogický příkazu while až na to, že řídící podmínku příkazu neguje? Bez použití run-time kompilace a předávání kódu v řetězcích nebo zavádění pomocných funkcí pro každou novou podmínku v until to prostě nejde. Přitom by stačilo mít prostředek na prostý textový přepis v Pythonu

  until -> while not

nebo v Javě

  until (condition) -> while (! (condition))

Prosté zavedení funkce until není možné, protože jí není možno dostatečně jednoduchým způsobem předat podmínku bez jejího okamžitého vyhodnocení a protože jí lze předat pouze výraz, nikoliv libovolnou sekvenci příkazů (to je již nedostatek programovacího jazyka). Museli bychom si pomoci obezličkami, které by celou věc zkomplikovaly a triviální účel zavedení příkazu until znehodnotily.

Dalším příkladem překážky, k jejímuž překonání chybí makra, může být nemožnost ošetření absence operátoru if-then-else. Přestože Python i Java samozřejmě disponují programovou konstrukcí if-then-else, tato konstrukce není výrazem a tudíž nemůže vracet hodnotu. Potřebujeme-li vyhodnocovat podmíněné výrazy, musíme si pomáhat pomocnými proměnnými a chtě nechtě tak patřičně navýšit počet řádků kódu svého programu. Co bychom například v jazyce C zapsali jednoduše jako

  some_function (x >= 0 ? x : -x)

musíme v Javě (pokud by na konkrétní operaci neexistovala knihovní funkce) zapsat jako

  {
    int abs_x;
    if (x >= 0)
      abs_x = x;
    else
      abs_x = -x;
    some_function (abs_x);
  }

Zkušený programátor toto obvykle nedělá a zřídí si raději pro výpočet použitého podmíněného výrazu pomocnou funkci. Tím se ale nadbytečné řádky programu jen přesunou jinam. Jak si zřizování pomocné funkce pro každou, v programu byť jen jedinkrát použitou, programovou konstrukci ušetřit?

Logickým opatřením by byla definice funkce if_:

  Object if_ (bool condition, Object then_, Object else_)
  {
    Object result;
    if (condition)
      result = then_;
    else
      result = else_;
    return result;
  }

abychom mohli psát

  some_function ((Integer) if_ (x >= 0, x, -x));

Nutnost přetypování výsledku if_ sice trochu ztrácí eleganci, omezení typů argumentů if_ na objekty a jejich chybějící typové kontroly již působí určité potíže, nicméně nejpodstatnějším problémem je něco jiného. Při takovém if_ totiž dochází během předávání argumentů k vyhodnocení obou částí podmínky, nezávisle na tom, která z nich se ve skutečnosti nakonec použije. Počítá se tak zbytečně i to, co by se počítač nemuselo, ba hůře, někdy takový podmínkový výraz nefunguje vůbec:

  if_ (x == 0, null, 1/x);

Uvedenou funkcí if_ dělení nulou neošetříme, musí nastoupit transformace zdrojového kódu. Tím jsme v podobných bezmakrových jazycích v koncích a nezbývá než aby kód programu bobtnal a bobtnal způsoby naznačenými výše.

Nyní je zřejmé, proč je potřeba při zavádění operátoru if-then-else v Pythonu debatovat o jeho syntaxi, místo aby se triviálně zadefinoval. A proč programátoři v Javě skřípou zubama, když již posté píšou

  {
    int result;
    if ( ...

C preprocesor

Patrně nejznámějším makroprocesorem spjatým s konkrétním programovacím jazykem je cpp, kterým je standardně vybaven programovací jazyk C. S jeho využitím je v C zavedení příkazu until zcela bezproblémové:

  #define until(condition) while (! (condition))

To je možné proto, že cpp provádí substituci zdrojového kódu, tj. při "vyhodnocování" podmínky nedochází k vyhodnocování výrazu. Definice makra představuje jen prosté zestručnění programového zápisu, což je to, co obvykle programátor chce a k čemu makra stejně jako ostatní programátorské prostředky slouží.

if_ však již opět narazíme, protože se neobejdeme bez použití vestavěného operátoru ?:. Kdybychom tento operátor neměli, cpp by nám nepomohlo. Lze sice zestručnit alespoň podmíněné přiřazení

  #define if_(result_var, condition, then_, else_) \
  {\
    int __tmp;\
    if (condition)\
      __tmp = (then_);\
    else\
      __tmp = (else_);\
    result_var = __tmp;\
  }

a psát

  if_ (y, x == 0, INFINITY, 1/x);

ne však již něco jako

  some_function (if_ (_, x >= 0, x, -x));

protože v argumentu volání funkce nemůžeme použít bloky uzavřené v složených závorkách. To je ovšem zatím více nedostatek jazyka C než cpp.

Hlavním nedostatkem samotného cpp je, že neumí provádět libovolný přepis a není plně integrováno s C. To se projeví například v situaci, kdy bychom v C chtěli zavést programovou konstrukci with známou z Pascalu, která umožňuje stručnější přístup k položkám struktury, přímo jejich jmény, bez uvádění jména proměnné struktury. cpp nemá žádnou možnost zjistit, jaké členy daná struktura má. Jiným projevem téhož je nemožnost provádět v cpp složitější operace, takže po něm například nelze chtít věci jako určování statického seznamu předků třídy, pokud bychom si rádi makry pomohli při konstrukci nějakého systému objektově orientovaného programování v C.

A proto C podporu pro objektově orientované programování nemá. Objektově orientované programování v C sice provozovat lze, avšak jen přespříliš ukecaně. Potřebná zestručnění jsou totiž, s ohledem na omezené možnosti cpp, nemožná.

K čemu jsou dobrá makra?

Jak jsme viděli, makra mohou být nezbytná pro definování nových programových konstrukcí. Různé programovací jazyky je mohou využívat pro různé účely. V obecnosti lze makra slušným způsobem typicky využít v následujících situacích:

  • Transformace argumentů. Pokud by v C nebyl příkaz for a chtěli bychom ho definovat v obvyklé syntaxi, jednalo by se o funkci jediného argumentu se třemi složkami odděleným středníkem. Takový argument je nutno ošetřit speciálním postupem.
  • Předávání identifikátorů. Potřebujeme-li kód, který pracuje přímo s identifikátory, například zmíněné with, musíme použít makro, neboť funkcím lze předávat jen hodnoty.
  • Podmíněné vyhodnocení argumentů. Jedná se o uváděné if_, kdy chceme podmíněně vyhodnotit jen některý z argumentů, v závislosti na podmínce.
  • Opakované vyhodnocení argumentů. Příkladem může být until, kdy je předanou podmínku nutno vyhodnocovat opakovaně, ne právě jednou, jak by se stalo při předání argumentu funkci.

Jednou z oblíbených aplikací maker v jazyce C je také podmíněný překlad. Můžeme například psát

  #ifdef HAVE_SPECIAL_FOO
  x = special_foo (y);
  #else
  x = foo (y);
  #endif

a použít tak potenciálně dostupnou vylepšenou funkci. Tato aplikace maker je diskutabilní, protože k ní makra vlastně nepotřebujeme:

  if (HAVE_SPECIAL_FOO)
    x = special_foo (y);
  else
    x = foo (y);

Solidní překladač by měl konstantní výraz HAVE_SPECIAL_FOO vyhodnotit již v době překladu a nepoužitý kód vůbec nezpracovávat. Drobná potíž je ovšem v tom, že solidní překladač by vás měl při té příležitosti na zahozený kód navíc upozornit, což v daném případě není to co chceme. Chceme-li se tedy zde obejít bez maker, musíme se obejít i bez kompletního komfortu vývojového prostředí.

Ještě dodejme, jaké mohou být méně slušné aplikace maker. Nejtypičtější z nich je inlinování kódu. Tuto věc má zvládnout kvalitní překladač, a proto bychom neměli psát věci jako

  #define MY_CONSTANT 123

místo

  const int my_constant = 123;

nebo

  #define abs(x) ((x) >= 0 ? (x) : (-(x)))

místo

  int abs (x)
  {
    return (x >= 0 ? x : -x);
  }

přestože konkrétně v jazyce C může mít definice makra abs určité opodstatnění s ohledem na jinak těžkopádnou práci s číselnými typy.

Dalším méně slušným použitím maker je provedení výpočtu v době kompilace. Například můžeme mít funkci počítající součet druhých mocnin svých argumentů, které jsou konstantami známými v době překladu. Méně kvalitní překladač může výpočet odložit do doby běhu programu, zatímco pokud je součet počítán makrem, je vynuceno jeho provedení již v době expanze makra, tj. před překladem programu.

A konečně může jít o využívání smluveného identifikátoru. Pokud například na mnoha místech používáme proměné nazvané connection a result a často s nimi provádíme nějakou operaci, můžeme si definovat

  #define op_connection result = op (connection)

a potom místo

  result = op (connection);

stručněji psát

  op_connection;

Takové programové konstrukce jistě nejsou příliš vhodné k obecnému užívání, ale občas se mohou hodit.

Proč ne obecný preprocesor?

Díky tomu že se při aplikaci maker často jedná jen o textový přepis kódu, mohli bychom se v jazycích, které makra zcela postrádají, pokusit použít nějaký obecný makroprocesor, například m4. V řadě situací by to fungovalo a mnohdy může jít o postačující řešení, leč ve vší obecnosti se potížím nevyhneme. Makroprocesor neznalý syntaxe konkrétního programovacího jazyka se může dopouštět nepříjemných omylů. Například mu nemusí být jasný rozdíl mezi until v programovém kódu a until v anglickém textu tištěném na výstup. Pak se dočkáme makroexpanze na místech, kde k ní rozhodně docházet nemá.

Kromě toho není příliš elegantní, je-li syntaxe makroprocesoru odlišná od syntaxe jazyka. Má-li programovací jazyk rozumnou syntaxi, lze místo textové substituce mnohem čistěji používat substituci programových konstrukcí za jiné programové konstrukce, přičemž makro není nic jiného než malý program v tomtéž programovacím jazyce. Pak makra s programovacím jazykem naprosto splynou a není třeba se učit jazyky dva. cpp je v tomto směru polovičaté, m4 již zcela od jazyka oddělené.

Z těchto důvodů je žádoucí, aby makroprocesor byl přímo součástí daného programovacího jazyka a postupy přepisu maker byly zapisovány také přímo v tomto jazyce.

Read macros

Makry zhýčkaný programátor může zajít ještě dále a požadovat komplikovanější formy zápisu. Představme si, že máme program, který velmi často pracuje s dvojicemi. Rádi bychom je zapisovali co nejstručnějším způsobem a přitom bychom se nechtěli vázat na jejich nějakou konkrétní implementaci. Takže nám nevyhovuje ani zápis typu

  Pair (x, y)

který je příliš upovídaný, ani třeba zápis pomocí seznamů, který by vyžadoval implementaci dvojic právě prostřednictvím seznamů. Místo toho by se nám líbil třeba zápis pomocí hranatých závorek

  [x, y]

samozřejmě za předpokladu, že hranaté závorky již nejsou využity jinak.

V dosažení kýženého nám pomohou tzv. read macros. Ta umožňují definovat, že pokud parser programového kódu narazí na symbol [ (nebo kterýkoliv jiný, pro který definujeme nějaké read macro), má zavolat funkci danému read macro programátorem přiřazenou, která zpracuje následující libovolnou část vstupu a vrátí odpovídající konstrukci v normální podobě programovacího jazyka. Pro náš příklad dvojic zapisovaných pomocí hranatých závorek by ona čtecí funkce po svém vyvolání mohla rekurzivně zavolat parser pro načtení argumentu x, načetla by čárku, opět zavolala parser pro načtení argumentu y, zkontrolovala uzavírací hranatou závorku a vrátila přepis

  Pair (x, y)

Je to vůbec možné?

Čtenář se možná v tuto chvíli ptá, zda výše popsané vůbec někde může reálně fungovat. Ano, může a funguje. Všechny uvedené požadavky na makra splňují lispové programovací jazyky. Právě makra jsou, spolu s absencí rozlišování programových konstrukcí na výrazy, příkazy a unární, binární, ternární, atd. operátory, příčinou nesmírné obliby Lispu mezi určitou skupinou programátorů. A z téže příčiny nemá Lisp problémy ani s operátorem if-then-else ani s doplněním objektově orientovaného programování bez nutnosti změny či doplnění jazyka. Makra v Lispu fungují jako jakási kouzelná hůlka, umožňující jazyk proměnit do mnoha různých a předem netušených forem.

Makra jsou nesporně velmi zajímavým a mocným programátorským nástrojem. Budu rád, když čtenáři znalí jiných prostředí s plnohodnotnými makroprocesory nebo s prostředky makra nahrazujícími v diskusi k článku přispějí příklady takových prostředí a dalšími příklady využití maker nebo podobných nástrojů.

Na závěr poznamenejme, že příklady maker uváděné v článku jsou triviální. Skutečné smysluplné využití maker často spočívá v definicích velmi komplikovaných konstrukcí, které mnohdy představují něco jako nový jazyk v jazyce.

Autor: Milan Zamazal, 15. 08. 2003, 00:00
Sekce Programování, Komentářů: 15
Průměrné hodnocení: 2,92

o Poslat e-mailem
o Tisk článku
o Uložit do profilu


 Přispějte nám




Líbil se Vám tento článek? Můžete ho ocenit zavoláním na tel. číslo 906 460 134.
Cena hovoru za 1 minutu je 46 Kč.





 Hodnocení článku




Článek hodnotím jako:  [1] výborný   [2] dobrý   [3] průměr   [4] špatný   [5] hrůza  





 Komentáře




--

Tiger, 08. 10. 2004 23:09
RE: Re: Crackerům k radosti












--

Milan Zamazal, 08. 10. 2004 10:31
Re: Crackerům k radosti












--

Tiger, 07. 10. 2004 23:54
Crackerům k radosti












--

Milan Zamazal, 07. 10. 2004 22:14
Re: Crackerům k radosti












--

Tiger, 07. 10. 2004 21:29
Crackerům k radosti












--

deda.jabko, 01. 09. 2003 18:39
Scheme rulez












--

Milan Zamazal, 19. 08. 2003 13:42
Re: Makra v Javě












--

Milan Zamazal, 19. 08. 2003 13:36
Re: Makra v Javě












--

Petr Adamek, 19. 08. 2003 11:50
Makra v Javě












--

Milan Zamazal, 15. 08. 2003 15:58
Re: Java a if-then-else












--

Jarda, 15. 08. 2003 13:14
Java a if-then-else












--

Milan Zamazal, 15. 08. 2003 11:48
Re: Makra












--

Milan Zamazal, 15. 08. 2003 11:32
Re: Doplňování kódu












--

Yeti, 15. 08. 2003 10:22
Makra












--

Franta Jetel, 15. 08. 2003 10:15
Doplňování kódu















PŘIDAT KOMENTÁŘ ZOBRAZ VŠE >>










2002 © Impossible, s.r.o.   >> Kontaktujte redakci >> Právní upozornění >> Reklama