non-nullマクロ
先ほどの例をnon-nullマクロを使って書き直してみます。
{curl 7.0 applet} {curl-file-attributes character-encoding = "shift-jis"} || 文字数を返すプロシージャ {define-proc public {length str:String}:int {return str.size} } strの文字数: {value let str:#String = "abc" {length {non-null str}} || non-nullマクロ }
non-nullマクロは、#付の変数を#無しの変数として処理します。型名を書かなくて済むなど、コードの変更に対しても柔軟に対応できます。
if-non-nullマクロ
次は、null値を許す変数でnull値の判定をするif文です。
null値を許す変数やフィールドに対して、null値の場合とそうでない場合で処理を分けて行うことはよくあります。先ほどの文字数をカウントするプロシージャを使って、null値であれば0を、null値でなければ文字数を設定してみましょう。コードは以下のようになります。
{curl 7.0 applet} {curl-file-attributes character-encoding = "shift-jis"} || 文字数を返すプロシージャ {define-proc public {length str:String}:int {return str.size} } strの文字数: {value let str:#String = "abc" {if str != null then {length {non-null str}} else 0 } }
このようなケースでは、if-non-nullマクロが便利です。if-non-nullマクロで書き直してみます。
{curl 7.0 applet} {curl-file-attributes character-encoding = "shift-jis"} || 文字数を返すプロシージャ {define-proc public {length str:String}:int {return str.size} } strの文字数: {value let str1:#String = "abc" {if-non-null str then {length str} || non-nullが不要 else 0 } }
if-non-null thenの次の{length str}のところに注目してください。null値を許す変数strを直接呼び出しているように見えます。if-non-nullマクロは、変数strをnull値を許さないString型として定義します。ifコードブロック内にstrというローカル変数(null値を許さないString型)を定義して、利用していると考えられます。
このようなコードが書けるのは、strがローカル変数の場合のみです。それ以外の場合は、別途if-non-nullのコードブロック内で利用する変数を指定します。変数を指定することで、フィールドやプロシージャの戻り値を使うことができます。
{curl 7.0 applet} {curl-file-attributes character-encoding = "shift-jis"} || 文字数を返すプロシージャ {define-proc public {length str:String}:int {return str.size} } || 文字をそのまま返すプロシージャ {define-proc public {mirror str:#String}:#String {return str} } strの文字数: {value let str:#String = "abc" {if-non-null str1 = {mirror str} then {length str1} else 0 } }
if-non-nullで導入された変数str1は、型の定義を行っていませんが、mirrorプロシージャの戻り値#Stringのnull値を許さない型であるStringが自動的に定義されます。このように、if-non-nullマクロはとても便利です。