HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2010
0204
玄冬whileについて9未解決


玄冬

リンク

2010/2/4(Thu) 02:39:03|NO.30382

hspを勉強中の身です。
基本的なことは一通りできるようになったので%tなどを用いたちょっと複雑なマクロ作りを覚えようと思い、まずは先人の作ったものを参考にさせてもらおうとhspdef.asを開き、参考にさせて頂きました。
そのおかげで%tなどの特殊展開マクロの機能は一通り理解することができたのですが、その過程で一つ疑問が生じたので質問をさせて頂きたいと思います。

それは、何故whileの実装が

#define global while(%1=1) %tcontinue %i0 %twhile *%i :%tbreak if (%1)=0 { goto *%i }
#define global wend %tcontinue *%o : %twhile goto *%o: %tbreak *%o

なのか?ということです。

まだまだ、hspを覚えたばかりの素人考えでは↓でいいのではないかと思えてしまいます。
#define test_while(%1=1) repeat -1 %c if %1 {
#define test_wend } else : break %c loop

こうすれば、_continue、_breakを定義しなくても標準命令のbreak、continueでループを制御できる上、ループ回数をcntで見ることができます。
多重ループにした時の兼ね合いかとも思い、簡単な多重ループを作って試してみましたが、不具合を見つけることはできませんでした。
しかし、実際には、この標準命令を用いた簡単な置き換えマクロではなく、特殊展開マクロを用いてwhileを実装しているということは、私の考えたtest_while、test_wendには何らかの欠陥が
存在するのだろうと思います。
私には気付けない、このtest_whileの欠陥をお教え頂く事で、今後自ら特殊展開マクロを作っていく際の、有用な視点・指針が得られればと思います。

なにとぞご回答よろしくお願い致します。



この記事に返信する


ANTARES

リンク

2010/2/4(Thu) 03:17:59|NO.30384

 repeat〜loopのネストの深さ制限に関する錯誤を避けたかったのでは?
再帰呼び出し以外では、まず問題にならないとは思いますが。



ANTARES

リンク

2010/2/4(Thu) 03:20:28|NO.30385

 あ、寧ろ再帰呼び出しでネスト制限が問題にならないようにということかも。



ANTARES

リンク

2010/2/4(Thu) 03:26:31|NO.30386

 今調べてみたら以下のようでした。
repeat〜loopのネスト制限=31
サブルーチンコールのネスト制限(#deffuncでテスト)=256



エイジ

リンク

2010/2/4(Thu) 12:54:21|NO.30402

玄冬さんの方法ではwhile〜wend間でcntの値が変化するので良くないです。
ほかにも、while〜wend間からgotoで外に出ることも出来ないです。



ANTARES

リンク

2010/2/5(Fri) 03:05:34|NO.30420

>玄冬さんの方法ではwhile〜wend間でcntの値が変化するので良くないです。
 cntはループレベルごとに別物なので、そのようなことはありません。

>ほかにも、while〜wend間からgotoで外に出ることも出来ないです。
 実際のwhile〜wendマクロもスタックを使っているので、
それはやっちゃまずいです。マニュアルに書かれているように
_breakを使ってください。



玄冬

リンク

2010/2/5(Fri) 10:03:51|NO.30422

>>ANTARESさま
あーなるほど
むしろ私は、"ループ構造"の深さがネストだと思っているので、foreachやrepeatがネストの階層に数えられるのに、whileを数えないほうがよっぽどややこしく感じてしまうのですが、そこは人それぞれな部分かもしれないですね。

標準ループ構造が31までしか行かないのはマニュアル見て知っていましたが、サブルーチンだと255回も行けるんですね…
ネスト気にせず使えるようにしているのは強みですね。
そして、思いがけずhspで再帰呼び出しができることを知ることができました。ありがとうございます(普段使わないので、そんな方法があったことすら失念していましたが…)


>>エイジさま
cntが変化するのは良くないことなのでしょうか?
ループ回数がシステム変数で自動的に入手できるのはhspの良いところだと思っているのですが…
ANTARESさまはループレベルごとの話をしていますが、仰っているのはたぶん↓の挙動が私の実装に置き換えると変わってしまうということですよね。

repeat 20 cls n = 0 while n < 20 mes n mes cnt if cnt = n : _break n++ wend wait 20 loop
これは↓のようにできるので、cntが使えたほうが良いと思いますが、何かwhile中のcntが動くと不具合があるループの例があればお教え下さい。

repeat 20 cls n = cnt test_while cnt < 20 mes n mes cnt if cnt = n : break test_wend wait 20 loop
ANTARESさまも仰っていますが、大抵のプログラム言語ではループ構造を終了しないでgotoで抜けるのは禁忌とされています。
何かの言語で、仮に実装上gotoしても不都合のないようにできていたとしても行わないほうが良いと思います。
(ANTARESさまが指摘するまでhspではできるのかと思ってしまいました。)



玄冬

リンク

2010/2/5(Fri) 10:04:26|NO.30423

こうやって見てみると、whileは、マニュアルにあるように手放しで推奨されるループ構造ではなく、他の言語を学んだ方が慣れた書き方で、再帰や深いネストを実現できるようにしているのであって、初心者が簡単なwhile的ループを行いたい時には
test_whileを使えという住み分けの意味でこういうマクロになっているのかなとも思いましたが、何かまだ指摘されていない欠陥がある可能性も考慮してもう少し未解決で様子を見たいと思います。



エイジ

リンク

2010/2/5(Fri) 18:18:32|NO.30424

>>ANTARESさん
>cntはループレベルごとに別物なので、そのようなことはありません。
そういう意味ではありません。玄冬さんは分かってくれた意味で書きました。
>実際のwhile〜wendマクロもスタックを使っているので、それはやっちゃまずいです
全然まずくないです。マクロのスタックと実行時の動作は全く別物です。

>>玄冬さん
>cntが変化するのは良くないことなのでしょうか?
いちいちcntを別の変数に他移入しなければならないのをめんどくさいと感じたことはありませんか?
この辺は好みの問題ですが。
>他の言語を学んだ方が慣れた書き方で、再帰や深いネストを実現できるようにしているのであって
そういうことです。
基本的にループ処理はrepeatだけで全部すませることが出来ます。
ですが多言語の書き方が好みの人や、repeatでは不便な部分を避けたい時のためwhileなどがあるのです。
不便な部分というのはネスト制限だったり、cntの問題だったりです。
玄冬さんの方法のようにwhileをrepeatを使って実装するのなら別にわざわざwhileを使わずともrepeatを使えば済みます。
>大抵のプログラム言語ではループ構造を終了しないでgotoで抜けるのは禁忌とされています。
まあそうですがネストの深いところから一気に外に出る使い方なんかもあります。



ANTARES

リンク

2010/2/6(Sat) 02:21:55|NO.30436

>>cntはループレベルごとに別物なので、そのようなことはありません。
>そういう意味ではありません。玄冬さんは分かってくれた意味で書きました。
 なるほど。
しかし、それは不便な場合と寧ろ便利な場合(条件にカウンタが含まれなくても
カウンタが使える)とがありますので、一概に欠点とは言えないでしょう。
私の感覚では、便利な場合の方が多い気がします。

>>実際のwhile〜wendマクロもスタックを使っているので、それはやっちゃまずいです
>全然まずくないです。マクロのスタックと実行時の動作は全く別物です。
 そうか、マクロ展開用のスタックで実行時スタックじゃないですね。



ONION software Copyright 1997-2023(c) All rights reserved.