<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>tag:plblog.danieljanus.pl,2019:category:haskell</id>
  <title>Daniel Janus – Haskell</title>
  <link href="http://plblog.danieljanus.pl/category/haskell/"/>
  <updated>2012-01-10T00:00:00Z</updated>
  <author>
    <name>Daniel Janus</name>
    <uri>http://danieljanus.pl</uri>
    <email>dj@danieljanus.pl</email>
  </author>
  <entry>
    <id>tag:plblog.danieljanus.pl,2012-01-10:post:praktyczne-uzycie-monady-state</id>
    <title>Praktyczne użycie monady state</title>
    <link href="http://plblog.danieljanus.pl/praktyczne-uzycie-monady-state/"/>
    <updated>2012-01-10T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;Wreszcie rozumiem monady!&lt;/p&gt;&lt;p&gt;Pierwszy raz zetknąłem się z nimi dobrych osiem lat temu, przy okazji nauki Haskella; wtedy jednak nie starczyło mi cierpliwości, aby zaznajomić się z podstawami teoretycznymi. Sprawy nie ułatwiał fakt, że trudno o &lt;em&gt;naprawdę&lt;/em&gt; przystępne i zrozumiałe wprowadzenie do tego tematu: wygląda na to, że każdy adept Haskella, zrozumiawszy monady, pisze na ten temat własny &lt;em&gt;tutorial&lt;/em&gt;. Ja się powstrzymam od tego naturalnego odruchu i po prostu odeślę do niesamowicie szczegółowego, ośmioczęściowego &lt;a href="http://mvanier.livejournal.com/3917.html"&gt;cyklu artykułów&lt;/a&gt; autorstwa Mike'a Vaniera, który -- wreszcie! – sprawił, że coś mi „zaskoczyło” w umyśle. Zamiast tego w tym wpisie wynotuję najważniejsze spostrzeżenia, jakie zapamiętałem, a potem pokażę dwie wersje pewnego kodu operującego na sekwencjach bitów: niemonadyczną i napisaną z użyciem monady &lt;code&gt;state&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Mike zakłada znajomość Haskella, jak pisze we wstępie, na poziomie typów polimorficznych i klas typów; w praktyce jednak myślę, że do zrozumienia tekstu wystarczy pewne obycie z haskellową notacją (bardzo zresztą przypominającą zwykłą notację matematyczną), bo bardziej zaawansowane rzeczy są wyjaśniane w tekście na bieżąco. Bardzo polecam.&lt;/p&gt;&lt;p&gt;Oto więc moje notatki:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;Kluczowe dla zrozumienia monad jest pojęcie &lt;em&gt;funkcji monadycznych&lt;/em&gt;; znacznie łatwiej jest je sobie intuicyjnie wyobrazić niż monadyczne wartości, zwracane przez &lt;code&gt;m-return&lt;/code&gt;. Mike podaje pewne intuicje także dla tych drugich, ale dla mnie ważne jest, żeby myśleć o monadach w kategoriach (wzbogaconych) funkcji, a nie wartości przez nie zwracanych.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;Łatwo wydefiniować przy użyciu prostego złożenia operacji &lt;code&gt;m-bind&lt;/code&gt; i &lt;code&gt;m-return&lt;/code&gt; funkcję składającą ze sobą dwie funkcje monadyczne. Przy użyciu tego operatora, który Mike nazywa &lt;code&gt;&lt;=&lt;&lt;/code&gt;, prawa rządzące monadami wyrażają się w elegancki i prosty do zapamiętania sposób: jest to operator łączny oraz &lt;code&gt;m-return&lt;/code&gt; jest jego lewą i prawą jedynką.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;I bodaj najistotniejsza rzecz – nie trzeba rozumieć monad, żeby ich używać. Niby oczywiste i niby tak właśnie pisałem do tej pory kod haskellowy, radośnie używając &lt;code&gt;do&lt;/code&gt;-notacji tak jakbym pisał kod imperatywny; ale okazuje się, że w ten sam sposób można z powodzeniem używać monady stanu i wyjaśnić, co ona robi, zupełnie w oderwaniu od całej reszty teorii monad. Wiedza na temat tego, co się dzieje „pod spodem”, jest konieczna tylko (i aż!) do zrozumienia, co poszczególne monady mają ze sobą wspólnego.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Reszta tego wpisu będzie poświęcona właśnie przykładowemu użyciu monady stanu w Clojure.  &lt;a href="http://plblog.danieljanus.pl/leniwa-wersja-makra"&gt;Pisałem wcześniej&lt;/a&gt;, że nie widziałem dotąd kodu, który dałby się wyrazić przejrzyściej zapisany z użyciem monad niż bez nich – i właśnie na taki kod się natknąłem.&lt;/p&gt;&lt;p&gt;Wyobraźmy więc sobie, że mamy strumień bitów. Dla prostoty zdefiniujmy sobie przykładowy strumień, na którym będziemy testować nasze funkcje, jako clojurowy wektor zer i jedynek.&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;def&lt;/span&gt; &lt;span class="hljs-title"&gt;v&lt;/span&gt; [&lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt;])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Chcemy naddać naszemu strumieniowi pewne uporządkowanie: zdekodować zera i jedynki, które z niego przychodzą, według jakiegoś kodu o zmiennej długości. Najbardziej oczywistym, znanym każdemu kodem jest kod binarny: czytamy ze strumienia ileś bitów, traktujemy je jako binarną (bez znaku) reprezentację pewnej liczby i zwracamy tę liczbę. Łatwo napisać w Clojure funkcję, która to robi.&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-binary&lt;/span&gt; [n bits]
  (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;loop&lt;/span&gt;&lt;/span&gt; [res &lt;span class="hljs-number"&gt;0&lt;/span&gt; n n [fst &amp;amp; rst &lt;span class="hljs-symbol"&gt;:as&lt;/span&gt; bs] bits]
    (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;zero?&lt;/span&gt;&lt;/span&gt; n)
      [res bs]
      (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;recur&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; res res fst) (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; n) rst))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Spróbujmy wczytać z naszego strumienia czterobitową liczbę:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-name"&gt;read-binary&lt;/span&gt; &lt;span class="hljs-number"&gt;4&lt;/span&gt; v)
