Jak rozmawiamy z maszyną: język maszynowy, kompilator, języki programowania
🎯 Po co Ci to?
Zdanie „programista pisze kod" słyszałeś tysiąc razy, ale co ono właściwie znaczy? Że programista dyktuje maszynie polecenia w języku, który maszyna rozumie. Ta jednostka pokazuje, że programowanie to komunikacja — dokładnie tego samego rodzaju co rozmowa z drugim człowiekiem, z tą różnicą, że rozmówca jest absolutnie dosłowny i nie domyśla się niczego. Zrozumiesz też, dlaczego dziś „programujemy" modele AI w języku naturalnym (prompty, Dział 18) i czym to się różni od pisania kodu.
✅ Czego się nauczysz
Po tej lekcji potrafisz:
- zdefiniować programowanie jako komunikację człowieka z komputerem;
- wyjaśnić, czym jest język maszynowy i dlaczego ludzie w nim nie piszą;
- wyjaśnić rolę kompilatora i interpretera;
- wskazać trzy warstwy każdego języka — znaki, gramatykę i znaczenie — i pokazać je na przykładzie języka programowania.
🔁 Przypomnij sobie
Z Jednostki 2.1: komputer jest uniwersalny, ale ceną uniwersalności jest konieczność powiedzenia mu, co ma robić. Teraz zajmiemy się właśnie tym „powiedzeniem".
📘 Wyjaśnienie
Komunikację człowieka z komputerem, której celem jest rozwiązanie jakiegoś problemu, nazwiemy programowaniem. Problemy stawiane przed komputerem mogą być proste, na przykład obliczenie wyniku mnożenia dwóch liczb, albo bardziej złożone, jak napisanie streszczenia kilkustronicowego artykułu.
Skoro programowanie to sposób komunikacji człowieka z komputerem, to osobę, która potrafi skutecznie taką komunikację prowadzić, nazwiemy programistą lub programistką. Co ciekawe, programistka komunikuje się z komputerem w podobny sposób, jak ludzie komunikują się między sobą — używa języka.
📐 DEFINICJA — programowanie: komunikacja człowieka z komputerem, której celem jest rozwiązanie określonego problemu.
Po ludzku: mówienie maszynie — w języku, który ona rozumie — co ma zrobić. Czym to NIE jest: programowanie nie polega na „tłumaczeniu maszynie, o co chodzi" w sensie przekazywania intencji. Maszyna nie odgaduje intencji; wykonuje dokładnie to, co napisano.
Trzy warstwy każdego języka
Poświęćmy chwilę samej komunikacji. Komunikujemy się, wymieniając komunikaty. Każdy taki komunikat składa się ze słów ułożonych w pewnym porządku, a porządek ten definiuje gramatyka języka, którym się posługujemy. Komunikat jako całość ma też swoją treść (czyli sens), którą nadawca chce przekazać odbiorcy.
Gdy komunikat jest niepoprawny gramatycznie, często nie możemy go zrozumieć. Tak samo jest, gdy komunikat — choć gramatycznie poprawny — zawiera wyrażenia, których znaczenia nie znamy. W obu przypadkach mówimy: „To jest bez sensu!".
Sprawne używanie języka w komunikacji — zarówno tej międzyludzkiej, jak i między człowiekiem a komputerem — wymaga więc trzech rzeczy naraz: znaków zrozumiałych dla odbiorcy, gramatyki, której się trzymamy, i sensownego doboru wyrażeń.
💭 Pomyśl: Powiedz koledze „podaj mi to coś ze stołu" — prawdopodobnie poda właściwą rzecz. Dlaczego identycznie nieprecyzyjne polecenie wydane komputerowi zawsze skończy się błędem?
Sprawdź odpowiedź
Bo człowiek uzupełnia braki komunikatu kontekstem i domysłem: widzi, na co patrzysz, wie, co robiłeś minutę temu, zna Twoje nawyki. Komputer nie ma dostępu do niczego poza tym, co napisano w kodzie. Każda niedopowiedziana rzecz musi być dopowiedziana wprost. To główne źródło trudności w programowaniu — nie skomplikowana matematyka, ale konieczność bycia całkowicie jednoznacznym.
Język maszynowy: to, co procesor naprawdę czyta
Procesor rozumie wyłącznie język maszynowy — ciągi liczb, w których jedna wartość oznacza operację („dodaj"), a pozostałe wskazują, gdzie leżą argumenty i gdzie odłożyć wynik. Prosta operacja „dodaj zawartość dwóch komórek pamięci i zapisz w trzeciej" to w języku maszynowym kilka liczb, a w zapisie dwójkowym — ciąg zer i jedynek.
Da się w tym pisać (pierwsi programiści nie mieli wyboru) i da się w tym zwariować. Dlatego bardzo szybko powstały języki wysokiego poziomu — Python, Java, C++ i setki innych — w których zamiast numerów operacji piszemy słowa zbliżone do angielskiego, a zamiast adresów pamięci używamy nazw.
📐 DEFINICJA — język programowania: język służący do komunikacji z komputerem, mający własny system znaków, gramatykę oraz reguły określające znaczenie wyrażeń (czyli jaki efekt osiągniesz, używając danego wyrażenia).
Po ludzku: zbiór słów i reguł ich składania, w którym da się zapisać polecenia dla maszyny tak, by człowiek też to jeszcze rozumiał. Czym to NIE jest: to nie „język, którym mówi komputer" — komputer mówi wyłącznie językiem maszynowym. Języki programowania są dla ludzi.
Tłumacz w środku: kompilator i interpreter
Skoro człowiek pisze w Pythonie, a procesor czyta liczby, ktoś musi tłumaczyć. Robią to dwa rodzaje narzędzi:
- kompilator — tłumaczy cały program na język maszynowy przed uruchomieniem, produkując plik wykonywalny (tak działa m.in. C++);
- interpreter — tłumaczy i wykonuje program na bieżąco, instrukcja po instrukcji (tak zwykle działa Python).
Różnica jest jak między przetłumaczeniem całej książki, a tłumaczeniem symultanicznym na żywo. Pierwsze jest szybsze w działaniu, drugie wygodniejsze w pracy — dlatego badacze uczenia maszynowego pokochali Python, w którym eksperyment można zmienić i uruchomić w kilka sekund (do konsekwencji tego wyboru wrócimy w Jednostce 13.4).
Pomysł, żeby tłumaczeniem zajmowała się maszyna, wcale nie był oczywisty. Gdy w 1952 roku amerykańska matematyczka i programistka Grace Hopper (późniejsza kontradmirał marynarki wojennej USA) uruchomiła system A-0 — pierwszy program zamieniający zapis symboliczny na kod maszynowy, uznawany za pierwszy kompilator — przez trzy lata nikt nie chciał go użyć. Jak sama wspominała, słyszała, że „komputery potrafią tylko liczyć". Bez tego uporu programowanie do dziś polegałoby na wpisywaniu numerów operacji.

Jeśli zostaniesz programistą lub programistką, komunikując się z komputerem będziesz wysyłać mu komunikaty instruujące go, jakie kroki kolejno powinien wykonać. To tak, jakbyś wydawał maszynie rozkazy: zrób to, a potem tamto, a następnie to.
Pamiętaj! Nie ma zasadniczej różnicy między uczeniem się języka obcego, takiego jak angielski czy włoski, a uczeniem się języka programowania Python czy Java. W obu przypadkach uczysz się znaków, gramatyki i znaczeń — a potem po prostu używasz.
⚠️ Uwaga, pułapka
Modele językowe, o których będzie druga połowa tej książki, przyjmują polecenia w polszczyźnie albo angielskim — i łatwo wyciągnąć wniosek, że „już nie trzeba znać języków programowania, bo teraz programuje się po polsku". To złudzenie z dwóch powodów. Po pierwsze, model nie wykonuje Twojego polecenia tak, jak procesor wykonuje instrukcję — on przewiduje, jaka odpowiedź jest prawdopodobna (Jednostka 15.1), więc ten sam prompt może dać różne wyniki. Po drugie, pod modelem wciąż stoi zwyczajny program w Pythonie i wciąż język maszynowy. Zmieniła się warstwa, z którą styka się użytkownik, a nie natura maszyny.
📐 Definicje tej lekcji
- Programowanie — komunikacja człowieka z komputerem służąca rozwiązaniu problemu.
- Programista/programistka — człowiek, który potrafi skutecznie prowadzić taką komunikację.
- Język maszynowy — zapis instrukcji w postaci liczb, jedyny język czytany bezpośrednio przez procesor.
- Język programowania — język dla ludzi (znaki + gramatyka + znaczenia), w którym zapisuje się polecenia dla maszyny.
- Kompilator — narzędzie tłumaczące cały program na język maszynowy przed uruchomieniem.
- Interpreter — narzędzie tłumaczące i wykonujące program na bieżąco.
📌 Najważniejsze w pigułce
- Programowanie to komunikacja, a nie magia — ma nadawcę, odbiorcę, język i sens komunikatu.
- Każdy język (naturalny i programowania) ma trzy warstwy: znaki, gramatykę, znaczenie.
- Procesor rozumie tylko język maszynowy; języki wysokiego poziomu istnieją dla ludzi.
- Między człowiekiem a procesorem stoi tłumacz: kompilator (całość z góry) albo interpreter (na bieżąco).
- Komputer nie domyśla się intencji — wszystko trzeba powiedzieć wprost.
🎒 Zadania
Zadanie 2.2.1. Wskaż w zdaniu „Wypisz wszystkie liczby od 1 do 10, ale pomiń parzyste" wszystkie miejsca, w których polecenie jest niejednoznaczne dla maszyny. Przepisz je tak, by nie zostawiało wątpliwości.
Pokaż rozwiązanie
Niejednoznaczności: czy „od 1 do 10" obejmuje 10? Czy wypisywać w kolejności rosnącej? Co znaczy „wypisz" — na ekranie, w jednej linii, oddzielone czym? Czy 1 jest parzysta (nie, ale maszyna musi mieć podaną regułę)?
Wersja jednoznaczna: „Dla każdej liczby całkowitej n od 1 do 10 włącznie, w kolejności rosnącej: jeżeli reszta z dzielenia n przez 2 jest różna od zera, wypisz n na ekranie w osobnej linii."
Zadanie 2.2.2. Wyjaśnij różnicę między kompilatorem a interpreterem i podaj po jednej sytuacji, w której każde z tych rozwiązań jest wygodniejsze.
Sprawdź odpowiedź
Kompilator tłumaczy cały program przed uruchomieniem — program działa potem szybko, bo tłumaczenie już się odbyło; wygodne przy oprogramowaniu, które ma działać wydajnie i długo (gra, system operacyjny). Interpreter tłumaczy na bieżąco — wolniej, ale można zmienić jedną linijkę i natychmiast sprawdzić efekt; wygodne w eksperymentach badawczych i analizie danych, gdzie kod zmienia się co chwilę.
Zadanie 2.2.3. Podaj trzy różnice między „programowaniem" maszyny promptem w języku naturalnym a napisaniem programu w Pythonie.
Pokaż rozwiązanie
- Determinizm: program w Pythonie wykonany dwa razy na tych samych danych da ten sam wynik; ten sam prompt może dać dwie różne odpowiedzi.
- Sposób realizacji: kod jest tłumaczony na instrukcje procesora i wykonywany; prompt jest wejściem do modelu, który przewiduje prawdopodobną odpowiedź.
- Kontrola nad krokami: w kodzie decydujesz o każdym kroku; w prompcie opisujesz cel i nie masz wglądu ani wpływu na to, co dzieje się po drodze.
🔍 Sprawdź, czy umiesz
- [ ] Zdefiniować programowanie jako komunikację i wskazać jej elementy.
- [ ] Wyjaśnić, czym jest język maszynowy i dlaczego ludzie w nim nie piszą.
- [ ] Opisać rolę kompilatora i interpretera oraz różnicę między nimi.
- [ ] Wymienić trzy warstwy języka i pokazać je na przykładzie.
- [ ] Wyjaśnić, dlaczego prompt to nie to samo co program.