前回と前々回は、関数の使い方をカンタンに見てきました。
RPG では、C でのちょっと初心者には難しいポインタの書き方等々に煩わされずに「関数」を書ける、というようなお話をしました。
関数を自由に使いこなすことができるようになるためには、本当は関数の定義の仕方と、どう使うと効果的かの二点がわかればいいわけです。
処理してもらいたい結果が増えただけで、ポインタの知識やその書き方の知識、さらに引数が"値渡し"か"参照渡し"かなどということまで知らないといけない、というのはやはり初学者にとっては正直厳しい。
そういう枝葉末節にとらわれず、まずは「関数とはどういうものか」を大づかみに理解することができる、ということができるとプログラミングを学ぶことはもっとラクになります。
細かいことや難しいことは、おいおい必要になったときにおぼえていけばいいんです。
実際、RPG にもポインタはありますし、"値渡し"だってできるようになっています。でもそれは、それが必要なコーディングに直面してからおぼえても間に合います。
「関数」をどういうふうに使うか、をまずは学んで慣れていくことが、逆にどんなプログラミング言語にも通じるスキルを得ることになります。
RPG はそんな出発点として、とてもいい言語だと言えるでしょう。
プログラミングの基本だけでできているような言語ですので、
もし他言語のスキルがきちんとあれば習得が難しいものではありませんし、
また、これから学ぶとしたら最もシンプルに基本を学べる言語でもあります。
では、今回も続けて関数の使い方を見ていきたいと思います。
今までは、同じプログラムの中に関数を定義して使うやり方をご紹介してきましたが、実はそれだけが関数の使い方ではありません。
別のプログラムに存在していてもいいんです。
より共有がしやすくなりますね。
さらに、RPG で書かれていなくてもいいんです。
RPG の中から C の標準ライブラリ関数を使用する、なんてこともできてしまうんですね!!
「C でこんな関数があるんだけど、RPG にはないの?!」
「どうぞ、そのままお使いください!!」
前回の RPG に C のライブラリ関数を使った処理を書き加えてみましょう。
前回の RPG で得た合計と平均の値に対して、
C のライブラリ関数である abs() 関数と sqrt() 関数を利用して、絶対値と平方根を得るといった処理を加えてみました。
(両方とも実は ILE RPG で同様の関数があるのでわざわざこんなことをする必要はないんですけどね?!
"例のための例"にはなっていますが、わかりやすさを考えてこうしてみました)
H DFTACTGRP(*NO)
H BNDDIR('QC2LE')
*
D sum_ave PR 10i 0
D num1 10i 0
D num2 10i 0
D sum 10i 0
D ave 10i 0
*
D abs PR 10i 0 extproc('abs')
D var 10i 0 value
*
D sqrt PR 8f extproc('sqrt')
D var 8f value
*
D x S 10i 0 inz(-3)
D y S 10i 0 inz(-5)
D goukei S 10i 0 inz(0)
D heikin S 10i 0 inz(0)
D a_goukei S 10u 0 inz(0)
D a_heikin S 10u 0 inz(0)
D f_heikin S 8f inz(0)
*
/free
sum_ave(x: y: goukei: heikin) ;
a_goukei = abs(goukei) ;
a_heikin = abs(heikin) ;
f_heikin = sqrt(%float(a_heikin)) ;
dsply ('合計は' + %char(goukei) + 'です。') ;
dsply ('平均は' + %char(heikin) + 'です。') ;
dsply ('合計の絶対値は' + %char(a_goukei) + 'です。') ;
dsply ('平均の絶対値は' + %char(a_heikin) + 'です。') ;
dsply ('平均のルートは' + %char(%dec(f_heikin:5:2)) + 'です。') ;
return ;
/end-free
*
P sum_ave B
D sum_ave PI 10i 0
D num1 10i 0
D num2 10i 0
D sum 10i 0
D ave 10i 0
*
/free
sum = num1 + num2 ;
ave = (num1 + num2)/2 ;
return 0 ;
/end-free
P Sum_Ave E
このプログラムの実行結果はこちら ↓ です。

