Programowanie w języku Rust
Programowanie w języku Rust to oficjalna książka na temat Rusta: języka programowania na licencji open source, który pozwala nam szybciej pisać niezawodne o
programowanie. Rust daje możliwość kontrolowania szczegółów niskiego poziomu (jak wykorzystanie pamięci) w połączeniu z ergonomią wysokiego poziomu, eliminując kłopoty tradycyjnie związane z językami niskiego poziomu.
W książce Programowanie w języku Rust dwaj członkowie Rust Core Team pokazują, jak w pełni korzystać z właściwości Rusta – od instalacji po tworzenie własnych niezawodnych i skalowalnych programów.
Zaczynamy od podstaw, takich jak tworzenie funkcji, wybieranie typów danych i wiązanie zmiennych i przechodzimy następnie do bardziej zaawansowanych pojęć takich jak:
posiadanie i pożyczanie, czasy życia i cechy bezpieczeństwo pamięci Rusta, które gwarantuje budowanie szybkich, bezpiecznych programów testowanie, obsługa błędów i efektywna refaktoryzacja typy generyczne, inteligentne wskaźniki, wielowątkowość, obiekty cech oraz zaawansowane dopasowywanie wzorców użycie Cargo - wbudowanego w Rust menedżera pakietów, służącego do budowania, testowania i dokumentowania swojego kodu i zarządzania zależnościami używanie zaawansowanego
kompilatora Rusta wraz z technikami programowania opartymi na kompilatorze Książka zawiera dużo przykładów kodu, a także trzy rozdziały poświęcone budowaniu gotowych projektów przeznaczonych do sprawdzenia swojej wiedzy: gra w zgadywanie, implementacja narzędzia wiersza poleceń w języku Rust oraz wielowątkowy serwer.
- Kategorie:
- Język wydania: polski
- ISBN: 978-83-01-20639-0
- ISBN druku: 978-83-01-20541-6
- Liczba stron: 608
-
Sposób dostarczenia produktu elektronicznegoProdukty elektroniczne takie jak Ebooki czy Audiobooki są udostępniane online po opłaceniu zamówienia kartą lub przelewem na stronie Twoje konto > Biblioteka.Pliki można pobrać zazwyczaj w ciągu kilku-kilkunastu minut po uzyskaniu poprawnej autoryzacji płatności, choć w przypadku niektórych publikacji elektronicznych czas oczekiwania może być nieco dłuższy.Sprzedaż terytorialna towarów elektronicznych jest regulowana wyłącznie ograniczeniami terytorialnymi licencji konkretnych produktów.
-
Ważne informacje techniczneMinimalne wymagania sprzętowe:procesor: architektura x86 1GHz lub odpowiedniki w pozostałych architekturachPamięć operacyjna: 512MBMonitor i karta graficzna: zgodny ze standardem XGA, minimalna rozdzielczość 1024x768 16bitDysk twardy: dowolny obsługujący system operacyjny z minimalnie 100MB wolnego miejscaMysz lub inny manipulator + klawiaturaKarta sieciowa/modem: umożliwiająca dostęp do sieci Internet z prędkością 512kb/sMinimalne wymagania oprogramowania:System Operacyjny: System MS Windows 95 i wyżej, Linux z X.ORG, MacOS 9 lub wyżej, najnowsze systemy mobilne: Android, iPhone, SymbianOS, Windows MobilePrzeglądarka internetowa: Internet Explorer 7 lub wyżej, Opera 9 i wyżej, FireFox 2 i wyżej, Chrome 1.0 i wyżej, Safari 5Przeglądarka z obsługą ciasteczek i włączoną obsługą JavaScriptZalecany plugin Flash Player w wersji 10.0 lub wyżej.Informacja o formatach plików:
- PDF - format polecany do czytania na laptopach oraz komputerach stacjonarnych.
- EPUB - format pliku, który umożliwia czytanie książek elektronicznych na urządzeniach z mniejszymi ekranami (np. e-czytnik lub smartfon), dając możliwość dopasowania tekstu do wielkości urządzenia i preferencji użytkownika.
- MOBI - format zapisu firmy Mobipocket, który można pobrać na dowolne urządzenie elektroniczne (np.e-czytnik Kindle) z zainstalowanym programem (np. MobiPocket Reader) pozwalającym czytać pliki MOBI.
- Audiobooki w formacie MP3 - format pliku, przeznaczony do odsłuchu nagrań audio.
Rodzaje zabezpieczeń plików:- Watermark - (znak wodny) to zaszyfrowana informacja o użytkowniku, który zakupił produkt. Dzięki temu łatwo jest zidentyfikować użytkownika, który rozpowszechnił produkt w sposób niezgodny z prawem. Ten rodzaj zabezpieczenia jest zdecydowanie bardziej przyjazny dla użytkownika, ponieważ aby otworzyć książkę zabezpieczoną Watermarkiem nie jest potrzebne konto Adobe ID oraz autoryzacja urządzenia.
- Brak zabezpieczenia - część oferowanych w naszym sklepie plików nie posiada zabezpieczeń. Zazwyczaj tego typu pliki można pobierać ograniczoną ilość razy, określaną przez dostawcę publikacji elektronicznych. W przypadku zbyt dużej ilości pobrań plików na stronie WWW pojawia się stosowny komunikat.
WSTĘP xix PODZIĘKOWANIA xxi WPROWADZENIE xxiii Dla kogo jest Rust xxiv Zespoły deweloperskie xxiv Studenci xxiv Firmy xxiv Deweloperzy open source xxv Ludzie ceniący szybkość i stabilność xxv Dla kogo jest ta książka xxv Jak korzystać z tej książki xxv Źródła i jak uczestniczyć w tworzeniu tej książki xxvii 1. ROZPOCZYNAMY 1 Instalacja 1 Instalacja rustup w systemach Linux i macOS 2 Instalacja rustup w systemie Windows 3 Aktualizacja i odinstalowywanie 3 Usuwanie błędów 4 Lokalna dokumentacja 4 Hello, world! 4 Tworzenie katalogu projektu 5 Pisanie i uruchamianie programu w języku Rust 5 Anatomia programu w języku Rust 6 Kompilacja i uruchomienie to oddzielne kroki 7 Witaj Cargo! 8 Tworzenie projektu za pomocą Cargo 9 Tworzenie i uruchamianie projektu w Cargo 10 Tworzenie gotowej wersji 12 Cargo jako konwencja 12 Podsumowanie 13 2. PROGRAMOWANIE ZGADYWANKI 15 Tworzenie nowego projektu 16 Przetwarzanie odpowiedzi 17 Zapisywanie wartości w zmiennych 18 Obsługa potencjalnych błędów za pomocą typu Result 19 Wyświetlanie wartości za pomocą symboli zastępczych w println! 21 Testowanie pierwszej części 21 Generowanie tajnej liczby 22 Korzystanie ze skrzynki, aby rozszerzyć funkcjonalność 22 Generowanie liczby losowej 24 Porównanie liczby odgadniętej z tajną 26 Dopuszczenie wielu prób za pomocą pętli 30 Kończenie programu po poprawnej odpowiedzi 31 Obsługa niepoprawnych danych na wejściu 31 Podsumowanie 34 3. TYPOWE POJĘCIA Z ZAKRESU PROGRAMOWANIA 35 Zmienne i mutowalność 36 Różnice między zmiennymi a stałymi 38 Zasłanianie 39 Typy danych 40 Typy skalarne 41 Typy złożone 44 Funkcje 47 Parametry funkcji 48 Instrukcje i wyrażenia w treści funkcji 50 Funkcje z wartościami zwrotnymi 51 Komentarze 53 Sterowanie przepływem 54 Wyrażenie if 54 Powtarzanie w pętlach 59 Podsumowanie 62 4. POJĘCIE POSIADANIA 63 Czym jest posiadanie? 63 Reguły posiadania 65 Zakres zmiennej 65 Typ String 66 Pamięć i jej przydział 67 Posiadanie i funkcje 73 Zwracane wartości i zakres 73 Odwołania i pożyczki 75 Odwołania mutowalne 77 Wiszące odwołania 79 Reguły odwołań 81 Typ wycinek 81 Wycinki łańcucha 83 Inne wycinki 87 Podsumowanie 87 5. UŻYWANIE STRUKTUR DO KONSTRUOWANIA POWIĄZANYCH DANYCH 89 Definiowanie struktur i tworzenie ich instancji 89 Używanie skrótu do inicjacji pola, gdy zmienne i pola mają takie same nazwy 91 Tworzenie instancji z innych instancji za pomocą składni aktualizacji struktury 92 Użycie struktur krotki bez nazywanych pól do tworzenia różnych typów 93 Struktury jako jednostki bez żadnych pól 93 Przykład programu z użyciem struktury 95 Refaktoryzacja za pomocą krotek 96 Refaktoryzacja za pomocą struktur 96 Dodawanie użytecznej funkcjonalności za pomocą wyprowadzonych cech 97 Składnia metody 99 Definiowanie metod 100 Metody z większą liczbą parametrów 102 Funkcje powiązane 103 Wiele bloków impl 103 Podsumowanie 104 6. TYP WYLICZENIOWY I DOPASOWANIE WZORCA 105 Definiowanie wyliczenia 106 Wartości wyliczeń 106 Wyliczenie Option i jego zalety w porównaniu z wartościami null 110 Operator sterowania przepływem match 113 Wzorce, które są związane z wartościami 114 Dopasowywanie za pomocą Option115 Dopasowania wyczerpują wszystkie przypadki 116 Symbol zastępczy _ 117 Sterowanie przepływem za pomocą if let 118 Podsumowanie 119 7. WYKORZYSTANIE MODUŁÓW DO PORZĄDKOWANIA KODU I JEGO PONOWNEGO WYKORZYSTYWANIA 121 mod i Filesystem 122 Definicje modułów 123 Przenoszenie modułów do innych plików 125 Reguły systemów plików modułów 130 Sterowanie widocznością za pomocą pub 131 Ustawienie funkcji jako publicznej 132 Reguły prywatności 135 Przykłady prywatności 135 Odwoływanie się do nazw w różnych modułach 136 Wprowadzanie nazw do zakresu za pomocą słowa kluczowego use 137 Wprowadzanie wszystkich nazw do zakresu za pomocą glob 138 Użycie super do uzyskiwania dostępu do modułu nadrzędnego 139 Podsumowanie 141 8. TYPOWE KOLEKCJE 143 Przechowywanie list wartości za pomocą wektorów 144 Tworzenie nowego wektora 144 Uaktualnianie wektora 145 Usunięcie wektora usuwa jego elementy 145 Czytanie elementów wektora 146 Iterowanie po wartościach w wektorze 148 Użycie wyliczania do przechowywania wielu typów 148 Przechowywanie w łańcuchach tekstu zakodowanego za pomocą UTF-8 149 Czym jest łańcuch? 150 Tworzenie nowego łańcucha 150 Aktualizacja łańcucha 152 Indeksowanie łańcuchów 154 Dzielenie łańcuchów na wycinki 156 Metody iterowania po łańcuchach 157 Łańcuchy nie są takie proste 158 Przechowywanie kluczy z powiązanymi wartościami w mapach skrótów 158 Tworzenie nowej mapy skrótów 158 Mapy skrótów a posiadanie 160 Dostęp do wartości w mapie skrótów 160 Aktualizacja mapy skrótów 161 Funkcje skrótu 163 Podsumowanie 163 9. OBSŁUGA BŁĘDÓW 165 Błędy nienaprawialne z makrem panic! 166 Użycie śladu panic! 167 Błędy do naprawienia za pomocą Result 170 Dopasowywanie przy różnych błędach 172 Skróty do paniki przy błędzie: unwrap i expect 173 Propagowanie błędów 175 Panikować czy nie panikować 178 Przykłady, prototypowy kod i testy 179 Przypadki, w których mamy więcej informacji niż kompilator 179 Wskazówki dotyczące obsługi błędów 180 Tworzenie niestandardowych typów do celów sprawdzania 181 Podsumowanie 183 10. TYPY GENERYCZNE, CECHY I CZASY ŻYCIA 185 Usuwanie duplikacji przez wyodrębnienie funkcji 186 Generyczne typy danych 189 W definicjach funkcji 189 Definicje w strukturze 191 W definicjach wyliczeń 193 W definicjach metod 194 Wydajność kodu z użyciem typów generycznych 196 Cechy – definiowanie wspólnego zachowania 197 Definiowanie cechy 197 Implementowanie cechy na typie 198 Implementacje domyślne 200 Granice cech 202 Naprawa funkcji largest za pomocą granic cech 203 Używanie granic cech do metod implementowanych warunkowo 205 Sprawdzanie odwołań za pomocą czasów życia 207 Zapobieganie „wiszącym” odwołaniom za pomocą czasów życia 207 Kontroler pożyczek 208 Generyczne czasy życia w funkcjach 209 Składnia adnotacji dla czasu życia 211 Adnotacje o czasie życia w sygnaturach funkcji 212 Myślenie w kategoriach czasów życia 214 Adnotacje o czasie życia w definicjach struktur 216 Pominięcie czasu życia 216 Adnotacje o czasie życia w definicjach metod 219 Statyczny czas życia 220 Parametry generycznego typu, granice cech i czas życia w połączeniu 220 Podsumowanie 221 11. PISANIE AUTOMATYCZNYCH TESTÓW 223 Jak pisać testy 224 Anatomia funkcji testowania 224 Sprawdzanie wyników za pomocą makra assert! 228 Testowanie równości za pomocą makr assert_eq! i assert_ne! 231 Dodawanie niestandardowych komunikatów 233 Testowanie kodu pod kątem paniki za pomocą should_panic 235 Sterowanie sposobem uruchamiania testów 238 Uruchamianie testów równolegle lub po kolei 239 Pokazywanie wyników funkcji 239 Uruchomienie podzbioru testów według nazwy 241 Pomijanie niektórych testów, jeśli nie zostaną konkretnie wymienione 243 Organizacja testów 244 Testy jednostkowe 245 Testy integracyjne 246 Podsumowanie 250 12. PROJEKT WE/WY – BUDOWA PROGRAMU WIERSZA POLECEŃ 253 Akceptowanie argumentów wiersza poleceń 254 Czytanie wartości argumentów 255 Zapisywanie wartości argumentów w zmiennych 256 Czytanie pliku 257 Refaktoryzacja w celu poprawienia modułowości i obsługi błędów 259 Oddzielanie problemów w projektach binarnych 260 Naprawa obsługi błędów 264 Wyodrębnianie kodu z main 268 Podział kodu do skrzynki bibliotecznej 271 Tworzenie funkcjonalności biblioteki przy użyciu TDD 272 Pisanie testu zakończonego niepowodzeniem 273 Pisanie testu, który przejdzie 275 Praca ze zmiennymi środowiskowymi 278 Pisanie testu zakończonego niepowodzeniem dla funkcji nierozróżniających wielkości liter 279 Implementacja funkcji search_case_insensitive 280 Pisanie komunikatów o błędach do standardowego błędu zamiast standardowego wyjścia 284 Sprawdzanie, gdzie są zapisywane błędy 284 Zapisywanie błędów do standardowego błędu 285 Podsumowanie 286 13. FUNKCJE JĘZYKA FUNKCYJNEGO: ITERATORY I ZAMKNIĘCIA 287 Zamknięcia – anonimowe funkcje, które mogą przechwycić swoje środowisko 288 Tworzenie abstrakcji zachowania za pomocą zamknięć 288 Wnioskowanie o typie zamknięcia i adnotacje 293 Zapisywanie zamknięć z użyciem parametrów generycznych i cech Fn 295 Ograniczenia implementacji Cacher 298 Przechwytywanie środowiska za pomocą zamknięć 299 Przetwarzanie ciągów elementów za pomocą iteratorów 302 Cecha Iterator i metoda next 303 Metody, które zużywają iterator 304 Metody tworzące inne iteratory 305 Wykorzystanie zamknięć, które przechwytują swoje środowisko 306 Tworzenie własnych iteratorów za pomocą cechy Iterator 307 Ulepszanie naszego projektu we/wy 310 Usuwanie klonu za pomocą iteratora 310 Bardziej przejrzysty kod dzięki adapterom iteratora 313 Porównywanie wydajności – pętle a iteratory 314 Podsumowanie 316 14. WIĘCEJ INFORMACJI O CARGO I CRATES.IO 317 Wersje niestandardowe z profi lami wydania 318 Publikacja skrzynki w Crates.io 319 Dokonywanie użytecznych komentarzy dokumentujących 319 Eksport wygodnego publicznego API za pomocą pub use 323 Tworzenie konta Crates.io 327 Dodawanie metadanych do nowej skrzynki 327 Publikowanie w Crates.io 329 Publikowanie nowej wersji istniejącej skrzynki 329 Usuwanie wersji z Crates.io za pomocą cargo yank 329 Przestrzenie robocze Cargo 330 Tworzenie przestrzeni roboczej 330 Tworzenie drugiej skrzynki w przestrzeni roboczej 331 Instalowanie wersji binarnych z Crates.io za pomocą cargo install 336 Rozszerzanie Cargo za pomocą niestandardowych poleceń 337 Podsumowanie 337 15. INTELIGENTNE WSKAŹNIKI 339 Używanie Box do wskazywania danych na kopcu 341 Używanie Box do zapisu danych na kopcu 341 Włączenie typów rekurencyjnych z pudełkami 342 Traktowanie inteligentnych wskaźników jak zwykłych odwołań z cechą Deref 346 Podążanie za wskaźnikiem do wartości z użyciem operatora wyłuskiwania 346 Używanie Box jak odwołania 347 Definiowanie własnego inteligentnego wskaźnika 348 Traktowanie typu jak odwołania dzięki implementacji cechy Deref 349 Niejawne wymuszanie Deref z funkcjami i metodami 350 Jak wymuszanie Deref współdziała z mutowalnością 351 Uruchamianie kodu czyszczącego z cechą Drop 352 Wczesne odrzucanie wartości z zastosowaniem std::mem::drop 354 Rc – inteligentny wskaźnik ze zliczaniem odwołań 355 Używanie Rc do współdzielenia danych 356 Klonowanie Rc zwiększa licznik odwołań 358 RefCell oraz wzorzec wewnętrznej mutowalności 360 Wymuszanie reguł pożyczania podczas wykonania za pomocą RefCell 360 Mutowalność wewnętrzna – mutowalne pożyczanie niemutowalnej wartości 361 Wielu posiadaczy zmiennych danych dzięki połączeniu Rc i RefCell 367 Odwołania cykliczne mogą prowadzić do wycieku pamięci 369 Tworzenie odwołań cyklicznych 369 Zapobieganie odwołaniom cyklicznym – zmiana Rc na Weak 372 Podsumowanie 377 16. WSPÓŁBIEŻNOŚĆ BEZ OBAW 379 Użycie wątków do równoległego uruchamiania kodu 380 Tworzenie nowego wątku za pomocą spawn 382 Oczekiwanie, aż wszystkie wątki się zakończą, z użyciem JoinHandle 383 Korzystanie z zamknięcia move z wątkami 385 Używanie przekazywania komunikatów do transferu danych między wątkami 388 Kanały i przeniesienie własności 391 Wysyłanie wielu wartości i oczekujący nadajnik 392 Tworzenie wielu producentów przez klonowanie nadajnika 393 Współbieżność ze współdzieleniem zasobów 395 Wykorzystanie muteksów w celu zezwolenia na dostęp do danych z jednego wątku naraz 395 Podobieństwa między RefCell /Rc a Mutex /Arc 402 Elastyczna współbieżność z cechami Sync i Send 403 Pozwolenie na przenoszenie posiadania między wątkami za pomocą Send 403 Pozwolenie na dostęp z wielu wątków za pomocą Sync 404 Ręczne implementowanie Send i Sync nie jest bezpieczne 404 Podsumowanie 404 17. WŁASNOŚCI PROGRAMOWANIA OBIEKTOWEGO W JĘZYKU RUST 407 Charakterystyka języków obiektowych 408 Obiekty zawierają dane i działanie 408 Enkapsulacja, która ukrywa szczegóły implementacji 408 Dziedziczenie jako system typów i jako współdzielenie kodu 410 Wykorzystywanie obiektów cech, które dopuszczają wartości różnych typów 411 Definiowanie cechy dla jednolitego zachowania 412 Implementowanie cechy 414 Obiekty cech wykonują dynamiczne wysyłki 417 Bezpieczeństwo obiektowe jest wymagane dla obiektów cech 418 Implementowanie wzorca projektu obiektowego 419 Definiowanie postu i tworzenie nowej instancji w stanie Draft 421 Przechowywanie tekstu treści postu 422 Gwarantowanie, że treść projektu postu jest pusta 422 Żądanie oceny postu zmienia jego stan 423 Dodawanie metody approve, która zmienia zachowanie treści 424 Kompromisy wzorca stanu 427 Podsumowanie 432 18. WZORCE I DOPASOWYWANIE 433 Wszystkie miejsca, w których można korzystać ze wzorców 434 Gałęzie match 434 Wyrażenia warunkowe if let 435 Warunkowe pętle while let 436 Pętle for 436 Instrukcja let 437 Parametry funkcji 438 Podważalność – czy dopasowanie do wzorca może się nie udać 439 Składnia wzorca 441 Dopasowywanie literałów 441 Dopasowywanie nazwanych zmiennych 442 Wiele wzorców 443 Dopasowywanie zakresów wartości za pomocą składni. 443 Destrukturyzacja w celu rozdzielenia wartości 444 Pomijanie wartości we wzorcu 448 Tworzenie odwołań we wzorcach za pomocą ref i ref mut 453 Dodatkowe instrukcje warunkowe ze strażnikami dopasowania 455 Wiązania @ 457 Podsumowanie 458 19. FUNKCJE ZAAWANSOWANE 459 Niebezpieczny Rust 460 Niebezpieczne super możliwości 460 Wyłuskiwanie pierwotnego wskaźnika 461 Wywoływanie niebezpiecznej funkcji lub metody 463 Uzyskiwanie dostępu do modyfi kowalnej zmiennej statycznej lub jej modyfi kowanie 468 Implementacja bezpiecznej cechy 470 Kiedy korzystać z kodu, który nie jest bezpieczny 470 Zaawansowane czasy życia 471 Podtypy czasów życia jako gwarancja, że jeden czas życia jest dłuższy od innego 471 Granice czasu życia w odwołaniach do typów generycznych 476 Wnioskowanie o czasach życia obiektów cech 478 Zaawansowane cechy 479 Określanie typów symboli zastępczych w defi nicjach cech z powiązanymi typami 479 Domyślne parametry typów generycznych i przeciążenie operatora 481 Składnia w pełni kwalifi kowana dla jednoznaczności – wywoływanie metod z taką samą nazwą 483 Użycie super cech, aby wymagać funkcjonalności jednej cechy wewnątrz innej cechy 487 Użycie wzorca newtype do implementacji zewnętrznych cech na zewnętrznych typach 489 Typy zaawansowane 490 Użycie wzorca newtype dla bezpieczeństwa typów i abstrakcji 490 Tworzenie synonimów typu z aliasami typów 491 Typ „nigdy”, który nigdy niczego nie zwraca 493 Typy o dynamicznie określanych rozmiarach i cecha Sized 495 Zaawansowane funkcje i zamknięcia 497 Wskaźniki funkcji 497 Zwracanie zamknięć 498 Podsumowanie 499 20. OSTATNI PROJEKT – BUDOWANIE WIELOWĄTKOWEGO SERWERA WWW 501 Budowanie jednowątkowego serwera WWW 502 Nasłuchiwanie połączeń TCP 502 Czytanie żądania 505 Bliższe spojrzenie na żądanie HTTP 507 Pisanie odpowiedzi 507 Zwracanie rzeczywistego HTML 508 Sprawdzanie poprawności żądania i selektywne odpowiadanie 510 Nieco refaktoryzacji 512 Zamiana serwera jednowątkowego na wielowątkowy 513 Symulowanie powolnego żądania w bieżącej implementacji serwera 513 Poprawienie przepustowości za pomocą puli wątków 514 Płynne zakończenie i czyszczenie 534 Implementacja cechy Drop na ThreadPool 534 Sygnalizowanie wątkom, aby przestały nasłuchiwać zadań 537 Podsumowanie 541 A SŁOWA KLUCZOWE 543 Słowa kluczowe obecnie stosowane 543 Słowa kluczowe zarezerwowane do użycia w przyszłości 545 B OPERATORY I SYMBOLE 547 Operatory 547 Symbole inne niż operatory 549 C CECHY WYPROWADZONE 555 Debugowanie wyjścia dla programisty 556 PartialEq i Eq do porównań równościowych 556 PartialOrd i Ord do porównywania kolejności 557 Klonowanie i kopiowanie zduplikowanych wartości 557 Cecha Hash do odwzorowania wartości na wartość o ustalonym rozmiarze 558 Cecha Default dla wartości domyślnych 559 D. MAKRA 561 Różnica między makrami a funkcjami 562 Makra deklaratywne z macro_rules! do celów ogólnego metaprogramowania 563 Makra proceduralne do celów niestandardowych wyprowadzeń 565 Przyszłość makr 570 INDEKS 571