title: Ruby から Delphi へ値を変換する
author: YOSHIDA Kazuhiro
mailto: moriq@moriq.com

1. Ruby から Delphi へ値を変換する

1.1. 順序型の範囲チェック

Fixnumを順序型へ変換するときは範囲チェックが必要です。
順序型の範囲を整数で得るには %c:Ord(Low(Type)), Ord(High(Type))% が使えますが、これは見た目があまりに冗長です。例外処理にしてしまいましょう。

* 冗長
  --code
var
...
  ret: Tvalue;
  n: Integer;
begin
...
  if ret <> Qnil then
  begin
    n := INT2FIX(ret);
    if (n < Ord(Low(TUpdateAction))) or (Ord(High(TUpdateAction)) < n) then
      ap_raise(ap_eIndexError, sOut_of_range);
    UpdateAction := TUpdateAction(n);
  end;
end;
--

* 例外処理ですっきり
  --code
var
...
  ret: Tvalue;
begin
...
  if ret <> Qnil then
  try
    UpdateAction := TUpdateAction(dl_Integer(ret));
  except
    ap_raise(ap_eIndexError, sOut_of_range);
  end;
end;
--

ap_raise に与える Ruby 例外の種類について。Ruby の範囲例外は ap_eIndexError ですが、インデックスが引数として与えられている場合は ap_eArgError を使ったほうが良いでしょう（Ruby本体がそうなっているから）。

1.1. setter の返り値

代入を連鎖できるように、プロパティを設定するメソッド（名前の末尾に %c:=% が付くメソッド）の返り値は、引数（第一引数。例では %c:v% ）そのものにすべきです。

--code
function Editor_set_selection_mode(This, v: Tvalue): Tvalue; cdecl;
var
  real: TEditor;
begin
  real := ap_data_get_struct(This);
  real.SelectionMode := TEditorSelectionMode(dl_Integer(v));
  result := v;
end;
...
  DefineAttrSet(cEditor, 'selection_mode', Editor_set_selection_mode);
--

