てきとう

てきとう

最近15ヶ月のまとめ

一度はてなblogで書きましたが戻ってきました。*1

余裕のなさと艦これと現実逃避で全部です。あと体調が若干マシ。

最後の記事の下書き*2から半年くらい?最後に書こうと思ってから3ヶ月くらい?

*1:ドラッグ時の「引用スター」の誤爆にイライラしたため

*2:重箱の隅を突くにしても悪趣味すぎたのでやめたはず

'Firstからやりなおし:現実逃避編

色々疲れたので現実逃避。
関数プログラミングの楽しみ」という本がありまして。*1

関数プログラミングの楽しみ

関数プログラミングの楽しみ


中身はHaskellなんですが、3章の「おりがみプログラミング」の(un)foldは再帰的な型があれば他の言語でも(やる意味はともかく)実装できます。
ところでAdaには配列というものがあります。*2
という訳で、どういう訳だか配列で(un)foldっぽいものを作ってみようと思い立ちました。
fold/unfoldそのものと、その便利な使い方については上の本を読んでください。

やる意味

なし

使い勝手

悪い

効率

悪い

特徴

  • 無駄にgeneric使う
  • 無駄にexpression functions使ってみる

ソースとか

origami.ads

仕様。無駄にgeneric。

pragma Ada_12;
generic
   type Index_Type is (<>);
   type Element_Type is private;
   type Array_Type is array (Index_Type range <>) of Element_Type;
package Origami is
   
   generic
      type Result_Type is private;
   function Fold_R (F : access function (E : Element_Type; SoFar : Result_Type) return Result_Type;
                    I : Result_Type;
                    S : Array_Type)
                   return Result_Type;
   
   generic
      type Input_Type is private;
      with function "&"(Left, Right : Array_Type) return Array_Type is <>;
   function Unfold_R (End_Of_Input : access function (I : Input_Type) return Boolean;
                      Element      : access function (I : Input_Type) return Element_Type;
                      Renew_Input  : access function (I : Input_Type) return Input_Type;
                      Input        : Input_Type)
                     return Array_Type;
   
end Origami;
origami.adb

A'Length=0な配列Aの簡単な書き方が分からなくて右往左往。

pragma Ada_12;
package body Origami is
   
   function Unfold_R (End_Of_Input : access function (I : Input_Type) return Boolean;
                      Element      : access function (I : Input_Type) return Element_Type;
                      Renew_Input  : access function (I : Input_Type) return Input_Type;
                      Input        : Input_Type)
                     return Array_Type is
      (if End_Of_Input(Input) then (Index_Type'Succ(Index_Type'First)..Index_Type'First => <>)
      else Array_Type'(Index_Type'First=>Element(Input))
        & Unfold_R(End_Of_Input, Element, Renew_Input, Renew_Input(Input)));
      
      
   function Fold_R(F : access function (E : Element_Type; SoFar : Result_Type) return Result_Type;
		   I : Result_Type;
                   S : Array_Type) return Result_Type is
      (if S'Length=0 then I
      else F(S(S'First), Fold_R(F, I, S(Index_Type'Succ(S'First) .. S'Last))));
      
end Origami;
テストしてみた
pragma Ada_12;
with Ada.Text_Io;
with Origami;
procedure Origami_Test is
   type Nat_Arr is array(Positive range <>) of Natural;
   package O is new Origami (Index_Type => Positive,
                             Element_Type => Natural,
                             Array_Type => Nat_Arr);
   
   function Eq_0 (N : Natural) return Boolean is (N = 0);
   function Mod_2 (N : Natural) return Natural is (N mod 2);
   function Div_2 (N : Natural) return Natural is (N / 2);
   
   function G is new O.Unfold_R(Input_Type => Natural);
   
   A : Nat_Arr := G(Eq_0'Access, Mod_2'Access, Div_2'Access,
                    Natural'Value(Ada.Text_Io.Get_Line));
   function F is new O.Fold_R(Result_Type => Natural);
   function Mul (E : Natural; SoFar : Natural) return Natural is (SoFar*2+E);
       
begin
   for E of reverse A loop
      Ada.Text_Io.Put(E'Img);
   end loop;
   Ada.Text_Io.New_Line;
   Ada.Text_Io.Put_Line(Natural'Image(F(Mul'Access,0,A)));
end Origami_Test;
なんとなく動いてる気がする
123456
 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0
 123456

しかし実際無駄な。
あ、あとそろそろHaskellもちゃんとやりたい。

