Czym jest Joy i dlaczego warto go poznać
Joy to funkcyjny język programowania stworzony przez Manfreda von Thunena, który realizuje radykalnie prostą ideę: programowanie to kompozycja funkcji, a wszystkie funkcje operują na jednym wspólnym stosie. Nie ma tu zmiennych, nie ma parametrów, nie ma lambda expressions. Program to po prostu sekwencja operacji, które przekształcają stan stosu.
Jeśli kiedykolwiek programowaliście w Forth albo PostScript, Joy wyda wam się znajomy — ale z jedną fundamentalną różnicą: Joy jest funkcyjny, nie imperatywny. Każda operacja jest czystą funkcją ze stosu na stos. Nie ma efektów ubocznych (przynajmniej w teorii), a kompozycja programów jest po prostu konkatenacją — dosłownie sklejaniem sekwencji operacji.
Joy jest fascynujący, bo pokazuje, jak daleko można posunąć minimalizm w projektowaniu języka. Cały język mieści się w garści koncepcji, a mimo to jest Turing-kompletny i potrafi wyrazić dowolne obliczenie. To lekcja w elegancji, która inspiruje twórców innych języków (np. Kitten, Factor, Pointfree Haskella).
Krótka historia i ewolucja
Joy został stworzony przez Manfreda von Thunena na La Trobe University w Melbourne, Australia, na przełomie lat 90. i 2000. Von Thunen był zafascynowany kombinatoryką i rachunkiem lambda i chciał stworzyć język, w którym programy są bezpośrednio kompozycją funkcji — bez pośrednictwa zmiennych i parametryzacji.
Inspiracją były Forth (model stosowy), FP Johna Backusa (programowanie na poziomie funkcji) i kombinatory (szczególnie S, K, I, B, C z logiki kombinatorycznej). Joy łączy te idee w spójny system, w którym każdy program jest funkcją ze stosu na stos.
Język nigdy nie zyskał dużej popularności — pozostał niszowym projektem akademickim z małą, ale entuzjastyczną społecznością. Implementacja referencyjna to interpreter w C. Powstały też alternatywne implementacje, m.in. w Haskellu i Pythonie. Von Thunen publikował liczne artykuły o Joy na swojej stronie university, tworząc bogatą bazę teoretyczną.
Kluczowe cechy i filozofia
Stos jako jedyna struktura danych. W Joy nie ma zmiennych ani nazwanych parametrów. Wszystko dzieje się na stosie: wartości są odkładane na stos, operacje zdejmują argumenty ze stosu i odkładają wyniki. Program 2 3 + odkłada 2 i 3 na stos, a potem + zdejmuje obie wartości i odkłada 5.
Konkatenacja = kompozycja. To jest genialne w swojej prostocie. Jeśli f jest programem (funkcją ze stosu na stos) i g jest programem, to f g (zapisane obok siebie) jest programem, który najpierw wykonuje f, potem g. Nie ma operatora kompozycji — sama konkatenacja jest kompozycją. To sprawia, że algebry programów Joy są wyjątkowo proste.
Cytowanie i kombinator. W Joy programy mogą być danymi — sekwencję operacji można „zacytować” w nawiasach kwadratowych [2 3 +], tworząc wartość na stosie. Kombinat to operacja wyższego rzędu, która zdejmuje cytowany program (i ewentualnie inne wartości) ze stosu i wykonuje go w określony sposób. Na przykład map bierze listę i cytowany program, i aplikuje program do każdego elementu listy.
Brak zmiennych = point-free style. W Joy nie da się pisać kodu z nazwanymi parametrami — wszystko jest „point-free” z definicji. To wymusza myślenie o programach jako kompozycji transformacji, co jest cennym ćwiczeniem intelektualnym nawet dla doświadczonych programistów.
Kombinatory to serce Joy. Zamiast pętli i rekurencji z nazwanymi funkcjami, Joy oferuje kombinatory jak map, filter, fold, linrec (linear recursion), genrec (general recursion), binrec (binary recursion) i wiele innych. Każdy kombinator definiuje schemat obliczeniowy, a programista dostarcza tylko „ciało” jako cytowany program.
Gdzie Joy sprawdza się najlepiej
Joy nie jest językiem produkcyjnym — to narzędzie edukacyjne i intelektualne. Sprawdza się najlepiej jako sposób na zrozumienie fundamentalnych koncepcji programowania funkcyjnego: kompozycji, abstrakcji wyższego rzędu i algebry programów.
W edukacji Joy bywa używany do nauczania studentów o kombinatorycznym stylu programowania i o związkach między logiką a informatyką. Jego prostota sprawia, że można szybko przejść od podstaw do zaawansowanych koncepcji.
Joy jest też inspiracją dla twórców języków i DSL-i. Jego idee — kompozycja przez konkatenację, model stosowy, cytowanie programów — pojawiają się w różnych formach w językach takich jak Factor, Kitten, a nawet w pewnych aspektach programowania point-free w Haskellu.
Jak wygląda kod w Joy
Kilka prostych przykładów:
(* Silnia za pomocą linear recursion *)
DEFINE
fact == [0 =] [pop 1] [dup 1 - fact *] linrec.
(* Quicksort *)
DEFINE
qsort == [small] [] [uncons] [split] [swapd concat] linrec.
(* Suma kwadratów listy *)
DEFINE
sumsq == [dup *] map 0 [+].
linrec to kombinator rekurencji liniowej, który przyjmuje cztery cytowane programy: predykat (czy już koniec?), przypadek bazowy, krok rekurencyjny (przed rekurencją) i krok po rekurencji. Silnia w Joy czyta się niemal jak definicja matematyczna.
A oto przetwarzanie listy:
(* Podwój parzyste liczby z listy *)
[1 2 3 4 5 6] [2 rem 0 =] filter [2 *] map.
Czytanie od lewej: weź listę, odfiltruj parzyste, podwój każdą. Proste, deklaratywne, czytelne — jeśli rozumiecie model stosowy.
Ekosystem i narzędzia
Ekosystem Joy jest minimalny. Referencyjna implementacja to interpreter w C, dostępny jako open source. Istnieją porty do innych języków, ale żaden nie zyskał statusu „standardowego”. Nie ma menedżera pakietów, nie ma rozbudowanej biblioteki standardowej — Joy jest samowystarczalny.
Dokumentacja to przede wszystkim artykuły Manfreda von Thunena, dostępne na stronie La Trobe University. Są to teksty akademickie, ale napisane przystępnie, z licznymi przykładami. Nie znajdziecie tutoriali wideo ani interaktywnych kursów.
Najbliższym krewnym Joy z aktywnym ekosystemem jest Factor — język stosowy z rozbudowaną biblioteką, IDE i społecznością. Jeśli Joy was zainteresuje, Factor jest naturalnym następnym krokiem.
Mocne i słabe strony
Siłą Joy jest jego matematyczna czystość i prostota. Kompozycja przez konkatenację to piękna idea, która ujawnia algebraiczną strukturę programów. Brak zmiennych wymusza dyscyplinę myślenia, która procentuje w każdym innym języku.
Słabością jest czytelność dla większych programów. Point-free style działa dobrze dla krótkich sekwencji, ale przy złożonej logice biznesowej stos rośnie, a śledzenie, co jest na szczycie stosu w danym momencie, staje się koszmarem. To jest ten sam problem, który trapi Forth — brak nazwanych abstrakcji utrudnia rozumienie kodu.
Brak ekosystemu i społeczności to oczywiste ograniczenie. Joy jest językiem do nauki i eksploracji, nie do budowania aplikacji produkcyjnych.
Podsumowanie
Joy to intelektualna perełka — język, który w minimalnej formie ujawnia głębokie prawdy o programowaniu funkcyjnym. Nie jest to narzędzie do codziennej pracy, ale weekend z Joy potrafi trwale zmienić sposób, w jaki myślicie o kompozycji i abstrakcji.
Jeśli jesteście fanami Haskella, point-free style, albo po prostu lubicie eleganckie systemy — dajcie Joy szansę. A jeśli szukacie produkcyjnego języka stosowego z ekosystemem — sprawdźcie Factor. Joy otwiera drzwi, ale Factor zaprasza do środka.

