środa, 7 maja 2014

Myślenie abstrakcyjne w Pythonie

Wpływ używanego języka na myślenie można nieraz odczuć samemu, jeśli w tym samym czasie programuje się dużo w różnych językach. Mając głowę wypełnioną pythonowymi narzędziami (comprehension, generatory, iteratory) próbowałem odruchowo zamienić wektor par w C++ (uzyskany z jakiejś funkcji) na odpowiednią mapę:
   std::vector< std::pair >  ->  std::map
W Pythonie analogiczna konstrukcja jest natychmiastowa:
   >>> x = [ (1,"a"), (2,"b") ]
   >>> dict( x )
   {1: 'a', 2: 'b'}
W C++ jednak analogia nie działa: Zamiast :
   std::vector< std::pair > v;
   std::map  m( v );
Musimy napisać :
   std::vector< std::pair > v;
   std::map  m( v.begin(), v.end() );
Ale to jest jeszcze nic. Trudnośc pojawiła się dopiero, gdy uświadomiłem sobie, że potrzebuję odwrotnej mapy (nie int -> string, a string -> int). W Pythonie mam od razu:
   >>> {name:value for value, name in x}
   {'a': 1, 'b': 2}

Próby użycia swap, transform itp. narzędzi w C++ zniechęciły mnie szybko, użyłem iteratorów i zrobiłem wszystko pętlami. Kod działa, ale nie jest ani prosty ani ładny, zamiast z jednej składa się z kilku linijek i zawiera dodatkowe obiekty, stworzone tylko po to, by to przekonwertować.

Z ciekawości uruchomiłem ghci i próbowałem analogiczną konstrukcję wykonać w Haskellu. Zaraz jednak okazało się, że nie znam go na tyle, by zrobić to od razu, potrzebuję importować jakieś moduły, szukać API w hoogle itd. itp. Python zwycięża wszystko równowagą pomiędzy prostotą a możliwościami ekspresji. Mamy tam comprehension, iteratory, generatory, yield i obiekty. Kilka narzędzi, które pozwalają budować złożone struktury listowe, mapy i inne zwierzęta z ZOO funkcyjnego, a wszystko w sposób miły i prosty. Mamy interaktywną konsolę, help do API i to już dośc, by szybko pisać złożony kod. Po prostu zapisywać myśl w postaci kodu.