*1:多分定価分以上の価値はある内容のようなのに、私は500円分も分かってなくて凄く悔しい一冊です。

*2:お察しの通り、配列は配列なので再起的ではありません。

1からやり直し:hello, world編

基本

with Ada.Text_Io;
procedure Hello is
begin
   Ada.Text_Io.Put_Line("hello, world");
end Hello;

応用:use

with Ada.Text_Io;
use Ada.Text_Io;
procedure Hello is
begin
   Put_Line("hello, world");
end Hello;

応用:renames

with Ada.Text_Io;
procedure Hello is
   package TIO renames Ada.Text_Io;
begin
   TIO.Put_Line("hello, world");
end Hello;

宣言時にrenamesを使うと別名として宣言できます。
パッケージに短く適当な別名をつけることで、書く際の負担を減らしつつ可読性を上げることができます。

【テスト】Mountain LionでGCCを--enable-languages=adaでビルドしてみた記憶【コピペ】

*1

お久しぶりですが別に何もありません。いつも通りのダメ人間です。
適当にやってもできなかったけど適当に調べたらできたので記録というか記憶をメモ。
記憶なので細かいところ違うかと。

用意するもの

  • 動くGNAT。今回はgnuadaの4.6.0を使用。
  • gccのソース。今回は4.7.1。
  • gccのビルドに必要らしいGMPとかMPFRとかMPCとか。細かくは忘れたのでドキュメント参照してください。
    • MacportsだのFinkだのHomebrewだのをお勧めします。

手順

ここここを参考にやりましたので、そちらを見ることをお勧めします。
まとめると、要点はconfigureに以下をくっつけること。

CC='gcc -D_FORTIFY_SOURCE=0'

というわけでconfigureだけ気をつければいいので、gnuadaのGNATにパス通して

$ ./configure CC='gcc -D_FORTIFY_SOURCE=0' \
--enable-languages=c,c++,ada \
--prefix=$SOMEWHERE \
--build=x86_64-apple-darwin12
(略)
$ make
(略)
$ make install
(略)

こんな感じで動いてそうなGNATができました。


ちなみにCC=...を忘れるとldが「x86_64でこのシンボル知らねーよ!」とだかよく分からない暴言を吐いてconfigureに失敗します。
そのうち直ることを期待しときましょう。

*1:先程はてダに書いたもののコピペです。

Mountain LionでGCCを--enable-languages=adaでビルドしてみた記憶

お久しぶりですが別に何もありません。いつも通りのダメ人間です。
適当にやってもできなかったけど適当に調べたらできたので記録というか記憶をメモ。
記憶なので細かいところ違うかと。

続きを読む

ダイナミックディスパッチを捨てる方法(おまけ)

Adaだとどうするん?と思って適当にそれっぽいコードを書いたところ、普通にキャストすれば良さそうな感じ。*1

with Ada.Text_Io;
procedure Dsp_Test is

   package Bs is
      type B is tagged null record;
      procedure Method(Obj: in out B);
   end Bs;
   package body Bs is
      procedure Method(Obj: in out B) is
      begin
         Ada.Text_Io.Put_Line("B#method");
      end Method;
   end Bs;

   package Ds is
      type D is new Bs.B with null record;
      procedure Method(Obj: in out D);
   end Ds;
   package body Ds is
      procedure Method(Obj: in out D) is
      begin
         Ada.Text_Io.Put_Line("D#method");
      end Method;
   end Ds;

   B:Bs.B'Class:=Ds.D'(Bs.B with null record);

begin
   B.Method;       --> D#method
   Bs.B(B).Method; --> B#method
end Dsp_Test;

ドット記法使うと凄くOOPLっぽく見えますね…
ちなみに95方式で

   Method(B);
   Method(Bs.B(B));

と書くと、Methodが見えないのでコンパイラに怒られますが、"use Bs, Ds;"しておけばドット記法を使った時と同様に解決してくれるようです。(この例では。)

*1:面倒くさくてARM確認してませんので規格的に正しいかは不明。

ダイナミックディスパッチを捨てる方法

Java弄っててふと疑問に思ったのでググった結果をメモ。
Java でメソッドを静的にディスパッチする - odz buffer
Java でインスタンスメソッドを静的にコールする方法はない? 2 - Smalltalkのtは小文字です
とりあえず普通に使ってる分には無理、という理解で良いのかな。
private限定じゃあんまり意味ないし…