kod • słowa • emocje

blog Daniela Janusa

O książkach technologicznych i ich tłumaczeniach

1 lutego 2013

Trudna rzecz jest jeden język drugim językiem dostatecznie wyrznąć.

-- Jan Leopolita (1523--1572)

Rodzaje książek informatycznych

Mam zasadę dotyczącą książek informatycznych: nie kupuję niczego, co ma w tytule nazwę konkretnej technologii. (Purystów z góry przepraszam za użycie tego słowa, mając świadomość jego pretensjonalności; ale nie znam innego polskiego określenia, które by zbiorczo obejmowało konkretne języki programowania, systemy operacyjne, platformy wykonawcze, serwery aplikacji, architektury itd.) Po pierwsze, technologie pojawiają się i znikają, wciąż ukazują się ich nowe wersje, i w efekcie czas życia książki opisującej, dajmy na to, konkretną implementację jakiegoś języka programowania na ogół bywa nie dłuższy niż kilka lat. Można wręcz mówić o „okresie półtrwania”, po którym połowa informacji zawartej w książce jest już nieaktualna. Po drugie, i może ważniejsze, tego typu publikacje często wnoszą niewielką wartość dodaną w porównaniu do dokumentacji: od książki oczekuję, że nie tylko przekaże mi suche instrukcje, ale także idee, które w jakiś sposób wzbogacą mój warsztat i zostaną ze mną na dłużej. Dlatego do poduszki wolę poczytać o uczeniu maszynowym za pomocą metod jądrowych niż o bebechach serwera aplikacyjnego.

Rzecz jasna, jak od każdej zasady, tak i od tej istnieją wyjątki. Bywa, że technologia na tyle wryła się w informatyczny krajobraz, że nie grozi jej szybkie przeterminowanie, a dana książka uznawana jest za kanoniczny opis technologii, nie zaś tylko dodatek post hoc (jak K&R do C czy Księga Wielbłądzia do Perla). Zdarza się też i tak, że książka opisuje język czy środowisko, którego akurat intensywnie używam lub przymierzam się do intensywnego używania, i wtedy mam szansę odnieść z niej dużą korzyść. Tak było z Programming Clojure Stuarta Hallowaya, której pierwsze wydanie kupiłem niedługo po jego ukazaniu się z górą trzy lata temu, a drugie, zmienione i uaktualnione (a jakże!) wkrótce ukaże się po polsku nakładem Helionu.

Po przeczytaniu darmowej próbki nasunęły mi się wątpliwości odnośnie samego tłumaczenia, a w ślad za nimi myśli dotyczące polskich tłumaczeń literatury informatycznej w ogóle. Spróbuję je poniżej zebrać.

O Clojure po polsku

Od razu powiem, że ogólny poziom przekładu Tomasza Walczaka uważam za wysoki: tekst jest spójny, nośny i pozbawiony błędów merytorycznych. Czepianie się szczegółów, które za chwilę nastąpi, ma być nie tyle krytyką, co raczej próbą uświadomienia sobie, dlaczego mimo wszystko „Programowanie w języku Clojure” czyta mi się mniej płynnie niż oryginał angielski; a także zwrócenia uwagi na problemy, z jakimi musi się zmierzyć tłumacz. Zasygnalizuję więc pewne zagadnienia, ale wcale nie mam pewności, czy potrafiłbym rozwiązać je lepiej, albo nawet – czy w ogóle się da.

Bo wydawałoby się, że tłumaczenie tekstu informatycznego jest czynnością bez porównania prostszą niż na przykład poezji, gdzie trzeba ważyć każde słowo, prawda? Tymczasem rodzi ono zupełnie nowe problemy. Tłumacz zmuszony jest często wymyślić od nowa terminologię z zakresu wąskiej dziedziny, o której po polsku się nie pisze lub pisze się rzadko lub nieformalnie; podjąć pewne nierzadko arbitralne decyzje i konsekwentnie się ich trzymać; albo – jak zobaczymy – zadecydować, co zrobić z subtelnymi różnicami odcieni znaczeniowych pewnych pojęć.

