diff --git a/pl-pl/lua-pl.html.markdown b/pl-pl/lua-pl.html.markdown new file mode 100644 index 00000000..a2966c6d --- /dev/null +++ b/pl-pl/lua-pl.html.markdown @@ -0,0 +1,427 @@ +--- +language: Lua +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] +translators: + - ["Aimless", "https://github.com/aimlesx"] +filename: learnlua-pl.lua +lang: pl-pl +--- + +```lua +-- Dwa myślniki rozpoczynają jednolinijkowy komentarz. + +--[[ + Dodanie dwóch znaków [ oraz ] tworzy + komentarz wieloliniowy. +--]] + +---------------------------------------------------- +-- 1. Zmienne i sterowanie przepływem. +---------------------------------------------------- + +liczba = 42 -- Liczby mogą być całkowite lub zmiennoprzecinkowe. + +s = 'walternate' -- Niezmienne ciągi znaków jak w Pythonie. +t = "podwójne cudzysłowy też są w porządku" +u = [[ Podwójne nawiasy + otwierają i zamykają + wieloliniowe ciągi znaków.]] +t = nil -- Usuwa zmienną t; Lua posiada garbage collector. + +-- Bloki są oznaczane słowami kluczowymi, takimi jak do/end: +while liczba < 50 do + liczba = liczba + 1 -- Brak operatorów ++ lub +=. +end + +-- Instrukcje warunkowe if: +if liczba > 40 then + print('powyżej 40') +elseif s ~= 'walternate' then -- ~= oznacza "nie równe". + -- Porównanie równości to == jak w Pythonie; działa dla stringów. + io.write('nie powyżej 40\n') -- Domyślnie wypisuje na stdout. +else + -- Zmienne są domyślnie globalne. + zmiennaGlobalna = 5 -- Popularny jest camel case. + + -- Tak deklaruje się zmienne lokalne: + local linia = io.read() -- Odczytuje kolejną linię wejścia standardowego. + + -- Łączenie ciągów znaków za pomocą operatora .. : + print('Nadchodzi zima, ' .. linia) +end + +-- Niezdefiniowane zmienne zwracają nil. +-- Nie jest to błędem: +foo = nieznanaZmienna -- Teraz foo = nil. + +wartoscLogiczna = false + +-- Tylko nil i false są fałszywe; 0 i '' są prawdziwe! +if not wartoscLogiczna then print('było fałszywe') end + +-- 'or' i 'and' podlegają ewaluacji short-circuit. +-- Działają podobnie do operatora a?b:c z C/js: +wynik = wartoscLogiczna and 'tak' or 'nie' --> 'nie' + +suma = 0 +for i = 1, 100 do -- Zakres obejmuje oba końce. + suma = suma + i +end + +-- Aby zliczać w dół użyj zakresu "100, 1, -1": +suma = 0 +for j = 100, 1, -1 do suma = suma + j end + +-- Ogólnie zakres to początek, koniec[, krok]. + +-- Inna konstrukcja pętli: +repeat + print('droga przyszłości') + liczba = liczba - 1 +until liczba == 0 + + +---------------------------------------------------- +-- 2. Funkcje. +---------------------------------------------------- + +function fib(n) + if n < 2 then return 1 end + return fib(n - 2) + fib(n - 1) +end + +-- Funkcje anonimowe i domknięcia (Closures w JS) są okej: +function sumator(x) + -- Zwracana funkcja jest tworzona, gdy sumator jest + -- wywoływany, i zapamiętuje wartość x: + return function (y) return x + y end +end +a1 = sumator(9) +a2 = sumator(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- Zwracanie, wywołania funkcji i przypisania działają +-- z listami o potencjalnie różnych długościach. +-- Zmienne które nie dostaną wartości dostają wartość nil; +-- nadmiarowe wartości są odrzucane. + +x, y, z = 1, 2, 3, 4 +-- Teraz x = 1, y = 2, z = 3, a 4 jest odrzucone. + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> wypisuje "zaphod nil nil" +-- Teraz x = 4, y = 8, wartości 15...42 są odrzucone. + +-- Funkcje są obiektami pierwszej klasy, mogą być lokalne/globalne. +-- Obie linie poniżej mają identyczny efekt: +function f(x) return x * x end +f = function (x) return x * x end + +-- Te również: +local function g(x) return math.sin(x) end +local g; g = function (x) return math.sin(x) end +-- deklaracja 'local g' sprawia, że odwołania do g są poprawne. + +-- Tak swoją drogą, to funkcje trygonometryczne działają w radianach. + +-- Wywołania z jednym parametrem stringowym nie wymagają nawiasów: +print 'cześć' -- Działa poprawnie. + + +---------------------------------------------------- +-- 3. Tabele. +---------------------------------------------------- + +-- Tabele = jedyna złożona struktura danych w Lua; +-- są to tablice asocjacyjne. +-- Podobne do tablic w PHP lub obiektów w JS, są to +-- słowniki (hashmap), które można używać także +-- jako listy. + +-- Używanie tabel jako słowników / map: + +-- Literały słowników domyślnie mają klucze typu string: +t = {klucz1 = 'wartość1', klucz2 = false} + +-- Klucze typu string mogą używać notacji kropkowej (jak w JS): +print(t.key1) -- Wypisuje 'wartość1'. +t.nowyKlucz = {} -- Dodaje nową parę klucz/wartość. +t.klucz2 = nil -- Usuwa klucz2 z tabeli. + +-- Notacja literału dla dowolnego klucza (nie będącego nil): +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- wypisuje "tau" + +-- Dopasowanie klucza działa według wartości dla liczb +-- i ciągów, ale według tożsamości dla tabel. +a = u['@!#'] -- Teraz a = 'qbert'. +b = u[{}] -- Można by oczekiwać 1729, ale wynik to nil: +-- b = nil, ponieważ wyszukiwanie nie powiodło się. +-- Dzieje się tak, ponieważ klucz, którego użyliśmy, nie jest +-- tym samym obiektem, który był użyty do przechowania +-- oryginalnej wartości. Dlatego ciągi i liczby są bardziej +-- przenośnymi kluczami. + +-- Funkcje z jednym parametrem będącym tabelą nie wymagają nawiasów: +function h(x) print(x.klucz1) end +h{klucz1 = 'Sonmi~451'} -- Wypisuje 'Sonmi~451'. + +for key, val in pairs(u) do -- Iteracja przez tabelę. + print(key, val) +end + +-- _G to specjalna tabela zawierająca wszystkie zmienne globalne. +print(_G['_G'] == _G) -- Wypisuje 'true'. + +-- Używanie tabel jako list / tablic: + +-- Literały list ustawiają domyślnie klucze jako liczby całkowite: +v = {'wartość1', 'wartość2', 1.21, 'gigawaty'} +for i = 1, #v do -- #v to rozmiar listy v. + print(v[i]) -- Indeksy zaczynają się od 1 !! SZALONE! +end +-- "Lista" nie jest prawdziwym typem. v to po prostu tabela +-- z kolejnymi kluczami liczbowymi, traktowana jako lista. + +---------------------------------------------------- +-- 3.1 Metatabele i metametody. +---------------------------------------------------- + +-- Tabela może mieć metatabelę, która nadaje tabeli +-- funkcjonalność podobną do przeciążania operatorów. +-- Później zobaczymy, jak metatabele wspierają zachowanie +-- przypominające prototypy z JS. + +f1 = {a = 1, b = 2} -- Reprezentuje ułamek a/b. +f2 = {a = 2, b = 3} + +-- To by się nie powiodło: +-- s = f1 + f2 + +metaulamek = {} +function metaulamek.__add(f1, f2) + sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metaulamek) +setmetatable(f2, metaulamek) + +s = f1 + f2 -- Wywołuje __add(f1, f2) na metatabeli f1 + +-- f1, f2 nie mają klucza dla swojej metatabeli, w przeciwieństwie +-- do prototypów w JS, więc trzeba ją uzyskać za pomocą +-- getmetatable(f1). Metatabela to normalna tabela +-- z kluczami, które Lua rozpoznaje, np. __add. + +-- Ale następna linia zawiedzie, ponieważ s nie ma metatabeli: +-- t = s + s +-- Wzorce przypominające klasy przedstawione poniżej +-- byłyby w stanie to naprawić. + +-- __index w metatabeli przeciąża odwołania przez kropkę: +domyslnieUlubione = {zwierze = 'gru', jedzenie = 'pączki'} +mojeUlubione = {jedzenie = 'pizza'} +setmetatable(mojeUlubione, {__index = domyslnieUlubione}) +zjedzonyPrzez = mojeUlubione.zwierze -- działa! dzięki metatabelo + +-- Bezpośrednie wyszukiwania w tabeli, które zawiodą, zostaną +-- powtórzone przy użyciu wartości __index w metatabeli, co +-- może się rekurencyjnie powtarzać. + +-- Wartość __index może być także funkcją function(tabela, klucz) +-- dla bardziej zaawansowanych wyszukiwań. + +-- Wartości __index, __add, itd. nazywane są metametodami. +-- Pełna lista. Tutaj a to tabela z metametodą. + +-- __add(a, b) dla a + b +-- __sub(a, b) dla a - b +-- __mul(a, b) dla a * b +-- __div(a, b) dla a / b +-- __mod(a, b) dla a % b +-- __pow(a, b) dla a ^ b +-- __unm(a) dla -a +-- __concat(a, b) dla a .. b +-- __len(a) dla #a +-- __eq(a, b) dla a == b +-- __lt(a, b) dla a < b +-- __le(a, b) dla a <= b +-- __index(a, b) dla a.b +-- __newindex(a, b, c) dla a.b = c +-- __call(a, ...) dla a(...) + +---------------------------------------------------- +-- 3.2 Tabele przypominające klasy i dziedziczenie. +---------------------------------------------------- + +-- Klasy nie są wbudowane; istnieją różne sposoby +-- na ich tworzenie przy użyciu tabel i metatabel. + +-- Wyjaśnienie dla tego przykładu znajduje się poniżej. + +Pies = {} -- 1. + +function Pies:new() -- 2. + nowyObiekt = {odglos = 'hau'} -- 3. + self.__index = self -- 4. + return setmetatable(nowyObiekt, self) -- 5. +end + +function Pies:wydajOdglos() -- 6. + print('Ja mówię ' .. self.odglos) +end + +panPies = Pies:new() -- 7. +panPies:wydajOdglos() -- 'Ja mówię hau' -- 8. + +-- 1. Pies działa jak klasa; w rzeczywistości to tabela. +-- 2. function tablename:fn(...) to to samo, co +-- function tablename.fn(self, ...) +-- Dwukropek dodaje pierwszy argument o nazwie self. +-- Przeczytaj 7 i 8 poniżej, aby zrozumieć, jak self +-- dostaje swoją wartość. +-- 3. nowyObiekt będzie instancją klasy Pies. +-- 4. self = klasa, która jest instancjonowana. Często +-- self = Pies, ale dziedziczenie może to zmienić. +-- nowyObiekt dostaje funkcje self, kiedy ustawiamy +-- metatabelę nowyObiekt i __index self na self. +-- 5. Przypomnienie: setmetatable zwraca swój pierwszy argument. +-- 6. Dwukropek działa jak w punkcie 2, ale tym razem +-- oczekujemy, że self będzie instancją a nie klasą. +-- 7. To samo, co Pies.new(Pies), więc self = Pies w new(). +-- 8. To samo, co panPies.wydajOdglos(panPies); self = panPies. + +---------------------------------------------------- + +-- Przykład dziedziczenia: + +GlosnyPies = Dog:new() -- 1. + +function GlosnyPies:wydajOdglos() + s = self.odglos .. ' ' -- 2. + print(s .. s .. s) +end + +seymour = GlosnyPies:new() -- 3. +seymour:wydajOdglos() -- 'hau hau hau' -- 4. + +-- 1. GlosnyPies dziedziczy metody i zmienne od Pies. +-- 2. self ma klucz 'odglos' z new(), zobacz punkt 3. +-- 3. To samo, co GlosnyPies.new(GlosnyPies), przekształcone w +-- Pies.new(GlosnyPies), ponieważ GlosnyPies nie ma klucza 'new', +-- ale ma __index = Pies w swojej metatabeli. +-- Wynik: metatabela seymoura to GlosnyPies, a +-- GlosnyPies.__index = GlosnyPies. Więc seymour.klucz1 będzie +-- = seymour.klucz1, GlosnyPies.klucz1, Pies.klucz1, w zależności od tego, +-- która tabela pierwsza ma dany klucz. +-- 4. Klucz 'wydajOdglos' jest znaleziony w GlosnyPies; to to samo, +-- co GlosnyPies.wydajOdglos(seymour). + +-- Jeśli potrzeba, new() w podklasie wygląda jak w bazowej: +function GlosnyPies:new() + nowyObiekt = {} + -- konfiguracja nowyObiekt + self.__index = self + return setmetatable(nowyObiekt, self) +end + +---------------------------------------------------- +-- 4. Moduły. +---------------------------------------------------- + + +--[[ Komentuję tę sekcję, aby reszta +-- tego skryptu pozostała możliwa do uruchomienia. +``` + +```lua +-- Załóżmy, że plik mod.lua wygląda tak: +local M = {} + +local function przedstawSie() + print('Hrunkner') +end + +function M.przywitajSie() + print('Cześć ') + przedstawSie() +end + +return M + +-- Inny plik może użyć funkcjonalności z mod.lua: +local mod = require('mod') -- Uruchamia plik mod.lua. + +-- require to standardowy sposób na importowanie modułów. +-- require działa jak: (jeśli nie jest w pamięci podręcznej; zob. poniżej) +local mod = (function () + +end)() +-- To tak, jakby mod.lua był ciałem funkcji, więc +-- lokalne zmienne w mod.lua są niewidoczne na zewnątrz. + +-- To działa, ponieważ mod tutaj = M w mod.lua: +mod.przywitajSie() -- Wypisuje: Cześć Hrunkner + +-- To jest błędne; sayMyName istnieje tylko w mod.lua: +mod.przedstawSie() -- błąd + +-- Zwracane wartości z require są pamiętane, więc plik +-- jest uruchamiany maksymalnie raz, nawet jeśli jest +-- wielokrotnie wywoływany przez require. + +-- Załóżmy, że mod2.lua zawiera "print('Witam!')". +local a = require('mod2') -- Wypisuje Witam! +local b = require('mod2') -- Nie wypisuje nic; a=b. + +-- dofile działa jak require, ale bez pamiętania wartości zwracanej: +dofile('mod2.lua') --> Witam! +dofile('mod2.lua') --> Witam! (uruchamia ponownie) + +-- loadfile ładuje plik Lua, ale jeszcze go nie uruchamia. +f = loadfile('mod2.lua') -- Wywołaj f(), aby go uruchomić. + +-- load to odpowiednik loadfile dla stringów. +-- (loadstring jest przestarzałe, używaj load) +g = load('print(343)') -- Zwraca funkcję. +g() -- Wypisuje 343; nic nie zostało wypisane wcześniej. +--]] +``` + +## Społeczność + +Jeśli potrzebujesz wsparcia, dołącz do oficjalnej [listy mailingowej Lua](https://www.lua.org/lua-l.html), [kanału IRC](http://lua-users.org/wiki/IrcChannel) lub [forum](https://luaforum.com). + +## Źródła + +Chciałem nauczyć się Lua, aby tworzyć gry +przy użyciu [silnika gier LÖVE](http://love2d.org/). To był mój cel. + +Zacząłem od [„Lua for programmers” autorstwa BlackBulletIV](https://ebens.me/posts/lua-for-programmers-part-1/). +Następnie przeczytałem oficjalną książkę [„Programming in Lua”](http://www.lua.org/pil/contents.html). +Tak wyglądała moja droga. + +Może być pomocne zapoznanie się z [krótką dokumentacją Lua](http://lua-users.org/wiki/LuaShortReference) na lua-users.org. + +Główne tematy, które nie zostały omówione, to standardowe biblioteki: + +* [`string` (łańcuchy znaków)](http://lua-users.org/wiki/StringLibraryTutorial) +* [`table` (tabele)](http://lua-users.org/wiki/TableLibraryTutorial) +* [`math` (funkcje matematyczne)](http://lua-users.org/wiki/MathLibraryTutorial) +* [`io` (wejście/wyjście)](http://lua-users.org/wiki/IoLibraryTutorial) +* [`os` (funkcje systemowe)](http://lua-users.org/wiki/OsLibraryTutorial) + +Przy okazji, cały plik jest poprawnym skryptem Lua; zapisz go +jako `learn.lua` i uruchom poleceniem "`lua learn.lua`"! + +Ten tekst został pierwotnie napisany dla strony tylerneylon.com, a także +jest dostępny jako [GitHub gist](https://gist.github.com/tylerneylon/5853042). Baw się dobrze z Lua!