&lt;span class="hljs-comment"&gt;;=&amp;gt; [14 (1 0 1 0 1 0)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Czternaście. Ale zauważmy, że zdekodowana liczba nie jest jedyną zwracaną wartością! Żeby dało się z naszego strumienia odczytywać dalsze liczby, musimy zwrócić parę (wektor dwuelementowy): wartość odczytana plus &lt;em&gt;reszta strumienia&lt;/em&gt;, z której będziemy czytać dalej. Piszemy wszak funkcyjnie: nie zmieniamy naszych wartości w miejscu, tylko z jednych wartości produkujemy następne.&lt;/p&gt;&lt;p&gt;Innym rodzajem kodu jest &lt;em&gt;kod unarny&lt;/em&gt;: czytamy po prostu ze strumienia jedynki, aż napotkamy pierwsze zero – wtedy przestajemy czytać i naszą wartością jest liczba przeczytanych bitów. W ten sposób dowolną liczbę dodatnią &lt;em&gt;n&lt;/em&gt; da się zareprezentować na &lt;em&gt;n&lt;/em&gt; bitach. Implementacja jest równie prosta:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-unary&lt;/span&gt; [bits]
  (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;loop&lt;/span&gt;&lt;/span&gt; [n &lt;span class="hljs-number"&gt;1&lt;/span&gt; [fst &amp;amp; rst] bits]
    (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;zero?&lt;/span&gt;&lt;/span&gt; fst)
      [n rst]
      (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;recur&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;inc&lt;/span&gt;&lt;/span&gt; n) rst))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sprawdzamy:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-name"&gt;read-unary&lt;/span&gt; v)
&lt;span class="hljs-comment"&gt;;=&amp;gt; [4 (1 0 1 0 1 0)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Trzy jedynki i zero, razem cztery skonsumowane bity, więc odczytaną liczbą jest 4. Działa.&lt;/p&gt;&lt;p&gt;Spróbujmy teraz skleić nasze funkcje, to znaczy odczytać ze strumienia dwie liczby: najpierw zakodowaną unarnie, a potem binarnie na sześciu bitach.&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;let&lt;/span&gt;&lt;/span&gt; [[x v1] (&lt;span class="hljs-name"&gt;read-unary&lt;/span&gt; v)
      [y v2] (&lt;span class="hljs-name"&gt;read-binary&lt;/span&gt; &lt;span class="hljs-number"&gt;6&lt;/span&gt; v1)]
  [x y])