Lispa czy Lispu?

Tłumacz często używa formy Lispa jako dopełniacza od rzeczownika Lisp. A jak naprawdę powinna brzmieć ta forma? Zdania na ten temat są podzielone. Wydaje się, że tradycyjnie w środowisku utrwalona była postać Lispu (zapewne nawiązująca do odmiany nazw innych wczesnych języków programowania: Fortranu i COBOL-u), co potwierdza zarówno poradnia językowa PWN, jak i słowniki: Słownik gramatyczny języka polskiego i słownik sjp.pl. Forma Lispa (być może urobiona przez analogię do odmiany nazw nowych języków: Perla, Pythona) też jest żywa w uzusie, choć, jak się zdaje, nieznacznie ustępuje odmianie Lispu (w Narodowym Korpusie Języka Polskiego znajdujemy jej 19 wystąpień wobec 33 wystąpień Lispu).

Dla kontrastu, słowo Clojure, którego paradygmat odmiany (nieodmienne) nie budzi wątpliwości, pojawia się na ogół jako część sformułowania język Clojure. Można by analogiczny zabieg przeprowadzić z językiem Lisp. Albo pozostać przy formie Lispu, która, choć zrazu brzmiała mi dziwnie, teraz wydaje się znacznie naturalniejsza niż Lispa.

Co to jest instrukcja?

Porównajmy taki fragment oryginału:

defrecord and related functions are covered in Section 6.3, Protocols.

z odpowiadającym mu tłumaczeniem:

Instrukcję defrecord i powiązane funkcje omawiamy w podrozdziale 6.3, „Protokoły”.

Tłumacz – słusznie – uznaje, że po polsku to zdanie brzmiałoby koślawo bez wprowadzenia na początku rzeczownika określającego, cóż to jest owo defrecord. Wybiera słowo „instrukcja”, które nie budziłoby żadnych sprzeciwów, gdyby to była książka o Pythonie albo C. Tu jednak mam wątpliwości. Wiele języków programowania odróżnia wyrażenia od instrukcji, i w nich te drugie rozumiane są jako autonomiczne fragmenty wykonywalnego kodu potencjalnie zmieniającego stan programu. A przecież Clojure kładzie duży nacisk na niezmienność danych! Co więcej, w Clojure, jak we wszystkich Lispach i wielu innych językach funkcyjnych, tak rozumianych instrukcji nie ma (albo patrząc z innego punktu widzenia: termin ten jest tożsamy z terminem „wyrażenie”) -- kod programu po prostu składa się z wyrażeń.

Jeśli więc nie instrukcja, to co? W angielskim żargonie lispowym używane jest słowo form na określenie obiektu, który ma być poddany ewaluacji. Jeśli ten obiekt jest listą, której pierwszy element jest symbolem (i w takim razie składnia i semantyka listy są wyznaczone przez ten symbol, który może nazywać funkcję, makro albo wbudowaną konstrukcję języka), to nazwy tego symbolu używa się często jako przydawki. Mówi się więc o „defmacro forms”, „defvar forms”, itd. To właśnie to określenie mógł tu pominąć Halloway. A jak jest po polsku form? Znowu: nie ma powszechnej zgody. Można by to mechanicznie przełożyć na forma, ale moim zdaniem nazwą mniej przeładowaną znaczeniowo i bardziej oddającą sens jest formuła. W użyciu są obie wersje i w Google można znaleźć ich przykładowe wystąpienia.

(Na marginesie można oddać tłumaczowi sprawiedliwość, że Halloway tą elizją zdaje się sugerować, że defrecord jest funkcją, gdy w rzeczywistości jest to makro. Z drugiej strony, makra w Clojure są w istocie funkcjami, których vars (patrz niżej) mają ustawioną odpowiednią flagę, co powoduje specjalne traktowanie ich przez kompilator.)

Zmienna zmiennej nierówna

Znowu zacznę od cytatu, tym razem najpierw dwóch kawałków tłumaczenia:

Nie występują tu zmienne, modyfikowalny stan ani rozgałęzienia.

