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


HSPTV!掲示板


未解決 解決 停止 削除要請

2010
0128
木村dup命令はモジュール変数の完全クローンを製造できるのでしょうか5解決


木村

リンク

2010/1/28(Thu) 23:08:45|NO.30214


//例(1) #module m1 F1,F2 #modinit array a1 F1=a1.0 : F2=a1.1 return #modfunc mm1 mes "F1="+F1+" : F2="+F2 return #global a=3,4 newmod z1,m1,a : mm1 z1 a=5,12 : mm1 z1 stop
 (1)を流してみれば分かると思いますが、z1の要素として代入したaが(3,4)から(5,12)に
変更されても、z1は相変わらず同じ値です。これはモジュール変数だけではなく普通の変数
計算(2)でも同様です。

//例(2) a=3,4 b=a.0+a.1 : mes b a=5,12 : mes b stop

 ところが、以下のソースでは少々様相が違ってきます。

//例(3) #module m1 F1,F2 #modinit int i1,int i2 F1=i1 : F2=i2 return #modfunc mm1 mes "F1="+F1+" : F2="+F2 return #modfunc m1renew int i1,int i2 F1=i1 : F2=i2 return #global #module m2 F1 #modinit array a1 F1=a1 return #modfunc mm2 mm1 F1 return #global newmod z1,m1,3,4 : newmod z2,m2,z1 : mm2 z2 m1renew z1,5,12 : mm2 z2 stop
 (3)ではz1はz2の要素です。[newmod z2,m2,z1]と入力した段階で、z2はその時点での
z1の情報を取り込んでいるはずで、この後z1にいくら変更が加えられてもz2には一切影響を
与えないはずです。
 が、[m1renew z1,5,12]とz1の情報を変更した後でz2の情報を呼び出してみると、z2は
z1変更の影響を受けている事が分かります。
 同じような事は#defineマクロでも起こります。

//例(4) #define z "X="+x+" : Y="+y x=3 : y=4 : mes z x=5 : y=12 : mes z stop
 (4)では#defineが定義された状態では(x,y)=(0,0)であるので"X=0 : Y=0"が標準的な
文字列ならば返るはずです。ところが、zをマクロとしたせいなのかzが常にxとyの影響を
受けています。

 これらのソースから分かるように、一部の定義方法では『変数の値』ではなく、『変数
の名前自身』を取得できるようになっています。
 (3)のモジュール変数の要素にモジュール変数を定義する場合、(4)#define命令を
使う場合以外にも、#const命令による定義、dup命令によるクローン複製(魔)でも同じ現象が
起きるようです。

 長々とした前置きでしたが本題に入ります。ずはり、ある変数Xを、任意のモジュール変数
Mのクローンにする事はできるかという質問です。
 普通に[X=M]と入力してはXが変更されても、それに連動してMが変更されません。dup
命令を利用つまり[dup X,M]と入力すればクローンにはなってくれるのですが、不安定で
よく分かりません。
(一応、[dup X,M]定義後の最初の一回目のXの数値要素の変更はMに反映されるという
事は確認したのですが、文字列要素(str)やモジュール要素(struct)の変更が反映されるのか
よく分かりません。当のHSPDLにさえ『クローン元の型が変更されたり、配列の拡張、または
文字列バッファの拡張が行なわれた場合には、クローンとしての動作は行なわれなくなります』
と書かれているのでdupが信用できるのだかできないのだか分りません)
 現在のところはdup命令で妥協しているのですが、なまじ妙な条件付きのせいでいつバグが
起きるのか怖くてたまりません。

 なので具体的な質問としては、
Q1,dup命令でモジュール変数の恒常的で安定したクローンは製造できるのか?
(尚、条件としては親モジュール、子、孫、曾孫、玄孫以下全てのモジュールの要素は
数値要素(int)、文字列要素(str)、実数要素(double)、子モジュール要素(struct)のみで、
数値要素は+-6桁以内、文字列要素は20文字以内の無拡張です)
Q2,製造できないとしたらdup命令以外でモジュール変数のクローンは製造できるのか?
 以上の2つです。ご指導お願いします。



この記事に返信する


窓口

リンク

2010/1/29(Fri) 00:02:17|NO.30215

Q1 について
試してみましたが出来るみたいです。


#module modvar0 x,y #define modmax 2 #modinit int x_,int y_ x = x_ y = y_ return #modfunc add0 int x_,int y_ x =x_ : y = y_ return #modcfunc printmxy return strf(" m0 %d,%d" , x,y) #global #module modvar x,y,m #modinit int x_ , int y_ , array modvar_ dup m,modvar_ x = x_ y = y_ return #modfunc add int ax_ , int ay_ x = ax_ y = ay_ return #modfunc add2 int mx_ , int my_ return #modcfunc printxy return strf("m %d,%d" , x,y)+" : " + printmxy(m) #global newmod m0 , modvar0 , 100,200 newmod m1 , modvar , 10,20 , m_p0 mes printxy(m_p) add0 m_p0 , 123 , 124 mes printxy(m_p)



