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;
おおー、なんかちょっとカリー化とは違う気がするけど、おおむねね期待通りだ! なんかもう必死すぎて涙が出てきますね。え、任意の関数で出来るようにしろって?
もっと簡単にかける気がするので、誰かトライお願いします。
useしないと外部パッケージの比較演算子が見えない件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で解決したらしい。
もの凄い勢いで読み飛ばしてた……。まさか真下に解決策があるとは思わなかったというか、ちゃんと表題付けといて欲しいなぁ。