Przedrostek #' oznacza, że funkcję zapisano w zmiennej języka Clojure (...)

A tak wyglądają te fragmenty w oryginale:

It has no variables, no mutable state, and no branches.

The prefix #' indicates that the function was stored in a Clojure var (...)

W polskim tłumaczeniu w obydwu tych fragmentach pojawia się słowo zmienna. Tymczasem spojrzenie na oryginał ujawnia, że słowo to ma dwa różne odcienie znaczeniowe, z których każdy oddawany jest po angielsku inaczej: raz jest to variable, a raz var.

Co to jest variable, wiadomo z innych języków: nazwane „pudełko” przechowujące wartość. (Zauważmy, że Halloway używa tego słowa mówiąc o zmiennych w Javie.) Jest to termin ogólny i używany w kontekście wszystkich języków imperatywnych, jak C czy Perl. Natomiast var jest terminem węższym i oznacza jedną z clojurowych implementacji takiego pudełka. Dokładniej mówiąc, jest to obiekt klasy clojure.lang.Var. Obiekty takie mają dwie charakterystyczne cechy, nietypowe dla zmiennych z innych języków, a odróżniające je od atomów, również podobnych do zmiennych:

  • wartości var mogą być różne w różnych wątkach (przy czym istnieje koncepcja głównego wiązania, czyli wartości domyślnej, którą nowo utworzone wątki widzą dopóki jej sobie nie przesłonią własnym; takie wiązanie nie musi istnieć);
  • obiekty takie są pamiętane w przestrzeniach nazw: w istocie o przestrzeni nazw można myśleć jako o mapie wiążącej symbol z obiektem var.

(Taka dychotomia nazewnicza jest endemiczna dla Clojure i ma również miejsce przy funkcjach: w angielskim slangu clojurowym mówi się o fns, czytane „ef-ens”, co oznacza obiekty implementujące interfejs clojure.lang.IFn).

To dopiero dylemat dla tłumacza! Nie mam pojęcia, co mógłbym tu zaproponować. Można by pozostać przy długim, doprecyzowującym określeniu „zmienna języka Clojure” dla odróżnienia od „zmiennej” po prostu, ale ceną za to jest rozwlekłość. Nie wiem, czy można jej jakoś uniknąć.

INSERT INTO użytkownik (imię) VALUES ('Judyto')

Ach, kod wypluwający komunikaty w języku naturalnym! Błogosławieni użytkownicy angielszczyzny, albowiem oni odmianą przez przypadki martwić się nie muszą. Halloway, na nieszczęście tłumacza, wpada na pomysł uogólnienia kanonicznego „Hello, world” vel „Witaj, świecie” poprzez sparametryzowanie witanego obiektu.

Chciałoby się, żeby funkcja witająca zwracała się do użytkownika w wołaczu. Tłumacz osiąga to bez problemu:

(defn hello [name]
  (str "Witaj, " name))

I świetnie. Tylko, że trzeba wołać tę funkcję tak: (hello "Janku"), co jest trochę nienaturalne. A co, jeśli oprócz wyświetlenia powitania chcemy imię zapisać też w bazie danych? Z drugiej strony, licentia poetica tłumacza nie może sięgać tak daleko, żeby walnąć tu

(defn witaj [imię]
  (str "Witaj, " (odmień imię :wołacz)))

!

Warto, nie warto?

Czy warto będzie kupić „Programowanie w języku Clojure” i przeczytać po polsku? Myślę, że tak, o ile ktoś jeszcze nie czytał po angielsku lub woli ojczysty język nawet kosztem drobnych nieścisłości. Jak już mówiłem, jestem pełen uznania dla pracy tłumacza i chylę czoła. Podziwiam!

Mam za to wątpliwości, czy warto w ogóle tłumaczyć książki o technologiach. W pierwotnym zamyśle reszta niniejszej notki miała stanowić rozważania na ten temat, ale rozważania techniczne tak się rozrosły, że wpis zrobiłby się za długi. Więc o tym następnym razem.