Carpをチョット触るその2

Carpをチョット触る - gos-k’s blog

前回に続いてCarpその2。 hello worldは書いたので、続いてfizz bazzを書く。

(defn fizz-buzz [n]
  (do
    (if (and (= (mod n 3) 0)
             (= (mod n 5) 0))
        (IO.print "fizzbuzz ")
        (if (= (mod n 5) 0)
            (IO.print "buzz ")
            (if (= (mod n 3) 0)
                (IO.print "fizz ")
                (do
                  (IO.print &(Int.str n))
                  (IO.print " ")))))
    (if (< n 20)
        (fizz-buzz (+ n 1))
        0)))

(defn main []
  (fizz-buzz 1))
carp -x fizz-buzz.carp
1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz 

if式の中にprintが沢山あるのでまとめたいのだが、うまく動かず。

(defn fizz-bazz [n]
  (do
    (IO.print (if (and (= (mod n 3) 0)
                       (= (mod n 5) 0))
                  "fizzbuzz"
                  (if (= (mod n 5) 0)
                      "buzz"
                      (if (= (mod n 3) 0)
                          "fizz"
                          &(Int.str n)))))
    (if (< n 20)
        (do
          (IO.print " ")
          (fizz-bazz (+ n 1)))
        (do
          (IO.println "")
          0))))

(defn main []
  (fizz-bazz 1))
carp -x fizz-buzz2.carp
  fizz  buzz fizz   fizz buzz  fizz   fizzbuzz   fizz  buzz

型エラーも出ずに実行できるが、数字が出力されない。 何かやり方間違ってるんだろうがよく分からん。。。

出力コードの対象部分を見ると

            } else {
                String _59 = Int_str(n);
                String* _60 = &_59; // ref
                String* _61 = _60;
                String_delete(_59);
                _62 = _61;
            }

参照を渡しているが、参照先の文字列がスコープから外れるから削除されているように見える。

(defn fizz-bazz [n]
  (do
    (IO.print &(if (and (= (mod n 3) 0)
                        (= (mod n 5) 0))
                   @"fizzbuzz"
                   (if (= (mod n 5) 0)
                       @"buzz"
                       (if (= (mod n 3) 0)
                           @"fizz"
                           (Int.str n)))))
    (if (< n 20)
        (do
          (IO.print " ")
          (fizz-bazz (+ n 1)))
        (do
          (IO.println "")
          0))))

(defn main []
  (fizz-bazz 1))
carp -x fizz-buzz3.carp
1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz

これで正しく動いてるように見えるが、文字列リテラルをわざわざコピーするもんなのか?

最後にループで書いてみる。

(defn main []
  (do
    (let [n 1]
      (while (<= n 20)
        (do
          (IO.print &(if (and (= (mod n 3) 0)
                              (= (mod n 5) 0))
                         @"fizzbuzz"
                         (if (= (mod n 5) 0)
                             @"buzz"
                             (if (= (mod n 3) 0)
                                 @"fizz"
                                 (Int.str n)))))
          (IO.print (if (< n 20)
                        " "
                        "\n"))
          (set! n (inc n)))))
    0))
carp -x fizz-buzz4.carp 
1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz

複数の式を列挙出来るのはdoだけで、defnのbodyですらダメなのか。 中々凄いな。。。