トピック
りきすけ rikisuke

ユーザー定義関数と、GOSUBで飛ぶサブルーチンとの違いがわかりません。というか、ユーザー定義関数の作り方自体も自分の中で曖昧なので、誰かわかりやすく教えて下さいませんか?

4そうだね
プレイ済み
返信[1]
親投稿
あきと SideBurnsM
サブルーチンは長くなった処理をまとめて切り出すだけですが、関数には引数があることで呼び出し側から振る舞いを変えることができます。また、返り値があることで呼び出した結果を受けとることができます。 例えばAとBに格納されている数字がどちらが大きいか判定して大きい数字を得るという処理をGOSUBで書くには @whichbig IF A>B THEN RET=A ELSE RET=B RETURN と書くとRETという変数に結果が入ることになります。 しかしこれだと本当にAとBの比較しかできません。CとDの比較がしたくなったら別のサブルーチンを書くことになります。
1そうだね
プレイ済み
返信[2]
親投稿
あきと SideBurnsM
そこで関数で大きさを比較して大きい数字を書く処理を作ります。 DEF WHICHBIG( A, B ) IF A>B THEN RETURN A RETURN B END 呼び出す側では RET=WHICHBIG( A,B ) となります。 関数の良いところは R=WHICHBIG(C,D)と書いても動くところです。GOSUBではAとBの比較しかできなかったのが関数では引数で渡す事でCとDの比較もできるようになっています。 返り値もGOSUBの時は必ず「RET」に入れていましたが、関数では受けとる側で書き換えることができるのでC,Dの比較時Rにいれてます。
2そうだね
プレイ済み
返信[3]
親投稿
りきすけ rikisuke
あきとさん。 的確に丁寧に、且つとても違いが分かるように説明頂き、本当にありがとうございます。 ユーザー定義関数の方が汎用性も高いし、引数の受け渡しも判りやすくできますね。 これで関数の理解度がだいぶ上がってきたので、これからはちょっと関数を深く学んでいきたいと思います。 ありがとうございます。
0そうだね
プレイ済み
返信[4]
親投稿
ゆうすけ OREYUSUKE
私も専門的にはよくわからないですが、DEFの「ユーザー定義命令」としてだけ使ってるので、初歩的なことですと、「DEF」は定義したら、GOSUBルーチン中でも、いつでも使えます。 ラベルが減って管理しやすいので、基本的にそれらの命令は、やはりGOSUBルーチン内に入れて使います。という感じです。
0そうだね
プレイ済み
返信[5]
親投稿
おおみの Omi-no-mino-398
ラベルで飛ぶかどうか、ローカル変数の有無、くらいの違いです。プチコンのDEFは機能が強力なのでGOSUBの立場をほぼなくしています。 サンプル:n%の確率で1を返す関数 DEF PRB(n%) '[n%]は変数名 VAR R=0 IF RND(100)<n% THEN R=1 RETURN R END
0そうだね
プレイ済み
返信[6]
親投稿
けい kei0baisoku
丁寧な説明はあきとさんがして下さってるので違う視点から補足してみます。 存在意義はどちらも「処理をまとめて再利用するための書き方」で同じです。 なので機能や使われ方もよく似てます。 GOSUBの方が直感的で分かりやすいですが、DEFの方が高機能で便利です。 なんで同じようなものが2つあるのかと言いますと、BASICは(プチコン前作も)もともとGOSUBだけだったのが、スマイルブームさんの判断で「今風の機能も少し付け加えよう」ということで三号からDEFも追加されたそうです。 なのでおーみのみのさんの言う通り、両方理解してる人はだいたいDEFの方が主流になってるぽいです。
1そうだね
プレイ済み
返信[7]
親投稿
りきすけ rikisuke
ゆうすけさん。ありがとうございます。今作ってるゲームのコードを見直して、サブルーチンを関数化してみようと思います。果たしてうまく作れるだろうか。頑張りますね!ベルトスクロールのやつもこれでもう少しバグが消えるかもしれません。 おーみのみのさん。 今まで、ローカル変数の事をほぼ無視してサブルーチンに飛ばしてたので、アリエナイ挙動が起きてたのではないだろうかと、気づきました。エネミー1のy座標変換が、エネミー2や3に同期する時があったりしたので。 ありがとうございます。
1そうだね
プレイ済み
返信[8]
親投稿
りきすけ rikisuke
けいさん。 なるほど。そういう流れでDEFが追加されたんですね!自分は古いままの人間だからベーシック覚えてから20数年間何もやってこなかったので、本当に時代に取り残されたなぁ、とつくづく感じました。 頑張って流行りに乗っかりたいと思います(笑)
0そうだね
プレイ済み
返信[9]
親投稿
おおみの Omi-no-mino-398
>ローカル変数の事をほぼ無視してサブルーチンに飛ばしてたので 昔のBASICにはローカル変数の概念がないので厳格に使い分けないといけなかったですねー。 私もその時代にやっていたので、むしろ同名でも内容が違うことになるローカル変数に戸惑いました。 DEFはC言語の関数にとてもよく似ているので、どちらかがわかればもう片方も理解できると思いますよ。
0そうだね
プレイ済み
返信[10]
親投稿
れい rei-nntnd
流れに逆らうようだけれども。 俺はGOSUBもたくさん使うし、みんなもGOSUBたくさん使ったらいいと思ってる。 DEFを使わないほうがいい用途はたくさんある。 歴史や思想を説明するのは長くて大変なんだけど。 GOSUBは「大きな処理から同じ処理を纏める」という発想から作られたもの。 DEF(関数)は「小さな処理をたくさん集めて徐々に大きな処理を作る」という発想でできてる。 トップダウンとボトムアップの違いというか。 だから構造的には、DEFは小さな部品を作るときは美味しくて、大きい処理はGOSUBがおいしい。 なんだけど、処理速度的にはGOSUBのほうがDEFより早くて、頻繁に呼ばれるものをDEFで作るとまずい。 参照とかないので配列や文字列を扱うときDEFではわかりづらい時もある。 なので、あんまDEF教を信仰するのはオススメしない。 その都度適切なものを考えたほうがいい。
2そうだね
プレイ済み
返信[11]
親投稿
MIKI ifconfig
いやー gosub て basic にしかないじゃないの。 これから先もずっとプチコンの中だけで暮らすつもりならいいけど。 gosub に設計思想なんてあったの?? 単に実装が楽だからってだけかと思ってました。 basic 自体 fortran の劣化コピーみたいなシロモノだし。
0そうだね
プレイ済み
返信[12]
親投稿
けい kei0baisoku
れいさんVSみきさんのGOSUB-DEF戦争を尻目に、 イマドキなプログラムも頑張ってください!(`・ω・´)/ >りきすけさん
1そうだね
プレイ済み
返信[13]
親投稿
れい rei-nntnd
そりゃ将来の話するならCやC++、Javaを勉強するのが一番いいって話になるに決まってる。なら最初からそれやりゃいいだろ。プチコンでなく。 むしろ、こういったメジャー言語で「関数」しかないから プチコンでGOSUB使えるのはいい経験だと思うね。 DEF=スコープのある関数はALGOL由来で、アルゴリズム研究から生まれた。抽象化を重要視する思想。サブルーチンを「関数」と解釈したのもこれで、だから「再帰呼び出し」もALGOLから。 GOSUBはFORTRAN由来で「必要があったから」作られた。BASICは引数なしだけど。より現実的というか、泥臭いというか。そういう思想。 引数の存在やその個数、変数や関数のスコープの有無やその範囲、そういった「サブルーチン呼び出し」の仕様は言語によって違う。それぞれ特徴があり、得手不得手がある。 柔軟に使うのが一番重要。
0そうだね
プレイ済み
返信[14]
親投稿
れい rei-nntnd
柔軟っていうだけだと中身ないので、俺の指針的なの書いとく。 副作用の有無 引数の個数 UIの有無 規模 この4つが判断するポイント。 副作用がないものや、ただ命令をラップしただけなら圧倒的にDEF。 副作用があっても限定的で、引数が少ないならDEF。 副作用があって、規模が大きくて、引数が多くて、UIがあるならGOSUB。 あてはまらない場合は分割の仕方がおかしい可能性高い。 参考に。
1そうだね
プレイ済み
返信[15]
親投稿
[注意]以下は個人的な感想です。 1)GOSUBは、汎用性が高い。しかし、その特徴を生かすためには、引数(パラメータ)の渡し方や、ローカル変数の管理など全て自前でやらなければならない。GOTOは、さらに汎用的です。つまり、自由と言うことです。 2)DEFは、引数やローカル変数の管理をプチコンがやってくれるため、そこを楽して本来やりたいことを考える時間に割り当てることが出来ます。不自由だけど、仕様に不満が無ければ、とっても便利です。 3)GOSUBは、CPUによって違いますがアセンプラのBSR(ブランチサブルーチン)命令ややJL(ジャンプアンドリンク)命令相当です。今やニッチな分野かもしれませんが、GOSUBが使える場面もあるかもしれません。 4)DEFの仕様に不満が無ければDEFを使った方が楽できます。DEFで問題があるときはGOSUB/GOTOを使えば良いと思います。
0そうだね
プレイ済み
返信[16]
親投稿
りきすけ rikisuke
れいさん。 GOSUBの方が処理速度が速いのですか。大まかなルーチンであればGOSUBで作って、その間のちょっとした細やかな演算、特殊な作業をDEFで処理するといいのでしょうかね。個人的にはベーシック言語を楽しむつもりなので、そんな感じに思えました。
0そうだね
プレイ済み
返信[17]
親投稿
りきすけ rikisuke
みきさん。 GOSUBはベーシック固有っていうほどの命令なんですか。自分は他の言語を覚える事もスマホでアプリを作ったりする事も恐らくないと思うので、プチコンユーザーとしてGOSUBもDEFも楽しんで使い分けて行きたいです。
1そうだね
プレイ済み
返信[18]
親投稿
りきすけ rikisuke
けいさん。 れいさんとみきさんのレベルの高さ、凄いです。素人の自分にはとても及ばないステージでの論議なので、とても尊敬できますね。自分なりに消化していって自分のゲーム作り上げて行きたいです。
1そうだね
プレイ済み
返信[19]
親投稿
りきすけ rikisuke
れいさん。副作用の事がわからなかったので調べてみましたが、ざっくり言うと、様々なケースにおいて処理されてしまう事が副作用、という事でしょうか。それとUIはユーザーインターフェイスのUIでしょうか?自分なりに判断してみましたがまだまだ未熟なようで、努力して頑張ってみます。ありがとうございます。
0そうだね
プレイ済み
返信[20]
親投稿
りきすけ rikisuke
コータさん。コータさんのおっしゃるGOSUBの汎用性の高さは、作成時のものではなくて、使用時のものですよね。自分なりに、DEFは限定的な処理をする、という認識なのできっとそうだと思いました。GOSUBの根本的なモノは今もバリバリ進化して使われてるんですね。やっぱり、使い分けを考えながら色々試してみます。
0そうだね
プレイ済み
返信[21]
親投稿
おおみの Omi-no-mino-398
GOSUBにできてDEFにはできないこと、ありました。 DEFはその中から外へ飛ぶことはできないけど、GOSUBだとサブルーチン内からGOTOで別のサブルーチンへ片道旅行できちゃいますね。それがいいのか悪いのかはさておき。 れいさんみきさんの書き込みも興味深いですが、なんにせよ自分がやりたいことができれば何でもいいのではないでしょうか。試行錯誤するのも楽しみのひとつだと私は思います。
1そうだね
プレイ済み
返信[22]
親投稿
れい rei-nntnd
副作用っていうのは… 関数を呼ぶ前後で、何かが変わること。 例えば、POWという関数がある。これは冪乗を求める関数だけど、呼んでも戻り値を入れる変数以外なにも変わらない。 これは副作用が無いという。数学の関数に近い。こういう命令だけじゃ(普通は)プログラムを作れない。 対してSPCLRという命令がある。これはスプライトの使用を止める命令で、呼んだ後は該当スプライトは無くなる。 関数というよりプチコンに対する「命令」で、こういうのは「作用」がある。 サブルーチンを自分で作るときは上の二つを組み合わせる。全部副作用無しなら簡単でわかりやすくてDEFに最適。とても再利用しやすい。 ところが一部に「作用」がある命令が含まれるととたんに微妙になる。例えば弾が敵に当たったら点数を増やして敵を消すという処理は何回も実行するから分離して関数にしたとする。続く。
0そうだね
プレイ済み
返信[23]
親投稿
れい rei-nntnd
これは点数もスプライトもいじるからたくさんプチコンを変化させる。副作用がある。(狙った通りに動いていても副作用という) これは関数だけでは作りづらい。引数が多くなる。かといってグローバル変数使っちゃうと関数の利点はかなり削れる。 さらに分割したら少しよくなる。 敵と弾が衝突したか判定する処理、 点数を増やす処理、 敵を消す処理、 にわけて、それらを呼ぶ処理をつくる。 そうすると、それぞれのサブルーチンは関数で綺麗にかけるようになるけど、 それらを呼ぶルーチンの引数はやっぱり爆発しちゃうし、そこは再利用しづらい。 これはGOSUB使うのがよいパターンになる。
0そうだね
プレイ済み
返信[24]
親投稿
れい rei-nntnd
副作用のある関数の問題は、関数型プログラミングやラムダ式関連でちょっとまえから話題に上がるようになったけど、実はダイクストラの昔からある話。 ALGOL型のサブルーチン=関数だけではこれがうまく解決できなくて、泥臭いグローバル変数つかうのが問題になってた。 構造体、さらにオブジェクト指向を使うと状態の情報やコンテキストといった物を引数に渡せるので副作用を無くすのが簡単になったんだけど、 それはまた別のお話。
0そうだね
プレイ済み
返信[25]
親投稿
りきすけ rikisuke
おーみのみのさん。 そうでしたか。飛べる飛べないあるんですか。RETURNさせないと処理的には落ち着かないですね、やはり。
0そうだね
プレイ済み
返信[26]
親投稿
りきすけ rikisuke
れいさん。 副作用のあるサブルーチンしか作れない自分は、やっぱりDEFの作り方をまだまだ理解してないんでしょう。というか、使い方も分からないんだろうと思います。 あぁ、ご指導いただいた説明も半分理解できるかできないか…頑張って調べながら理解しま~す!!ありがとうございます。
0そうだね
プレイ済み
返信[27]
親投稿
返事が遅くなってすみません。 DEFは、ローカル変数と戻り位置、GOSUBは戻り位置をプチコンが管理してくれるため、他の処理で破壊する事無く安全に使えます。しかし、まれにローカル変数や戻り位置を操作出来ればいいのにと思う事があります。自前で管理すれば自由に出来ますが、その分手間がかかったり、バグを出す確率も増える事を、私は汎用性が高いと呼んでいます。(一般的な使い方とは違いかもしれません。)
0そうだね
プレイ済み
返信[28]
親投稿
りきすけ rikisuke
コータさん。 なるほど、そういう意味でGOTOの自由度の高さを評価してらっしゃったのですね。GOSUBは戻り位置指定しなくても戻ってくれるから便利、としか考えた事なかったのでそこまでのレベルでの使い方を知らない自分にとって、ある意味目からウロコです。 確かにGOSUBルーチンの中での戻り位置指定を無視して飛ばす事も出来ますがスタックフローとか何とかっていうエラーがファミリーベーシック(笑)であったような気がします。
0そうだね
プレイ済み
返信[29]
親投稿
りきすけ rikisuke
ここに書き込んでくださった皆様方、本当に有り難うございました。これでこの質問を終了します。
0そうだね
プレイ済み