よりそいAda

同じ問題をAdaでやってみた。

まずはEmacsを起動します。使い回せそうなEmacsが有ればそれを使いますが、Emacsごとに開いているファイルの文脈が有るので、目的ごとに結構たくさんEmacsを走らせます。2重screenの兼ね合いもありますし。とりあえず僕もボディファイルから作ります。ヘッダは後。

yudai@lysithea% emacs yorisoi.adb

手癖でとりあえずの構造を作ります。

procedure Yorisoi is
begin
end Yorisoi;

おもむろに副プログラムの構造ができあがります。

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
   begin
   end Count_Comma;

begin
end Yorisoi;

「数えるための変数が必要だなー」

procedure Yorisoi is

   function Count_Comma (About :out String) return Integer is
      Count : Integer := 0;
   begin

   end Count_Comma;

begin
end Yorisoi;

「文字列をイテレートするにはforかな」

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
      end loop;
   end Count_Comma;

begin
end Yorisoi;

「関数名からして決め撃ちだし、いいよハードコーディングで」

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About(I) = ',' then
      end loop;
   end Count_Comma;

begin
end Yorisoi;

「増やしてif閉じて」

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About(I) = ',' then
            Count := Count + 1;
         end if;
      end loop;
   end Count_Comma;

begin
end Yorisoi;

「あとは戻すだけ」

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About(I) = ',' then
            Count := Count + 1;
         end if;
      end loop;

      return Count;
   end Count_Comma;

begin
end Yorisoi;

「適当に実験しよう。標準出力にでも出せばいいよね」と思いつつ、Integer_Text_IOを呼ぶのはめんどくさいので、Integer'Imageする。

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About(I) = ',' then
            Count := Count + 1;
         end if;
      end loop;

      return Count;
   end Count_Comma;

begin
   Put_Line (Integer'Image(Count_Comma ("Here, Here, and Here,")));
end Yorisoi;

パッケージ読み込み。

with Ada.Text_IO; use Ada.Text_IO;
procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About(I) = ',' then
            Count := Count + 1;
         end if;
      end loop;

      return Count;
   end Count_Comma;

begin
   Put_Line (Integer'Image(Count_Comma ("Here, Here, and Here,")));
end Yorisoi;

できたかな? ここで一度コンパイル。

yudai@lysithea% gnatmake yorisoi
gcc -c yorisoi.adb
gnatbind -x yorisoi.ali
gnatlink yorisoi.ali

問題なさそう。実行。

yudai@lysithea% ./yorisoi
 2

良さそうだな。

後は、コードをきれいに。コーディング規約重要。個人的にはDoDのよりもNASAのやつの方が好きかな。関数名の後に空白入れるとかそこら辺。

with Ada.Text_IO; use Ada.Text_IO;

procedure Yorisoi is

   function Count_Comma (About : String) return Integer is
      Count : Integer := 0;
   begin
      for I in About'Range loop
         if About (I) = ',' then
            Count := Count + 1;
         end if;
      end loop;

      return Count;
   end Count_Comma;

begin
   Put_Line (Integer'Image (Count_Comma ("Here, Here, and Here,")));
end Yorisoi;

確認してみる。gmkがgnatmake -gnaty3abefhiklM120nprtへのaliasで、これがNASAのコーディング規約に従ってる設定。オプション自体の詳細はマニュアル参照の事。gnat check使ってもいいかも。

yudai@lysithea% gmk yorisoi
gcc -c -gnaty3abefhiklM120nprt yorisoi.adb
gnatbind -x yorisoi.ali
gnatlink yorisoi.ali

というわけで完成。

Adaだと固定長文字列の操作が楽だなー。ミスが入り込む余地が無い。今回は問題が簡単だったのでAdaのいいところがあまり出なかったかも。もっと難しい問題だとコンパイル時エラーの検出と親切すぎる警告文がとてもありがたいんですが。