&lt;span class="hljs-comment"&gt;;=&amp;gt; [4 42]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Wynik jest poprawny, ale kod nieelegancki: tak naprawdę nie interesują nas te wszystkie &lt;code&gt;v&lt;/code&gt;, &lt;code&gt;v1&lt;/code&gt;, &lt;code&gt;v2&lt;/code&gt;, które przepychamy przez nasze funkcje; potrzebujemy tylko przeczytanych liczb, a poszczególne części strumienia są nam tylko po to, żeby mieć z czego czytać. Im więcej składanych ze sobą operacji, tym łatwiej się pomylić.&lt;/p&gt;&lt;p&gt;Tu wkracza monada stanu, która umożliwia ukrycie tych pośrednich wartości i bardziej eleganckie złożenie &lt;code&gt;read-unary&lt;/code&gt; i &lt;code&gt;read-binary&lt;/code&gt;. Monadycznie zapisalibyśmy to jakoś tak:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-name"&gt;domonad&lt;/span&gt; state-m
         [x read-unary
          y (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;partial&lt;/span&gt;&lt;/span&gt; read-binary &lt;span class="hljs-number"&gt;6&lt;/span&gt;)]
         [x y])
&lt;span class="hljs-comment"&gt;;=&amp;gt; #&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Wygląda to bardzo podobnie. &lt;code&gt;domonad state-m&lt;/code&gt; jest jak &lt;code&gt;let&lt;/code&gt;. Tak jak chcieliśmy, nie przekazujemy naszego stanu (strumienia) &lt;em&gt;explicite&lt;/em&gt;; zamiast tego przy &lt;code&gt;x&lt;/code&gt; i &lt;code&gt;y&lt;/code&gt; podajemy funkcje, które mają być zawołane na aktualnym stanie, żeby uzyskać żądaną wartość i nowy stan.&lt;/p&gt;&lt;p&gt;No dobrze, ale gdzie tu miejsce na nasz stan początkowy? Jak go przekazać? Proste: powyższa formuła, jak widać z mało czytelnego wyniku, zwróciła jakąś funkcję. Wystarczy ją teraz zawołać na naszym początkowym stanie, aby uzyskać wynik wraz ze stanem końcowym:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-name"&gt;*1&lt;/span&gt; v)
&lt;span class="hljs-comment"&gt;;=&amp;gt; [[4 42] nil]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Jedyne, co wydaje się nadmiarowe w naszym złożeniu, to owo &lt;code&gt;partial&lt;/code&gt; pojawiające się wyżej. Jest to efekt uboczny faktu, że Clojure w odróżnieniu od Haskella rozróżnia funkcje jedno- i więcejargumentowe (tak dokładniej to w Haskellu występują wyłącznie funkcje jednoargumentowe). Skoro w &lt;code&gt;domonad state-m&lt;/code&gt; powinny na przemian pojawiać się symbole i funkcje jednoargumentowe biorące stan, to gdy nasza funkcja akceptuje coś jeszcze (tu: liczbę bitów), powinniśmy zrobić z niej funkcję jednoargumentową za pomocą &lt;code&gt;partial&lt;/code&gt;. Alternatywnie, jeżeli chcemy trzymać się stylu monadycznego, możemy przepisać &lt;code&gt;read-binary&lt;/code&gt; jako:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-binary&lt;/span&gt; [n]
  (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;fn&lt;/span&gt;&lt;/span&gt; [bits]
    (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;loop&lt;/span&gt;&lt;/span&gt; [res &lt;span class="hljs-number"&gt;0&lt;/span&gt; n n [fst &amp;amp; rst &lt;span class="hljs-symbol"&gt;:as&lt;/span&gt; bs] bits]
      (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;zero?&lt;/span&gt;&lt;/span&gt; n)
        [res bs]
        (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;recur&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; res res fst) (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; n) rst)))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Teraz zamiast &lt;code&gt;(partial read-binary 6)&lt;/code&gt; możemy napisać po prostu &lt;code&gt;(read-binary 6)&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Teraz, kiedy umiemy już składać operacje stanowe, zilustrujemy to przy pomocy jeszcze jednego kodu, a właściwie rodziny kodów nazywanych &lt;em&gt;kodami Golomba&lt;/em&gt;. Po szczegółowy opis odsyłam do &lt;a href="http://pl.wikipedia.org/wiki/Kod_Golomba"&gt;Wikipedii&lt;/a&gt;, natomiast dla potrzeb tego artykułu wystarczy nam wiedza, że te kody są parametryzowane jedną liczbą &lt;em&gt;m&lt;/em&gt;. Liczba w kodzie Golomba jest podzielona na dwie części, z których pierwsza jest zakodowana unarnie, a druga -- nie większa niż &lt;em&gt;m&lt;/em&gt; – binarnie. W implementacji możemy więc skorzystać z naszych gotowych już funkcji &lt;code&gt;read-unary&lt;/code&gt; i &lt;code&gt;read-binary&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Bez dłuższych już komentarzy przedstawię dwie implementacje: eksplicytną i używającą monady stanu. Obie będą używać pomocniczej funkcji &lt;code&gt;read-bit&lt;/code&gt;, czytającej po prostu jeden bit ze strumienia i używanej tak samo jak &lt;code&gt;read-unary&lt;/code&gt; czy &lt;code&gt;read-binary&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-bit&lt;/span&gt; [[bit &amp;amp; bits]]
  [bit bits])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Najpierw wersja niemonadyczna:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-golomb&lt;/span&gt; [m]
  (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;fn&lt;/span&gt;&lt;/span&gt; [bits]
    (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;let&lt;/span&gt;&lt;/span&gt; [k (&lt;span class="hljs-name"&gt;clog2&lt;/span&gt; m)
          r (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;-&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;bit-shift-left&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; k) m)
          [a bits1] (&lt;span class="hljs-name"&gt;read-unary&lt;/span&gt; bits)
          [b bits2] ((&lt;span class="hljs-name"&gt;read-binary&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; k)) bits1)
          [ir bits] (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt; b r)
                      [b bits]
                      (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;let&lt;/span&gt;&lt;/span&gt; [[nb bits] (&lt;span class="hljs-name"&gt;read-bit&lt;/span&gt; bits)]
                        [(&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; b b nb (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;-&lt;/span&gt;&lt;/span&gt; r)) bits]))]
      [(&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;*&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; a) m) ir) bits])))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A teraz używająca monad. Żeby nie przeplatać &lt;code&gt;let&lt;/code&gt; i &lt;code&gt;domonad&lt;/code&gt;, można po prostu zdefiniować funkcję zwracającą pewną stałą wartość i niezmieniony stan – nazwę ją &lt;code&gt;m-const&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;m-const&lt;/span&gt; [x]
  (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;fn&lt;/span&gt;&lt;/span&gt; [state]
    [x state]))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Używając jej, możemy zaimplementować &lt;code&gt;read-golomb&lt;/code&gt; tak:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs clojure"&gt;(&lt;span class="hljs-keyword"&gt;defn&lt;/span&gt; &lt;span class="hljs-title"&gt;read-golomb-monadic&lt;/span&gt; [m]
  (&lt;span class="hljs-name"&gt;domonad&lt;/span&gt; state-m
           [k (&lt;span class="hljs-name"&gt;m-const&lt;/span&gt; (&lt;span class="hljs-name"&gt;clog2&lt;/span&gt; m))
            r (&lt;span class="hljs-name"&gt;m-const&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;-&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;bit-shift-left&lt;/span&gt; &lt;span class="hljs-number"&gt;1&lt;/span&gt; k) m))
            a read-unary
            b (&lt;span class="hljs-name"&gt;read-binary&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; k))
            nb (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt; b r) (&lt;span class="hljs-name"&gt;m-const&lt;/span&gt; &lt;span class="hljs-literal"&gt;nil&lt;/span&gt;) read-bit)]
           (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;*&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;dec&lt;/span&gt;&lt;/span&gt; a) m)
              (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt; b r) b (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;+&lt;/span&gt;&lt;/span&gt; b b nb (&lt;span class="hljs-name"&gt;&lt;span class="hljs-built_in"&gt;-&lt;/span&gt;&lt;/span&gt; r))))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Czytelniej?&lt;/p&gt;&lt;/div&gt;</content>
  </entry>
</feed>