窓口

リンク

2010/1/29(Fri) 00:19:52|NO.30216

すみません、Q1の恒久的で、安全なクローンかどうか、
というところを読み飛ばしていたようです。

根拠は有りませんが、多分大丈夫です(笑)



レノス

リンク

2010/1/29(Fri) 23:35:03|NO.30233

* #define により定義されるマクロは、スクリプト自体をいじくるので、
 今回の話には関係ありません。

> モジュール変数のコピー
例 3 の z2 のメンバである F1 は、z1 への (微妙な) クローンとして働きます。
そのため、そのような動作になります。

* モジュール型変数の代入はそういう仕様です (詳細は後述)。

> 例 4

実際に実行されるのは次のようなスクリプトです。

x = 3 : y = 4 : mes "X="+ x +" : Y="+ y x = 5 : y = 12 : mes "X="+ x +" : Y="+ y stop

> 普通に[X=M]と入力してはXが変更されても、
> それに連動してMが変更されません。
Mがモジュール変数なら、連動するはずです。


> Q1
元の変数が、配列拡張したり、文字列型のバッファ拡張をしたり、型が変わったりするときに、
そのクローンは無効になりますが、逆に言うと、そうしなければ恒常的に使用できます。
( この他に制限はなかったと思います。 )

そのため、「モジュール変数の配列を拡張しない」という条件付きなら、普通に可能です。
そうでなければ、不可能です。

> Q2
モジュール変数を他の変数に = で代入することで、左辺が、右辺のクローンになります。
これならば、右辺のモジュール変数が配列拡張されても、左辺のクローンは死にません。

( もちろん、右辺のモジュール変数が delmod などで消えると、左辺は死にます。 )

というわけで、オススメは、代入によるクローンです。



adref

リンク

2010/1/30(Sat) 00:02:58|NO.30235

木村さんの内容はm1やmm2などモジュール名と命令名が似通っており、お世辞にも他人に説明するためのスクリプトとは思えないため、
その後のm1がどうのこうの、mm2ではどうのこうのといった説明に目を通す気が起きませんでした。
途中まで読んだ時点での貴殿の勘違いをご指摘いたします。

>z1の情報を変更した後でz2の情報を呼び出してみると、z2はz1変更の影響を受けている事が分かります。

全く違います。z2とz1は別のモジュール変数です。

ややこしいのでいい改めます。

z1やz2はモジュール識別変数、そのモジュールのインスタンスです。
z1はモジュールm1のインスタンス、z2はモジュールm2のインスタンスです。

モジュールm2のコンストラクタは引数にモジュールのインスタンスを受け取り、モジュール変数(メンバ変数)にインスタンスを保存する仕様になっています。
>定義
>  #module m2 F1
>    #modinit array a1
>    F1=a1
>    return
>呼び出し
>  newmod z2,m2,z1 // z2はm2のインスタンス、コンストラクタでz1のインスタンスを保存

インスタンスz2の情報を表示しているというmm2命令を見てみましょう。
>  #modfunc mm2
>    mm1 F1
>    return
インスタンスz2のモジュール変数F1は保存したモジュールm1のインスタンスz1です。
要するにmm2命令はモジュールm2のインスタンスz2を引数に受け取っていながら、
内部ではモジュールm1のインスタンスz1を引数にmm1を呼び出しているのです。

mm1命令は与えられたインスタンスのモジュール変数F1とF2を表示するだけですから、
モジュールm1のインスタンスz1が与えられればz1の情報を表示します。


そもそもモジュールm1とm2ではモジュール変数の構造に互換性はない(個数が違う)ので、
>z1の情報を変更した後でz2の情報を呼び出してみると、z2はz1変更の影響を受けている
わけがありません。
モジュールm2にはモジュール変数F2は無いからです。


正しい理解が無いために

勘違い
をしてしまっただけでしょう。

#defineマクロに関しても#defineマクロの正しい理解が無いために
>zをマクロとしたせいなのかzが常にxとyの影響を受けています。
などと勘違いをしているに過ぎません。
あなたが

#define z "X="+x+" : Y="+y x=3 : y=4 : mes z x=5 : y=12 : mes z stop
と書いたものは、あなたが

x=3 : y=4 : mes "X="+x+" : Y="+y x=5 : y=12 : mes "X="+x+" : Y="+y stop
と書いたも同然なのです。「zが影響を受ける」という解釈は大間違いです。

正しい理解のない憶測は読むだけ無駄ですので、これらの正しい知識を元に
ご自分の憶測を考え直してみてください。


窓口さん あなたもプログラマの端くれなら「多分」という言葉は捨てたほうが良いです。



木村

リンク

2010/1/30(Sat) 01:21:43|NO.30236

 解決しました。おかげさまで、スクリプトが安心して組めるようになりました。
 窓口様、レノス様、adref様、回答をどうもありがとうございました。

 後、ソースが見にく過ぎた点は失礼しました。次からは気をつけます。ご指摘
ありがとうございました。



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