AdaでYield

そういえば大分昔に書こうと思っていて、完全に忘れてたのをふと思い出したので書いてみましょう。

PiroさんのJavaScript 1.7のyield文ってなんじゃらほに書かれているフィボナッチ数列を求める例がわかりやすいので、これをAdaで書いてみます。

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Yield is
   task type Test is
      entry Next (Value: out Integer);
   end Test;

   task body Test is
      A    : Integer := 0;
      B    : Integer := 1;
      Temp : Integer;
   begin
      loop
         select
            accept Next (Value : out Integer) do
               Value := A;
               Temp := B;
               B := A + B;
               A := Temp;
            end Next;
         or
            terminate;
         end select;
      end loop;
   end Test;

   Generator : Test;
   Value : Integer;
begin
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
   Generator.Next(Value); Put (Value); New_Line;
end Yield;

AdaのTaskは本当に強力すぎて、正直TaskだけでもAdaを使う価値有りすぎです。or terminateとか素敵すぎます。

あとはYieldとはあんまり関係ないですが、then abortとかもやばいです。10msでフィボナッチ数列を出来るだけ計算してみる、なんて処理がこんなに簡単に書けちゃいます。

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Yield is
   task type Test is
      entry Next (Value: out Integer);
   end Test;

   task body Test is
      A    : Integer := 0;
      B    : Integer := 1;
      Temp : Integer;
   begin
      loop
         select
            accept Next (Value : out Integer) do
               Value := A;
               Temp := B;
               B := A + B;
               A := Temp;
            end Next;
         or
            terminate;
         end select;
      end loop;
   end Test;

   Generator : Test;
   Value : Integer;

begin
   select
      delay 0.01;
   then abort
      loop
         Generator.Next(Value); Put (Value); New_Line;
      end loop;
   end select;
end Yield;

わぁ、かっこいい。