ちゃんと正しい結果が返ってきているのがわかりますね。
今までと違うところだけを見ていきましょう。
最初に ↓ が追加されていますね。
これがいわば #include ですね。後で定義して使う関数を C のランタイムライブラリに探しに行ってほしい、という指示です。
H BNDDIR('QC2LE')
以前の関数の定義と異なるのは extproc キーワードですね。
extproc('abs') とあるので、"abs という名前の関数が外部に存在してそれを使う"という指定になっています。
プログラムの最初にある H 仕様書にある BNDDIR('QC2LE') とあわせて、"C の標準ライブラリにある同名の関数を使用する"という意味になります。
D abs PR 10i 0 extproc('abs')
D var 10i 0 value
abs というのは C の標準ライブラリ関数で、C で定義、つまり C でプロトタイプ宣言したとすると ↓ のようになります。
int abs(int n);
戻り値が integer で、引数として integer をひとつ取る、というのがこの関数の利用形態です。
integer というのは具体的に言えば 10桁の整数になるので、RPG では 10i 0 と書かれていますね。
10桁のデータ型 i 小数点以下桁数は 0 ということになります。
sqrt も C の標準ライブラリ関数です。
double sqrt(double x);
こちらは double の引数をひとつ取って、double の戻り値を返すようになっています。
double というのは、より具体的に言うと 8桁の浮動小数点型といわれる数を表しています。
RPG では 8桁のデータ型 f ということになります。(小数点以下桁数を表す 0 は必要ありません。
ちなみに、浮動小数点という型は必然的に誤差があります。RPG 育ちの人には信じられないことでしょうが、バグではありません。注意して使ってくださいね)
D sqrt PR 8f extproc('sqrt')
D var 8f value
戻り値は浮動小数点型で受け取る必要がありますので、ひとつ浮動小数点型の変数を用意しています。
D f_heikin S 8f inz(0)
引数も浮動小数点型で受け取る必要があります。RPG の組み込み関数で変換させることができます。
f_heikin = sqrt(%float(a_heikin)) ;
表示するときに、より見やすくするために 10進表現に変換した上で文字に変換しています。
dsply ('平均のルートは' + %char(%dec(f_heikin:5:2)) + 'です。') ;
というところが変化点です。
特別、なにかトリッキーなところはないでしょう。
データの交換などで「?」なところはあるかもしれませんが、実際「double って何?」というような人が C の標準関数を使いたいと言い出すわけもないでしょうから、それほど問題にはならないでしょう。
今回は、C で書いてあろうが RPG はそれを使うことができる、ということを見ていただければ目的達成です。
極端なことを言えば、C の関数を駆使して「処理はほとんど C の関数なんだけど RPG プログラム」なんてものを作ることもできるわけですね!
いまアプリケーションを作る上で大事なのは、いかに速く確実に本番で仕事をしてもらって価値を生んでもらうか、だと思います。
共有することで書かないで済ませられるところを増やせれば、そのぶん早くプログラムはできるわけです。
共有されていればそのぶんテストされて、その部分の信頼性は上がっていきます。共有されているところが多くなれば、そのぶん信頼性が上がる、ということになります。
もちろんそうできるように設計も運用もしなければなりませんが、いわゆる「ソフトウェア工学」で蓄積してきた知見のひとつがこの「モジュール化による共有」なんですね。
オブジェクト指向ももちろんその考え方の延長線上にあるわけです。
ぜひ、「関数」の考え方を理解して、より速く、よりバグの少ないプログラムを作って、よりよいアプリケーションでよりよい未来を作ってください!
ちなみに、C の関数だけでなく、Java のメソッドも使用することができます。
ただし、それが必要になるくらいの処理はやはりかなりの"上級編"と言っていいので、さすがにこのブログでは紹介しきれません。
インフォメーション・センターにはもちろん必要なことは全部載っていますので、もし"上級"になった方はぜひネットのどこかででも公開してくださいね!!
この記事にはトラックバック・コメントがありません。
コメントは投稿者の責任においてなされるものであり,サイト管理者は責任を負いません。