指向性メモ::2006-07-23

ページ情報
制作日
2006-07-23T00:41:50+09:00
最終更新日
2006-07-25T20:23:11+09:00

AdaでCurry化

Created:
2006-07-23T00:41:50+09:00

Curry化もできない奴とは話をしたくないと言われたので、がんばってみた。

ふぁーすとらい。関数ポインタ編。

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

procedure Curry is

   -- Ada95で追加された副プログラムへのアクセス型を使ってみる
   type Sum_Function_Type is access function(Y : in Integer) return Integer;
   function Curried_Sum(X : in Integer) return Sum_Function_Type is
      C : Integer;
      function Sum(Y : Integer) return Integer is
      begin
         return C + Y;
      end Sum;
   begin
      C := X;
      return Sum'Access;
   end Curried_Sum;

   Z : Sum_Function_Type;
begin
   Z := Curried_Sum(10);
end Curry;
curry.adb:15:14: subprogram must not be deeper than access type

いけると思ったのになー。これ、Ada05でも駄目かな?

せかんどとらい。Taskは世界を救う編。

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

procedure Curry is
   task type Sum_Task is
      entry Set_X(X : in Integer);
      -- なんで返値渡せるentryって存在しないんだろ
      entry Calc(Y : in Integer; Result : out Integer);
   end Sum_Task;

   task body Sum_Task is
      C : Integer; -- Xを保存しておくところ
   begin
      accept Set_X(X : in Integer) do
         C := X; 
      end Set_X;

      -- ループして何回でも使えるようにしておく
      loop
         select
            accept Calc(Y : in Integer; Result : out Integer) do
               Result := C + Y;
            end Calc;
         or
            terminate;
         end select;
      end loop;
   end Sum_Task;

   type Sum is access Sum_Task;

   function Curried_Sum(X : in Integer) return Sum is
      S : Sum;
   begin
      S := new Sum_Task;
      S.Set_X(X);
      return S;
   end Curried_Sum;

   S : Sum;
   R : Integer;

begin
   S := Curried_Sum(10);
   S.Calc(10, R);
   Put(R); -- 20
   S.Calc(20, R);
   Put(R); -- 30

   -- ドットで繋いでも書けるぞ!
   Curried_Sum(5).Calc(10, R);
   Put(R); -- 15
end Curry;

おおー、なんかちょっとカリー化とは違う気がするけど、おおむねね期待通りだ! なんかもう必死すぎて涙が出てきますね。え、任意の関数で出来るようにしろって?

もっと簡単にかける気がするので、誰かトライお願いします。

Comments
2
Trackbacks
0
PermaLink
http://yudai.arielworks.com/memo/2006/07/23/004150

useしないと外部パッケージの比較演算子が見えない件

Created:
2006-07-23T04:06:58+09:00
Modified:
2006-07-23T04:44:55+09:00

OOPの解説をprivateで書くべきかlimited privateで書くべきか悩みながら色々居試してたら、なんか困った現象にぶち当たってしまった。普段use使いまくりだから気がつかなかった。

withしたパッケージ内で宣言したレコードとか配列を=で比較しようと思うとコンパイルエラーが出る。withだけじゃなくて、インラインで宣言したパッケージでも発生するので、とりあえずサンプルコードを。

procedure Sample is
   package Test is
      -- 何でも良いから型宣言
      type Foo is array(Integer range 1 .. 0) of Integer;
   end Test;

   -- 同じ内容の型を宣言
   type Bar is array(Integer range 1 .. 10) of Integer;

   -- 比較するだけだから内容は何でもいい
   X : Test.Foo := (others => 1);
   Y : Test.Foo := (others => 1);

   N : Bar := (others => 1);
   M : Bar := (others => 1);

begin
   -- 当然いける
   if N = M then
      null;
   end if;

   -- これエラー
-- if X = Y then
--    null;
-- end if;

   -- use すれば使えるらしい
   declare
      use Test;
   begin
      if X = Y then
         null;
      end if;
   end;

end Sample;

エラーが出る部分のコメントを外してコンパイルすると、

operator for type "Foo" defined at sample.adb:4 is not directly visible
use clause would make operation legal

とか言われてコンパイルできない。言われたとおりにuseするとコンパイルできるんだけど、useが使えないときはどうするのよ!

Test.=

とか無理だし、どうしろと。思わずISO規格の本まで引っ張り出してきたけど、ここら辺のことなんか今一書いてないっぽい。派生型作っちゃえば比較演算子もインポートされるらしいけど、それもなんか違う気がするしなぁ。どうしたものか。

あるいは、明示的に演算子をオーバーロードしろってことなのかなぁ。でもそれだったらuseした時だけ可視になるのは納得いかないし。

この問題はAda95で導入されたuse typeで解決したらしい。

もの凄い勢いで読み飛ばしてた……。まさか真下に解決策があるとは思わなかったというか、ちゃんと表題付けといて欲しいなぁ。

Comments
2
Trackbacks
0
PermaLink
http://yudai.arielworks.com/memo/2006/07/23/040658
連絡先、リンク、転載や複製などについては『サイト案内』をご覧ください。Powered by HIMMEL

I ♥ Validator