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


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0507
woods57#define の global49解決


woods57

リンク

2013/5/7(Tue) 01:41:37|NO.53865

兵庫県姫路市の57歳、あるきっかけでHSPを勉強しはじめた
ビギナーです。
HSPはまずGUIからとscreen命令から読み始め(プログラミングガイド)
ウインドウを中央表示するにはどうしたら・・と考え
defcfuncで計算結果を配列で2つ返せばいいと思ったがreturn 配列(n)
とできないようであきらめ、#moduleで行こうと思っても
#modcfuncで配列は返せないだろうと思い、#modcfuncを2つ作るも
1)モジュール内の変数は#moduleの直下行で定義しても#modcfuncでは
使えず#modinitで定義したらよいようで、
2)newmod で #modinitを動かそうとすると以下のようなエラーが発生。

#HSP script preprocessor ver3.32 / onion software 1997-2013(c)
#Use file [hspdef.as]
#HSP code generator ver3.32 / onion software 1997-2013(c)
#defineのテスト.hsp(25) : error 28 : モジュール変数の指定が無効です (25行目)
--> #deffunc __init modinit abc,

ドキュメントライブラリのエラー一覧には、エラー番号違いの
「36 "モジュール変数の指定が無効です"
パラメーターに指定されたモジュール変数が間違ったモジュールで 初期化されている場合に表示されます。
通常、表示されることはありません。
これが表示される場合は、 システムに致命的なエラーが発生したことを示しています。」
と記載されており、意味不明でスクリプトエディタを再起動する無駄をして
結局#module モジュール名 のうしろに何かのパラメータが一つでもあればエラーが発生
しないようだとわかり、
3)最後にnewmod命令を#defineで別の書き方にしたかったのでこの#define (global付き)
を#moduleの直下あたりに置いていたのが無意味で、#modinit内に置いてもダメで
#module〜#globalの外に置かねばならないようだとわかりました。
プログラミングガイドの#defineの説明では
「#define命令の直後に「global」を入れることで、
すべてのモジュールで永続的に利用することのできる
マクロを作成することができます。」って書いてあるじゃない。

プログラムが簡単に作れることを期待しているのではないけど、
プログラミングガイドは曖昧だし、文法のチェックもゆるゆるのようで
それはいいとしてもエラーメッセージは意味不明だし、この壁を乗り越える
人は限られた人になるような気がします。

#moduleのパラメータは何のためにあるのか説明もなく、
アバウトなサンプルプログラムでどこまで想像力をふくらませることができるか
私は、「ダミーパラメータ」と考えています。

newmod命令を#defineで別の書き方にしたいというのはやはり#module〜#global内
に置きたく、delmod命令で#undefしたいのです。

私は日ごろの仕事ではExcelと関数とVBAを使う事が多く、多くの言語を
比較できませんが、何ができるのか、できないのか、有効範囲(スコープ)だとか
こういうことがらは基本事項と思うのですが、独学する者には敷居が高いなあと
思います。諸先輩の方はよりアバウトな情報でマスターされたのでしょうね・・・
5月の連休は小さな一歩、意気消沈。



この記事に返信する


f(早出前)

リンク

2013/5/7(Tue) 04:14:47|NO.53866

「そもそも絶対に配列で返す必用あるのか」

と言う辺りに立ち帰るべきではないか。

この話を聞く限り、必要なものは「x,y座標」であるし、
個別にx座標用、y座標用のモジュール関数作れば済む話と思われ、
態々配列で取り出す意味も意義も感じられない。

しかも、その方が

#module #defcfunc getWX int _width return ( ginfo_dispx - _width ) / 2 #defcfunc getWY int _height return ( ginfo_dispy - _height ) / 2 #global screen 0 , 640, 480 , 0 , getWX( 640 ) , getWY( 480 )
の様に書けてスマートだ。


どうしても「配列で返したい」のなら

#module #deffunc getWXY array _xy , int _width , int _height _xy( 0 ) = ( ginfo_dispx - _width ) / 2 _xy( 1 ) = ( ginfo_dispy - _height ) / 2 return #global dim wpos , 2 // 配列を作って getWXY wpos , 640 , 480 // モジュールに渡す screen 0, 640 ,480 , 0 , wpos( 0 ) , wpos( 1 )

この様にする。



KA

リンク

2013/5/7(Tue) 08:51:28|NO.53868

>>HSPはまずGUIからとscreen命令から読み始め(プログラミングガイド)
>>ウインドウを中央表示するにはどうしたら・・と考え
>>defcfuncで計算結果を配列で2つ返せばいいと思ったがreturn 配列(n)
>>とできないようであきらめ、#moduleで行こうと思っても
初心者が、いきなり難しい事をしようと思っても、それま無理でしょう。

>>私は日ごろの仕事ではExcelと関数とVBAを使う
それを覚えた方法と比較して下さい。



y.tack

リンク

2013/5/7(Tue) 09:14:43|NO.53869

なんかなんでHSP3 モジュール機能ガイド。が中上級者向けなのかわかった気もします
http://www.onionsoft.net/hsp/v33/doclib/module.htm
#deffuncとかモジュール変数とかerrorメッセージの情報の精度低いからです
そういう意味では
>それはいいとしてもエラーメッセージは意味不明だし、この壁を乗り越える人は
HSPユーザーはこの壁を乗り越えるのに皆、一度は苦労したかもしれません
僕はサンプルスクリプトをものすごい参考にして
なんとなく飲み込めて、後は自分で書いたスクリプトを参考にしたり
書いたメモ参考にしてます

でもHSP2.61のクックブックではあんまり#deffuncとか使ってなかったような
HSPはBASICライクな言語なので
無理にそういうの使わずにグローバル変数とgosub/gotoサブルーチンで書いていって
暇なときに#defffuncとか実験していって
なんとなく理解していくという流れなのかな?

後、HSPの返り値は引数用だと解釈しているので
2個値返してその2個をどうやって一つの引数に渡すのか謎です
Perlは渡せるんですが、複数返しってどうやって渡したかな
(リストに渡したことしかないので)

2個返したいなら、無理に一行に書かないで

#module #deffunc getWXY var _width , var _height _width = ( ginfo_dispx - _width ) / 2 _height = ( ginfo_dispy - _height ) / 2 return #global x=640:y=480 getWXY x,y screen 0, 640 ,480 , 0 , x ,y
のように変数引数を加工して次の行で使用しましょう
後#moduleの後のエイリアスは
名前空間分割用です

>文法のチェックもゆるゆるのようで
>Excelと関数とVBAを使う事が多く
僕もHSPは最初の言語じゃないし
勘で書いてもそんなに普通の文ではひっかからないような
でも#deffunc辺りはやたら意味不明なerror出ました

普通の文では
型付けの弱さ。とか文末に;がないとかで
うるさいerrorは少ないですが
割と的確にerror出ますけど
後、コンパイルはしないので
一気にダダーっとerrorが出ないので
ゆるゆるに感じるかもしれませんね



レノス

リンク

2013/5/7(Tue) 15:15:06|NO.53870

モジュール(#module)の機能は重要ですが、
モジュール変数(#module m x,y,z...)の機能はおすすめしません。
ドキュメントも少ないですし。

> 3)最後にnewmod命令を#defineで別の書き方にしたかったのでこの#define (global付き)
> を#moduleの直下あたりに置いていたのが無意味で、#modinit内に置いてもダメで
> #module〜#globalの外に置かねばならない
中にある #deffunc などが使用されていないモジュールは、
“使われていない”と判断されて、自動的に削除されてしまいます。
おそらくそのせいかと。


#module #define global mymes mes // モジュールの中で定義 #deffunc f mes "f" return #global mymes "hello!" // 有効 f // ←モジュールが使われていると判断される

> y.tack さん
コンパイルはします。エラーが1つ返った時点で終了する仕様なのです。



woods57

リンク

2013/5/10(Fri) 01:25:02|NO.53930

fさん 早出前の時刻にありがとう、
(1)HSPが配列をreturnできないことがはじめからわかっていれば
 ある種のあきらめまたは割り切りをして指摘されたようにしたかもしれない。
 しかし私は配列を返すくらいの事はできるだろうとドキュメントに「できる」
 とは書いてなかったが「できない」とも書いてなかったので・・・。
(2)getWXとgetWYの二つの関数に分けるという案は私には思い付かないざんしんな
 考えで驚いたが、これは単独値しか返せないことを前提に考えていると思われ
 また2つの関数は1回ずつ使って初めて一人前のしごとをする半人前関数と考えると
 やはり一人前関数をひとつ作りたい。表示したいウインドウの横幅と高さの2つを
 与えたら中央配置するための左上隅の座標xとyを同時に返すものにしたい。
(3)どうしても配列で返したいならという案もいただいたが
 パラメータとは引数であり引き渡す領域または値と考え、引き渡される領域と
 して使いたくない。VBやその他の言語でも参照渡しだから戻す領域にも使えるが
 何を渡して何を受け取るのかが不明瞭になるから推奨していない、
 関数とは引数を渡して結果を戻すのはイコールの左側であるべきだとしたい。
 それがHPSの常識で引数の一つは戻り値領域だというのは
 HSPの基本ということでなく回避策として使うということだと思う。
 誰もが左辺に返してほしいと願うもの、しかしできないという位置づけだろうと
 考えます。
(4)当初はxとy座標があればと思ったが、中央配置のためにはタスクバーがどの位置に
 あるかも含めて計算しないと正しく中央配置できない。上辺や左端に置く人もいる。
 タスクバーの位置やサイズ情報を取得しようとすると2つを超える数の戻り値が必要で
 やはり配列で1回の呼び出しでプロパティ値getのような形ででも取得したい。

screen命令の使い方を勉強するだけでさまざま立ちはだかる壁があり、それぞれを
はし折って書いてしまい申し訳ありません。


 



f(現場前)

リンク

2013/5/10(Fri) 10:43:30|NO.53933

誰も止めやしないし、文句も言わないし、最終的に本人の好きなようにすれば良い事だが。
「HSP的ルール違反行為」に拘るより「ルール内で出来るカッコイイ書き方」に拘るほうが
余程建設的であろうと思う。



ht.

リンク

2013/5/10(Fri) 17:01:40|NO.53936

気持ちは非常によく分かるのですが、自ら言語の特徴を理解し歩み寄るのも
この先の苦難の解決策として大切な一つの能だとも言えます。

さて、どうしても返却値として二つのパラメータを渡したいならば、
戻り値の上位ワードと下位ワードに結果を格納するという方法もあります。
HSPの整数型は32bitなので、これをニ分割して16bitずつ別の数値に見立てて使おうという概念です。
一応、使用メモリ節約にもなりますしWin32APIなどでは頻出する方法です。

#module #define global ctype MAKELONG(%1,%2) (%1) & $FFFF | (%2) << 16 #define global ctype HIWORD(%1) (%1 >> 16 & $FFFF) #define global ctype LOWORD(%1) (%1 & $FFFF) #defcfunc getWXY int _width, int _height x = ( ginfo_dispx - _width ) / 2 y = ( ginfo_dispy - _height ) / 2 return MAKELONG(y, x) #global xy = getWXY(640, 480) screen 0, 640 ,480 , 0 , HIWORD(xy) , LOWORD(xy)

あとはお馴染みの参照で引数を入力・出力に使用する方法など

#module #deffunc toWXY var _width, var _height _width = ( ginfo_dispx - _width ) / 2 _height = ( ginfo_dispy - _height ) / 2 return #global x = 640 : y = 480 toWXY x, y screen 0, 640 ,480 , 0 , x , y
(3)について、引数は不明瞭との意見ですが
戻り値が配列というのも一旦説明を受けないと分からないと思います。
少なくとも複数のパラメータを受け取る関数ではまずは引数の参照を疑います。

このような入出力を兼ねる引数の指定方法は、HSP以外の言語にも通用する一般的な手段であり、
実際、戻り値に配列を使えたとしてもこっちの方が使用(仕様?)頻度は高いです。
この仕様ならば、戻り値は関数が成功したか否かの真偽値として活用できるので、
協同開発など堅実な設計が求められる場では他に悩む余地もありません。



osakana

リンク

2013/5/11(Sat) 00:46:04|NO.53946

強引な方法ですが、
マクロを使って配列が戻った様に見せかける事が出来ます
と言ってもこれでは配列というよりパラメーターが2つ戻ってるだけですけど。

#define ctype WNDPOS_CENTER(%1, %2) ( GINFO_DISPX - %1 ) / 2, ( GINFO_DISPY - %2 ) / 2 screen 0, 640, 480, 0, WNDPOS_CENTER(640, 480) buf = WNDPOS_CENTER(640, 480) mes "" + buf + ", " + buf(1)
後この方法の延長として、
思い付きですがモジュールと組み合わせても良さそうですね。

#module mod_center #define global ctype get_center(%1,%2,%3,%4) _get_center(%1, %2, %3, %4), result@mod_center(1) #defcfunc _get_center int w1, int h1, int w2, int h2 result = (w1 - w2) / 2, (h1 - h2) / 2 return result #global screen 0, 640, 480, 0, get_center(GINFO_DISPX, GINFO_DISPY, 640, 480) buf = get_center(GINFO_DISPX, GINFO_DISPY, 640, 480) mes "" + buf + ", " + buf(1)
しかしマクロはプリプロセスのため
不用意に使用し過ぎると全体の模様が把握しにくくなるので
今までの書き込みを見ているとwoods57さんの意には沿わないかもしれませんね。
#ちなみに私も配列を戻り値に出来たら良いのにとは思いますが



投稿者名

リンク

2013/5/11(Sat) 02:06:01|NO.53948

ポインタなら配列を返せるような気がする
うまく動かなかったらごめんなさい

#module #defcfunc getWXY int p1, int p2 p( 0 )=(ginfo_dispx-p1)/2 p( 1 )=(ginfo_dispy-p2)/2 return varptr(p) #global dim p, 2 dupptr p, getWXY(640,480), 8 screen 0, 640, 480, 0, p( 0 ), p( 1 )



f(現場前)

リンク

2013/5/11(Sat) 09:18:31|NO.53949

>ポインタなら配列を返せるような気がする

元来、VBではreturnで配列が返せてるのだって、内部でポインタ返してるだけなのよ。

VBにはガベージコレクションがあるから、「どこで確保したメモリか」にかかわらず
持ち主の居なくなったメモリは自動で開放されるから、
メモリ周りの処理考えずに「returnで配列を返す」とか言えちゃうだけで。



woods57

リンク

2013/5/11(Sat) 19:49:40|NO.53973

y.tackさん ありがとうございます。
やはり壁がありますよね、y.tackさんは
じわじわと霧をはらっていったように思いますが
短気な私はしばらくすると爆発炎上するかもしれません。
もやもやしたものがなかなかクリアにならず、
それが積み上がって・・・というように。
提供する側は作るのに苦労しているのに、説明不足だと非難するのも
どうかと思いますけどね。
姫路市で一番大きいと思われる駅ビルプリオあらためピオレ2階の
「ジュンク堂」書店に「HSPの本」を探しに行きましたが、
「1冊も置いていません」の回答。(新宿や大阪の紀伊国屋ほどは無い)
とりあえず図書館で借りて「HSP2.55」「3.2」を読んでいますが、
これも入門と書いてあっても命令の説明は簡単だし、
あとはサンプルを読めって〜ことなのか・・
違和感があるのはまだ気持ちが入っていない(ちからが無い)からかも。
しかし何とか頑張って壁を越えるべく、あきらめるまで、
あきらめません・・あきらめるんかい?(^^);
「#moduleの後のエイリアスは名前空間分割用」は後日自分で勉強します。



woods57

リンク

2013/5/12(Sun) 11:55:03|NO.53989

レノスさん、ありがとうございます。
>「 #deffunc などが使用されていないモジュールは、
>“使われていない”と判断されて、自動的に削除されてしまいます。」
とは驚きです。
どこかに書いてあるのか、HSPソースをご存じなのか、
周知の事実としてもこんなことはHSPの「暴挙(勝手なふるまい)」と思います。
つまり
deffunc/defcfuncとmodfunc/modcfuncの差はイマイチですが
modcfuncを持っているのにdeffuncがないと
「使われていない」と判断するなんてその理由なんぞ
どう考えても思いつきません。

示していただいたサンプルを実行すると確かに「mymes」は「mes」に置替わって
います。これをdeffuncからmodfuncに変えてみたらmymesがエラーになるのか
試してみたところ、「hello!」が表示され次のfで「#Error 23 変数名が指定されていません」
となります。#defineは「効いている」と。

#module テストモジュール parm ;追記 #define global mymes mes // モジュールの中で定義 #modfunc f mes "f" return #global newmod a, テストモジュール ;追記 無くてもいい? mymes "hello!" // 有効 f // ←モジュールが使われていると判断される

そこで自分でもテストプログラムを作ってみました。
mes命令で明確に表示して示せないのですが、デバッグウインドウで
#defineで置き換わった変数名になるのかならぬのかを見たところ
いずれも#defineが「効く」という結果に・・ (ToT)
以前の「ウインドウ中央配置の」エラーは何だったか今は証拠を示せません。
(以下余計なmesもあります)

#module test1 p1 モジュール変数1="アイウエオ" #define global ABC XYZ #modfunc testfunc1 mes "modfunc" return #global #module test2 p2 モジュール変数2="カキクケコ" #define global DEF UVW #deffunc testfunc2 mes "deffunc" return #global assert _debug ;意味不明だが・・ newmod a1,test1 newmod a2,test2 ;testfunc1 ;#Error 23 変数名が指定されていないとなる ; (#defineで置き換え対象にならなくてもなっても) ;testfunc2 mes "モジュール変数1="+モジュール変数1@test1 ;値は入ってない mes "モジュール変数2="+モジュール変数2@test2 ;値は入ってない ABC = "12345" DEF = "678" mes "変数1="+ABC mes "変数2="+DEF stop

「#Error 23」の対応も力不足のため解決できませんが先送りの課題にします。
なぜHSPがモジュールのdeffuncを認識できてmodfuncを認識できないのか
(モジュールの使い方が基本的に間違っているのかもしれない)



あり

リンク

2013/5/12(Sun) 15:11:58|NO.53992

modfuncでエラーが出るのは定義命令fにモジュール変数が指定されていないからです。

#module テストモジュール parm #define global mymes mes // モジュールの中で定義 #modfunc f mes "f" return #global newmod a, テストモジュール //モジュール変数を使用する為に必要 mymes "hello!" // 有効 f a // newmodで指定した変数を指定する
まず、ややこしい話ですが通常モジュール内で使われる変数と
モジュール変数は全く違う物です。
この事も含めてモジュール関係(特にモジュール変数)のドキュメントは
初心者には理解し辛いので、サンプルと見比べながら
試行錯誤を繰り返すしか現状理解の道はありません。

またモジュール変数は利用までの手続きが多い上に
現時点のHSPでは労力のわりに効果的に使える場面が少なく
他の言語の様な効率的な記述を目指すとかえって非効率になる
場合が多々あるのが実情です。

#module test1 p1 #define global ABC XYZ #modinit //モジュール変数を作成(newmod)すると実行される モジュール変数1 = "アイウエオ" return #modfunc testfunc1 mes "modfunc" return #global #module test2 p2 #define global DEF UVW モジュール変数2 = "カキクケコ" // ここに書いても無効(testfun2をコメントアウトすれば確認可能) #modinit // モジュール変数を作成すると実行されるが変数は使えないので無駄 モジュール変数2 = "カキクケコ" return #deffunc testfunc2 モジュール変数2 = "カキクケコ" // testfunc2を実行すると値を入力 mes "deffunc" return #global newmod a1,test1 // ;newmod a2,test2 // #deffuncなので必要なし(実行するとtest2の#modinitを実行) testfunc1 a1 // #modfuncで定義しているのでモジュール変数の指定が必要 testfunc2 // #deffuncで定義しているのでモジュール変数の指定は必要なし(指定するとエラー) mes "モジュール変数1=" + モジュール変数1@test1 ;#modinitを実行しないと値は入らない mes "モジュール変数2=" + モジュール変数2@test2 ;testfunc2を実行しないと入力無し ABC = "12345" DEF = "678" mes "変数1=" + ABC mes "変数2=" + DEF stop
HSPは機能拡張で様々な事が実現可能になりつつはありますが
その全てを楽に実現できる訳ではありませんので
無理に理想の構成を目指すより今理解出来ている事で
実現できる構成を考えた方が結果楽という事も多いです。



fortunehill

リンク

2013/5/12(Sun) 15:25:17|NO.53993

/*../sample/modfunc.hapを改造して説明して見ますが微妙かな? */

#module ball x,y ;ballと言うネームスペスと構造体もどき #modinit int a ;newmod実行時実行されその時受け取る初期値 x = rnd(a) :y = rnd(a) ;加工された初期値のセット return #modterm ;delmod(放棄)時実行される mes strf("xx( ) Bey X = %3d Y = %3d",x,y) return #modcfunc putprm ;モジュール型変数の値を直接値を読めないので return strf("Put X = %3d Y = %3d",x,y) #modfunc setprm int a ;モジュール型変数の値を直接値を書けないので x = a return #defcfunc func str a return getpath(a,16) #define test 123 #global repeat 5 ;ballと言う構造体を5個確保で良いかな newmod ii,ball,10 loop mes strf("vartype = %3d\nlength = %3d\n",vartype(ii),length(ii)) ;モジュール型変数の確認と確保した数の確認 mes strf("xx(%d) %s\n",cnt,putprm(ii(0))) setprm ii(0),123 ;モジュール型変数a(0)のxを書き換えてみる foreach ii :mes strf("xx(%d) %s",cnt,putprm(ii(cnt))) :loop mes delmod ii(0) #define test 456 mes strf("test = %d test@ball = %d",test,test@ball) ;名前空間による変数のスコープの確認 mes strf("function = %s",func("AAAAAAAAAAAAAAAAAA"));普通のファンクション stop



woods57

リンク

2013/5/12(Sun) 23:17:43|NO.54005

htドットさん ありがとうございます。
示していただいた1例め

二値限定配列 = 中央配置位置(640, 480) screen 0, 640, 480, 0, 二値限定配列1つめ, 二値限定配列2つめ
的イメージで使えるということですね、すばらしい。

2例め
toWXY x, y
は引数として渡す時は「表示したいウインドウの横幅と高さ」であり
命令の実行後は値が変化して「中央配置の左上隅のx座標とy座標」の
値に加工編集される一時入出力領域として使われる、
これはNo thank youです。
HSPでチーム開発することを想像すると複数の引数に複数の戻り値を
1つしか戻せない言語で堅苦しく言ってられるかというのはわかります。
しかしtoWXY の前後で x y の値が変化するというような命令が
これ以外にも多数あるとソースを追いかける机上デバッグが
できるでしょうか。(机上デバッグってするよね?)
まだHSPに明るくないので具体的な対案を示せませんが、
引数は引き渡すのみで変更されない方法を模索します。
たとえば、
(1)5/11投稿者名さんが書かれたvarptr 未確認
(2)モジュールで複数変数一括管理   それぞれにモジュールにするのかい?
(3)配列要素を1変数(文字型)にパックする機能を作る 遅くなるだろ!
今はよくわからずテキトーに書いています。
でもありがとうございます。



ht.

リンク

2013/5/13(Mon) 02:16:26|NO.54006

呼び出し時にdupptrを記述する手間を惜しまないならvarptrを使った方法が一番目的に近いです。
あとはもうstatみたいに結果を受け取るためのオリジナルシステム変数を用意するくらいでしょうか。

> しかしtoWXY の前後で x y の値が変化するというような命令が
> これ以外にも多数あるとソースを追いかける机上デバッグが
> できるでしょうか。(机上デバッグってするよね?)
うーん。例えばこういう関数はHSPでもそれなりによく使われます。
確かにtoWXY cx, cy, getx, getyとかにした方が良かった気もしますが。
http://msdn.microsoft.com/ja-jp/library/cc410572.aspx
HSPはC++から出来ていますが、C/C++では参照型やポインタはまさに結果を受け取るための代物です。
fさんがちらっと仰っていますが、本来メモリ管理はプログラマのお仕事で、
メモリリークが起きないために結果セットの格納に必要な領域は呼び出し側が確保するのが伝統です。
ですから堅苦しい話をするならば、むしろ引数で受ける方が手馴れたプログラマにとってスタンダードと言えなくもないです。
Rubyにも自身を加工する破壊的メソッドという概念があります。
C言語を齧ってみれば言わんとすることは一目瞭然だと思うのですが、
結論として(関数名さえきちんとしていれば)デバッグが辛いという人は少ないと思われます。



レノス

リンク

2013/5/13(Mon) 15:31:41|NO.54007

> HSPの「暴挙(勝手なふるまい)」と思います
いえ、#module は #deffunc, #defcfunc 他を囲うために使うものなので、
「内側で定義された命令・関数が使われていない #module は不要」と考えるのは
不自然なことではありません。

なお「#deffunc など」と書いたのは、
 #deffunc, #defcfunc, #modfunc, #modcfunc
の4つの略でした。雑で申し訳ない。

----
次のものが「モジュール変数」機能にまつわるHSPのキーワードです:
#modfunc, #modcfunc, #modinit, #modterm, newmod, delmod
「#module "モジュール名" メンバ変数列...」

これら以外、例えば #deffunc, #defcfunc と、通常の #module は、
「モジュール変数」機能とは無関係です。
このあたりの切り分けも、理解の助けになるかもしれません。

(前回のレスの冒頭に記したとおり、現時点では
「モジュール変数」機能は無視するのが一番だと私は思いますが)



woods57

リンク

2013/5/14(Tue) 01:09:43|NO.54031

osakanaさん ありがとうございます。
例示していただいた1つめの方法で
#define ctype WNDPOS_CENTER(%1, %2) 計算値その1, 計算値その2

buf = WNDPOS_CENTER(640, 480)
によって
buf = 計算値その1, 計算値その2
となり関数の結果が配列変数bufに返されるという形をとれる
ということですね!すばらしい。
3つでも4つでも返せると。
HSPの基本命令の組合せだけで計算できるような場合でないときは
例示いただいた2つめの
モジュールと#defineを組合せて
という考えは大好きです。
偽装してまたは変身させてでもわかりやすく書きたいと思うので
私はこの「2つのコラボでうまく見せられる案」がよいと思います。

細かい点で
1)2行めの
> #define ・・ get_center(%1,%2,%3,%4), _get_center(%1, %2, %3, %4), result@mod_center(1)
は1回_get_centerを実行して1つめだけを受取り、もう一つはその後に2つめの要素は
計算しているから入っているはずという指定、同時に受け渡す並べて書くようなものに
前提となる順序がからむ
2)7行めの
> screen 0, 640, 480, 0, get_center(GINFO_DISPX, GINFO_DISPY, 640, 480)
はscreen命令が見えるのなら
screen 0, 640, 480, 0, buf(0), buf(1)
のようなつまりscreenのパラメータの5番と6番めが位置xとyなのだから
パラメータが2つのように見えるようにしたい

初心者なのに文句が多くてすみませんね。こういうふうに・・と示したいところですが
作ろうとしましたがうまく作れなかったのでごめんね。
いろいろ勉強させていただき、ありがとうございます。

プリプロセッサの展開結果を見る機能があれば、試行錯誤しながら#defineを
創作できると思います。無いように思います。



ぴょぴょ

リンク

2013/5/14(Tue) 06:42:30|NO.54035

> プリプロセッサの展開結果を見る機能があれば、試行錯誤しながら#defineを
> 創作できると思います。無いように思います。
ありますよ。

// プリプロセッサファイル出力
#cmpopt ppout 1

他にもあるのでマニュアルをどうぞ。



123

リンク

2013/5/15(Wed) 22:25:48|NO.54067

>>プログラムが簡単に作れることを期待しているのではないけど、
>>プログラミングガイドは曖昧だし、文法のチェックもゆるゆるのようで
>>それはいいとしてもエラーメッセージは意味不明だし、この壁を乗り越える
>>人は限られた人になるような気がします。

HSPは自由度が高くて覚えやすいと思いますよ。
最初はやっぱりどうしたらいいんだろう?とか思う部分はあったけど
頭を切り替えて自分の好きな言語ライクに組んでいくようにしたらすんなり行くようになりましたし。

それとスコープ、引数の話が出てたんですが引数の変数に別の値入れたり
スコープ外の変数に値を出し入れも出来ますから(これやると後で整理やバグさがしが大変になるけど)
returnで返せるのは一個だけど実際にはいくらでも返せますよ。



woods57

リンク

2013/5/19(Sun) 10:14:59|NO.54143

5/11の投稿者名さん
ありがとうございます。
dim p, 2
dupptr p, getWXY(640,480), 8

dim p, 2
 p = getWXY(640,480)
と書ければ 配列を返したように見せられますね

まだそこまでは到達できないけれどテストプログラムを
作ってみました。
問題が残っていて、文字型の配列の長さをdupptrでどう与えるのか
わかりません。なので文字型配列を返すことはできていません。
とりあえず整数型と実数型だと4バイト、8バイトとわかるので
その範囲では教えていただいた方法で
関数から配列を「戻すように見せかける」ことがたぶん
できるだろうと思います。このあと#defineでうまく包み込めれば
ということですが。考えてみます。

#module ;本来は乱数発生、数字重複排除、昇順並べ替え ;すべきだがテストなので手抜き #defcfunc ロト7の番号を返す int p1 ddim 数値配列, 7 数値配列( 0 )=5 数値配列( 1 )=9 数値配列( 2 )=18 数値配列( 3 )=20 数値配列( 4 )=23 数値配列( 5 )=24 数値配列( 6 )=28 return varptr(数値配列) #global assert _debug ;意味不明だが dim 返却数値配列, 7 配列桁数 = 0 配列データ型 = vartype(返却数値配列) 配列要素数 = length(返却数値配列) If 配列データ型 = 4 : 配列桁数= 4 * 配列要素数 ;整数型は4バイト If 配列データ型 = 3 : 配列桁数= 8 * 配列要素数 ;実数型は8バイト 配列ポインタ = ロト7の番号を返す(1) ;何かパラメータが無いとエラーになる dupptr 返却数値配列, 配列ポインタ, 配列桁数, 配列データ型 mes 返却数値配列(0) mes 返却数値配列(1) mes 返却数値配列(2) mes 返却数値配列(3) mes 返却数値配列(4) mes 返却数値配列(5) mes 返却数値配列(6) stop ;実数型でやりとりするなら値セットも=5でなく=5.0としなければならない ;ddimで事前定義してもその時点では実数型だが ;=5を実行した時その配列は整数型になることをデバッグウインドウで確認した ;その次に9.0を代入すると「#Error31 異なる型を持つ配列変数に代入しました」となる



woods57

リンク

2013/5/19(Sun) 10:20:28|NO.54144

上記の16行目はdimではなくddimです。(ddimで確認した) 訂正。



fortunehill

リンク

2013/5/19(Sun) 16:09:18|NO.54152

/*ご参考*/

#module test #defcfunc ロト7の番号を返す ;値を返す関数は()で括る必要がある ddim 数値配列, 7 ;型宣言しても最初に入力された値で初期化されてしまう 数値配列( 0 )=double( 5) ;初回のみキャストか明示的に代入が必要 数値配列( 1 )= 9.0 数値配列( 2 )=double(18) 数値配列( 3 )=double(20) 数値配列( 4 )=double(23) 数値配列( 5 )=double(24) 数値配列( 6 )=double(28) mref _refstr,65 _refstr = length(数値配列) ;文字列の返り値に配列数を代入する return varptr(数値配列) #global dupptr 返却数値配列,ロト7の番号を返す(),int(_refstr@test)*8,vartype("double") repeat length(返却数値配列) ;(0+_refstr@test) mes 返却数値配列.cnt loop



y.tack

リンク

2013/5/19(Sun) 16:42:02|NO.54155

文字列で返して、受け取り側で分割する方法もありますよ

#module #defcfunc ret_str int p1,int p2,int p3 return ""+p1+"\n"+p2+"\n"+p3 #deffunc sep_str str p s=p sdim ar,16,16 split s,"\n",ar foreach ar // tmp=int(ar.cnt);でint型に変わる mes ar.cnt loop return #global sep_str ret_str(1,12,123) stop



暇人

リンク

2013/5/19(Sun) 16:55:40|NO.54157

>文字型の配列の長さをdupptrでどう与えるのか
文字列が入ってるバイト数ならstrlen(p1)

a="123あいうえお" mes strlen(a) //dupptrに渡すなら終端文字も含めた方が良いだろうから+1する //確保してるバッファサイズの取得(この方法が良いかどうかは分からない) dupptr a_strsize, varptr(a)-16,4,4 mes a_strsize //a_strsizeは通常ユーザーが触らないメモリなので書き換えたりしちゃいけない・・・



woods57

リンク

2013/5/19(Sun) 23:11:07|NO.54166

#defineで包み込む方法を考えていましたが
この展開形がどのようになるのか確認もできず
とりあえずギブアップします。(え〜っなんと軽々しい)
(1)マクロの展開は5/14ぴょぴょさんに教えていただき
 できそうだと思いましたが#cmpopt ppout 1を先頭に記述しても
 スクリプトと同じフォルダのhsptmpやhsptmp.iには展開も出ていないし
 リファレンスに説明もないし、デバッグウインドウでステップ実行される
 訳でもないし、#define 1行で書いたりもしましたが
 期待のようには動かず、原因も調べきれないので。(何もしてないということです)
(2)#define 〜〜 を複数行に書こうとして : \と書き、
 その後ろに空白1つでもあると文法エラーですなどとすぐにはわからぬ
 エラーではじかれます。あまり活用されていないのか自分の力不足か
 いずれも低レベルにとどまっていると感じます。
(3)これがうまくできたとしても、ポインタ値からクローン変数で
 使うときのdupptrにはポインタ変数だけではなくデータ長さや型まで
 与えなければならないなんておかしいでしょ。(と八つ当たり)
 varptrでアドレスだけ取得するのではなくメモリを2倍使っても
 長さや型までの情報をdupptrに渡すべきだと思います。
 そのようにできていないのをできるようにしようとすると
 もう2つ3つ情報を渡すように考えるとするとreturnで1つだけでは
 足りません。
ということでぐずぐず言い訳しながら#defineの勉強を先送りします。
期待はずれで[誰も期待してないか(--);]すみません。

下記はうまく動かないものです、コメントアウトしたところ
を戻すと動くのですが#defineで同じことをしようとしてできません。
この考えの前提にはモジュールで戻り値のポインタを受け取る前に
クローン変数の為の配列を事前定義(Dim/DDim)していると考えています。
これがなくてもという条件ならモジュールでその情報も返却することを
考えねばなりませんが下記はそうしていません。

#define global ctype ポインタ付け配列の展開(%1, %2) \ x配列データ型 = vartype(%1) : \ x配列要素数 = length(%1) : \ If x配列データ型 = 4 : x配列桁数 = 4 * x配列要素数 : \ If x配列データ型 = 3 : x配列桁数 = 8 * x配列要素数 : \ dupptr %1, %2, x配列桁数, x配列データ型 #module #defcfunc ロト7の番号を返す dim 整数配列, 7 整数配列( 0 )=5 整数配列( 1 )=9 整数配列( 2 )=18 整数配列( 3 )=20 整数配列( 4 )=23 整数配列( 5 )=24 整数配列( 6 )=28 return varptr(整数配列) #global assert _debug ;意味不明だが dim 返却整数配列, 7 配列ポインタ = ロト7の番号を返す() ;5/19 fortunehillさんに教えてもらった書き方 ;tmp1_配列データ型 = vartype(返却整数配列) ;tmp1_配列要素数 = length(返却整数配列) ;If tmp1_配列データ型 = 4 : tmp1_配列桁数 = 4 * tmp1_配列要素数 ;If tmp1_配列データ型 = 3 : tmp1_配列桁数 = 8 * tmp1_配列要素数 ;dupptr 返却整数配列, 配列ポインタ, tmp1_配列桁数, tmp1_配列データ型 ポインタ付け配列の展開(返却整数配列, 配列ポインタ) mes 返却整数配列(0) mes 返却整数配列(1) mes 返却整数配列(2) mes 返却整数配列(3) mes 返却整数配列(4) mes 返却整数配列(5) mes 返却整数配列(6) stop
このあとは第二、第三の方法に行こうと思いますが
第二の方法「何でもモジュールにする」方法は、できるとわかっているので
「配列を返したい関数はモジュール化で」となるんだろうと予想しながら
教えていただいている他の方法を試そうと思います。
私はHSPの#defineに期待をしていたのですが
(上記の方法にではなく#defineそのものにです)、自分の基本レベルが
低すぎるのか、HSP#defineが軟弱なのか、がっくりです。
なかなかついていけませんね。

レスが遅いですがご容赦ください。



暇人

リンク

2013/5/20(Mon) 00:03:24|NO.54167

> スクリプトと同じフォルダのhsptmpやhsptmp.iには展開も出ていないし
hsptmp.iにマクロも展開されて出力されてる(hspdef.asは出力されないで空行が130行ぐらい付くが・・・)

タブは削除して展開されたのをコピペ
>x配列データ型 = vartype@hsp(返却整数配列) : x配列要素数 = length@hsp(返却整数配列) : if@hsp x配列データ型 = 4 : x配列桁数 = 4 * x配列要素数 : if@hsp x配列データ型 = 3 : x配列桁数 = 8 * x配列要素数 : dupptr@hsp 返却整数配列, 配列ポインタ, x配列桁数, x配列データ型
単一行にifが有るのでそこで弾かれると以降が実行されない

ifに関係なく以降も実行させるには{}で囲う

If x配列データ型 = 4 { x配列桁数 = 4 * x配列要素数} \ If x配列データ型 = 3 { x配列桁数 = 8 * x配列要素数} \



fortunehill

リンク

2013/5/20(Mon) 00:08:29|NO.54168

/*ご参考 #define ctype マクロ中で値を返す以外の処理を行うと機能しません*/

#module #defcfunc ロト7の番号を返す dim 配列, 7 配列( 0 ) = 5,9,18,20,23,24,28 return str(varptr(配列))+","+str(length(配列))+","+vartype(配列) ;refstrで返してsplitで分解する ;キッチリメモリー割り当てなくても良いなら4*100とか適当なサイズでも良いかと #defcfunc ポインタ付け配列の展開 str p1,var p2,local ss,local ii ss = p1: split ss,",",ss :if (stat < 3) {return 0} switch int(ss(2)) case 3 : ii = 8*int(ss(1)) :swbreak case 4 : ii = 4*int(ss(1)) :swbreak default: ii = 1024 :swbreak swend dupptr p2,int(ss),ii,int(ss(2)) return length(p2) #global repeat ポインタ付け配列の展開(ロト7の番号を返す(),xx) mes xx(cnt) loop



レノス

リンク

2013/5/20(Mon) 21:35:14|NO.54174

> #define ctype マクロ中で値を返す以外の処理を行うと機能しません
そんなことはありません。
#define は単なるスクリプトの書きかえなので、書いた通りに機能します。

#define ctype c_mes(%1) mes %1 c_mes("hello") //= mes "hello"



fortunehill

リンク

2013/5/20(Mon) 23:14:25|NO.54177

/*あえて ctype を使うなら値を返す処理を行いたい=機能しないでしたが
言葉足らずか書き方が悪かったですね*/

#define ctype c_mes(%1) mes %1 c_mes("hello") //= mes "hello" #define _mes(%1) mes %1 _mes("hello") xx = c_mes("hello")



woods57

リンク

2013/5/21(Tue) 01:52:28|NO.54182

暇人さんありがとうございます。

(1)指摘いただいた If文の実行命令を { }で囲む修正のみで
 #defineは期待の動きをするようになりました。
 「:」がマルチステートメントの始まりつまりIf文の終わりになるだろう
 と考えていましたが、HSPは条件を満たした時の命令がマルチステートメント
 で続いているとでも判断しているのでしょうか。
 Ifで条件を満たした時に行なうのが命令1つならコロンで区切って書くと
 プログラミングガイドに書いてあり、
 命令が複数なら「{」「}」を使うと書いてあります。
#defineの中では
 #enddefine のようなものが無いがために :と\ で定義は続いていると
 書かねばならない そういうときのIfの書き方は
 単一命令でも「{」「}」で囲め  はプログラミングガイドに必要ですね。
今考えるとHSPにはendifなどなくて 条件と条件を満たしたときの命令を
 コロン1つで分けるというのが安易な文法のように思えます。
 RubyのIf文も then またはコロンで分けますがRubyには(Ifの)endがあります。
 #defineにも#enddefineがあれば、「:\」など要らないはずです。
 私はHSPの構文規則が「変だ」と思います。

(2)マクロの展開
>hsptmp.iにマクロも展開されて出力されてる
>(hspdef.asは出力されないで空行が130行ぐらい付くが・・・)
 hsptmp_iが確かに129行空白を置いて展開されているのを確認しました。
 エディタで開いた時垂直スクロールバーの長さに注意がいってなくて
 展開されていないと早合点しました。

二つ教えていただいたことで#defineの展開を確認することができます。
ありがとうございます。



ぴょぴょ

リンク

2013/5/21(Tue) 18:07:37|NO.54188

最初に私はC/C++言語の出身です。

>  #defineにも#enddefineがあれば、「:\」など要らないはずです。
>  私はHSPの構文規則が「変だ」と思います。
HSPはC/C++の便利な機能をたくさん取り入れてます。
特にプリプロセッサの #define はC/C++言語の真似ですよ。
でね。
C/C++ にも #enddefine なんてないんです。

だからHSPの構文規則が「変だ」というよりも
VB 出身者の方がプリプロセッサ機能を知らないだけなのです。
ただし、VB.NET からプリプロセッサ機能が追加されたようですね。



woods57

リンク

2013/5/23(Thu) 12:53:51|NO.54229

ありさん ありがとうございます。
fを使うときはaが必要だということでmodfuncとdeffuncの違いが
わかったように思います。
モジュールとは、VBやJAVAでよく説明されるクラスであり
HSPのモジュールはクラス定義で、newmodはインスタンス生成だと
いうことなんでしょう。
たとえばゲームの敵キャラをクラス定義し、その強さをmodinitで初期設定し
modfuncでインスタンス別に場所移動させるためにモジュール変数を指定する
というような感じ。
インスタンスを複数作ることもないような場合は
modfuncでなくてもdeffuncでよいと、またはインスタンス共通ならdeffuncだと。
それならプログラミングマニュアルにそう書いてくれたらいいのに。
HSP3 モジュール機能ガイドにはこう書いてあります。
「モジュール機能は、複数のスクリプトをラベル名や変数名の衝突を気にせず
結合するための仕組みです。
この機能は、大きなサイズのスクリプトを作る時や、
多量の変数名を管理 する場合に有効です。」
とても抽象的だ、またこの程度で理解しろなんてと思います。
インスタンス1つならモジュールはいらねえという解釈は
今はreturnでの返却結果を複数取得したいという要求の代用方法として
希望のひとつですから・・
私は多量の変数名を管理する・・に着目したのです。
解釈を大きくはずしてませんよね。
f には a が必要という指摘は もやもやを晴らしてくれた気がします。



774

リンク

2013/5/23(Thu) 16:47:06|NO.54238

まず、"モジュール機能"と"モジュール型変数"は、全くの別物だと考えた方が良いと思います。
以下はあくまで私見ですし、呼称も間違ってるかも知れません。

◆モジュール機能
複数の追加命令/関数(deffunc/defcfunc)をまとめておける個別のローカル空間。
モジュール内の変数は、同名なら同一のもの。
モジュール外の変数は、同名でも別個のものとして扱われる。
#const/#define/#func/#cfunc も global 指定が無い限りモジュール個別っぽいです。

◆モジュール型変数
モジュール機能にクラスのようなメンバ変数やメンバ関数を追加してみたもの。
生成されたインスタンス(モジュール型変数)毎に、内部の"メンバ変数だけ"は別物。
メンバ変数以外の同名の変数は、同モジュール内では同一のもの。

◇local指定の引数 (ついで)
「#deffunc func int p1, local a」における「a」。
宣言された命令/関数内でのみ存在する変数。
再帰的処理の場合でも、ネスト毎に別個な気がします。


HSPにおいて変数は全て(local指定引数を除き)グローバル変数として扱われる為
ローカルな変数等を扱う為の空間(変数の有効範囲)の定義として、
#module 〜 #global 間のモジュール機能があると思っています。

ですので"モジュール機能"の説明としてはガイドも間違ってないのですが
モジュール型変数の存在、それぞれの呼称が紛らわしい事、
モジュール型変数がモジュール機能も丸ごと継続してる点などで
非常に解り難い事になってる気がします…

モジュール型変数はクラスと同等に扱おうとすると痛い目見ると思いますが、
モジュール機能自体は普通に便利だと思いますよ。



ぴょぴょ

リンク

2013/5/23(Thu) 18:08:26|NO.54241

> #const/#define/#func/#cfunc も global 指定が無い限りモジュール個別っぽいです。
global 指定が無い限り個別だと思います。

> 再帰的処理の場合でも、ネスト毎に別個な気がします。
もともと再帰処理に対応するために local 機能を追加したと思われます。
なお、#deffunc の次に local を指定するとモジュール内でしか呼び出せない
ユーザ定義命令、ユーザ定義関数となります。
つまり、C/C++ の static 修飾子と同じ役割ですね。

> ローカルな変数等を扱う為の空間(変数の有効範囲)の定義として、
> #module 〜 #global 間のモジュール機能があると思っています。
そうですね。

> ですので"モジュール機能"の説明としてはガイドも間違ってないのですが
> モジュール型変数の存在、それぞれの呼称が紛らわしい事、
> モジュール型変数がモジュール機能も丸ごと継続してる点などで
> 非常に解り難い事になってる気がします…
同感です。
しかし、HSPがどのように機能アップして来たのが考えると納得がいきます。

N88-BASIC を元に作成される(goto、gosub)

gosub に引数が使える機能を追加する
ユーザ定義命令(#deffunc)

#deffunc に戻り値を返せる機能を追加する
ユーザ定義関数(#defcfunc)
定義(define)、C言語風(c)、関数(function)の略

変数のローカル機能を追加する
#module 〜 #global 間でユーザ定義命令、ユーザ定義関数の利用

#module 〜 #global 間に C++ のクラス概念を取り入れる
#modinit、#modterm、#modfunc、#modcfunc を追加する
これに伴い newmod、delmod、thismod などが追加される

●まとめ
モジュール機能=変数のローカル機能
モジュール型変数≒オブジェクト指向のクラス概念

こんな感じですね。



woods57

リンク

2013/5/23(Thu) 19:30:58|NO.54245

fortunehillさん ありがとうございます。
・modfuncでモジュール内の変数を操作する
・モジュール内変数とモジュール外の変数は同一名でも別に管理されている
など理解できます。

以下、全くの余談ですが、
モジュール内の変数をmodfuncでもdeffuncでも同様に扱える
ことを確認しようと思い作ったものですが
#globalの直前のreturnを書き忘れて動かしたら
 #Error29スタックオーバーフロー
となります。すぐにはわかりませんでしたが
deffuncとmodinitを無限に繰り返すのはなぜなのかと
眺めていたら見えてきました。#globalを突き破って
newmodを実行、次のdeffuncを呼ぶという流れだろうと。
HSPってけっこう間違った記述に忠実なんだなあと思いました。

#module test1 p1 #modinit mvar=3.14159 mes "modinit: mvar="+mvar return #modfunc modfunc01 mes "modfinc: mvar="+mvar return #deffunc deffunc01 mes "deffunc: mvar="+mvar ;return ;これを書き忘れるとdeffuncからnewmod→deffunc→newmodとループし#Error29スタックオーバーフローとなる #global newmod a1,test1 deffunc01 modfunc01 a1 stop

strf関数で書式編集というのはまだ学習していませんでした。

a=123 mes "変数値123を表示するのに" mes "10進..%d["+strf("%d",a)+"]" ;[123] mes "10進..%i"+strf("[%i]",a) ;[123] mes "10進..%u"+strf("[%u]",a) ;[123] mes "10進ケタ数指定で..%5d :" + strf("[%5d]",a) ;[ 123]整数部をゼロサプレス mes "10進ケタ数指定で..%05d :" + strf("[%05d]",a) ;[00123] mes "10進ケタ数指定で..%5.6d:" + strf("[%5.6d]",a) ;[000123]整数に小数以下桁数は無意味 mes "16進で..%x" + strf("16進[%x]",a) ;[7b] mes "16進ケタ数指定で..%5x :" + strf("[%5x]",a) ;[ 7b] mes "16進ケタ数指定で..%05x :"+ strf("[%0x]",a) ;[7b] mes "16進ケタ数指定で..%05X :"+ strf("[%0X]",a) ;[7B] a=sqrt(2)*(-1) mes "sqrt(2)*(-1)" mes "10進実数..%f :" + strf("[%f]",a) ;[-1.414214]小数桁数のデフォルトは6か mes "10進実数..%5.6f:" + strf("[%5.6f]",a) ;[-1.414214] mes "10進実数..%5.8f:" + strf("[%5.8f]",a) ;[-1.41421356]末尾桁は四捨五入か mes "10進実数..%e :" + strf("[%e]",a) ;[-1.414214e+000] mes "10進実数..%E :" + strf("[%E]",a) ;[-1.414214E+000] a=sqrt(111) mes "sqrt(111)" mes "10進実数..%e :" + strf("[%e]",a) ;[1.053565e+001] mes "10進実数..%E :" + strf("[%E]",a) ;[1.053565E+001] mes "10進実数..%g :" + strf("[%g]",a) ;[10.5357] mes "10進実数..%G :" + strf("[%G]",a) ;[10.5357] mes "10進実数..%G :" + strf("[%G04.5]",a) ;[10.535704.5] "04.5"は文字列だと。 mes "文字列で表示..%s:" + strf("[%s]",a) ;[10.535654]小数桁数のデフォルトは6か stop ;以下は後日の課題 ;3桁区切りカンマ形式 ;\記号編集形式 ;整数部は指定桁数で小数部も指定桁数という%dと%fのミックス形式 ;「+」を必ず付ける形式 ;日付/時刻の書式



ZAP

リンク

2013/5/23(Thu) 19:43:23|NO.54246

HSPはBASICの変異型だと思いますので、オブジェクト指向な言語しか触ってない人だと
いろいろと違和感があるんでしょうね。

自分はBASICから育った世代なので取っつきやすかったですけど。



woods57

リンク

2013/5/26(Sun) 23:24:17|NO.54336

5/19のy.tackさんの案である
文字列に詰め込んで1つにして返し、あとでばらして使うという方法
を試してみました。
結論は「NoGood」、理由は以下。

返却配列 = 配列で返したい関数(〜)
とか
返却配列 = パックされた文字列ばらし(配列で返したい関数(〜))
のように、返却配列はイコールの右側に書きたいのですが
返却配列 = xx, yy, zz
などと要素を所定の数だけカンマで展開するような方法は無さそうで
そうすると私の嫌いな「関数の引数に受取側配列を」渡さねば
そこに値を編集できないことになるのは少し考えれば
想像できそうなものでしたが
時間をかけたあとやっぱり無理かとあきらめることに。

プリプロセッサの段階で実行時の配列要素数のぶん記述するなんてできないし
実行時に記述の無効化/命令動的生成 ができないとxx,yy,zzは作れないか。

以下はテストですが
  パックされた文字列ばらし 返却配列配列 配列で返したい関数(〜)
というような形でしかできません。
こんな構文ではダメですね。並べりゃいいっいうもんじゃないです。
プログラムソースは暗号ではなくできるだけすなおに「読める」
ものであるべきですね。
「複数データの返却はモジュールで」しかないのかな。(TT)

#module #defcfunc ●配列を文字列パック化 array パックしたい配列 #define デリミタ "゙゚" SDim 返却パック 配列要素数 = length(パックしたい配列) 配列データ型 = vartype(パックしたい配列) 返却パック = str(配列データ型) + デリミタ + 配列要素数 + デリミタ Switch vartype(パックしたい配列) case 4 ;vartype("int") For I, 0, 配列要素数, 1 返却パック = 返却パック + str(パックしたい配列(I)) + デリミタ Next swbreak case 3 ;vartype("double") For I, 0, 配列要素数, 1 返却パック = 返却パック + str(パックしたい配列(I)) + デリミタ Next swbreak case 2 ;vartype("str") For I, 0, 配列要素数, 1 返却パック = 返却パック + パックしたい配列(I) + デリミタ Next swbreak default swend return 返却パック ;#defcfuncで開梱処理を作っても配列を返せないのだった・・・ ;で、やむを得ず#deffuncで処理する ; パラメータ1は複数データを最終的に受け取りたい配列名を ; パラメータ2は配列データを文字列型パックで返すdefcfunc型の関数呼び出し ; を記述すると想定するがテストは文字列パックデータとする #deffunc ●文字列パック開梱 array 返却配列, str 文字列パック ;#define デリミタ "゙゚" a文字列パック = 文字列パック split a文字列パック, デリミタ, 一時的事前定義しない配列 ;直接引数名をsplitに書くとエラー23 変数名が指定されていません のエラー 配列データ型 = int(一時的事前定義しない配列(0)) 配列要素数 = int(一時的事前定義しない配列(1)) If 配列要素数 > 0 { Switch 配列データ型 Case vartype("int") Repeat 配列要素数 ;「配列要素数 - 2」などとすると#Error21サポートされない機能を選択しました となる 返却配列(cnt) = int(一時的事前定義しない配列(2+cnt)) Loop swbreak Case vartype("double") Repeat 配列要素数 返却配列(cnt) = int(一時的事前定義しない配列(2+cnt)) Loop swbreak Case vartype("str") Repeat 配列要素数 返却配列(cnt) = 一時的事前定義しない配列(2+cnt) Loop swbreak Default Swend } return ;忘れるとループするぞ #global assert _debug screen 0,640,650,0 Dim 整数配列データ,5 整数配列データ = 11,22,33,44,55 パックした文字列 = ●配列を文字列パック化(整数配列データ) mes "パックした(1)=" + パックした文字列 ●文字列パック開梱 返却受取配列1,パックした文字列 foreach 返却受取配列1 mes 返却受取配列1(cnt) loop mes "パック開梱完(1)" assert _debug DDim 実数配列データ,5 実数配列データ = 11.1,22.2,33.3,44.4,55.5 パックした文字列 = ●配列を文字列パック化(実数配列データ) mes "パックした(2)=" + パックした文字列 ●文字列パック開梱 返却受取配列2,パックした文字列 foreach 返却受取配列2 mes 返却受取配列2(cnt) loop mes "パック開梱完(2)" assert _debug SDim 文字配列データ,1,7 文字配列データ = "日","月","火","水","木","金","土" パックした文字列 = ●配列を文字列パック化(文字配列データ) mes "パックした(3)=" + パックした文字列 ●文字列パック開梱 返却受取配列3,パックした文字列 foreach 返却受取配列3 mes 返却受取配列3(cnt) loop mes "パック開梱完(3)" stop
テストしている時、様々によくわからぬエラー出ますね、
経験積むとイライラ感は減るんだろうか、Perlと同じか、いやましかも。
1)defcfunc xx str A
split A,〜
と直接splitの第一引数に指定すると「変数名が指定されていない」のエラー
 意味わからんね。
B = A
split B,〜
として回避
2)Repeat 繰り返し回数 - 2
などと式を書くと「サポートされない機能を選択しました」となる
はいはい、式は書けないんですね (書けるとはマニュアルにはありませんけどね)
 式にする必要なかったんです。



woods57

リンク

2013/5/26(Sun) 23:38:46|NO.54337

書き損じました。
「以下はテストですが
 パックされた文字列ばらし 返却配列 配列で返したい関数(〜)
というような形でしかできません。」
です。



暇人

リンク

2013/5/26(Sun) 23:49:20|NO.54338

>はいはい、式は書けないんですね (書けるとはマニュアルにはありませんけどね)
式が書けないんじゃなく
文字列の式に-が使えないだけ(mes "10"-1 でも同じエラーがでる)
int(繰り返し回数)-2にすれば良い

後、Repeatに文字列で指定するとパラメータが違うと出る
計算が先にされるからサポートされてないと出るんだろう



あり

リンク

2013/5/27(Mon) 03:51:48|NO.54342

>1)defcfunc xx str A
>split A,〜
>と直接splitの第一引数に指定すると「変数名が指定されていない」のエラー

splitの解説を読むと第一引数には変数を指定するとあるので
defcfuncで受け取る引数は文字列(str)ではなく変数(var)である必要があります。


ちなみに引数に変数を渡して値を受け取るのは
HSP開発初期からそう記述する事を前提として設計・実装されている【正式な仕様】です。
(関数やモジュール、マクロは後に付け加えられた拡張文法で現時点では機能不足な点も多い)
ですのでたとえ嫌いだろうと他とは違うからダメだと言われても
それが現時点での正しい使い方なのですからそういうものだと受け入れられなければ
今後も仕様の差異によるストレスが苦痛であり続けるだけです。

それでも自分の使いやすいように試行錯誤を繰り返すというのなら
止めはしませんが、その経過報告で一々愚痴や恨み言と受け取られかねない
言葉を書き込めばそれを読んだ人はあまり気分が良いものではありませんし
それが繰り返されれば本人の意図とは関係ない無用な利用者間の衝突を招く
危険性を多分に孕んでしまうのだという事はご理解下さい。
(途中経過や不満を投稿するなという事ではなく言葉は慎重に選びましょうという事です



ZAP

リンク

2013/5/27(Mon) 07:04:31|NO.54344

作者の善意でご提供頂いている言語ですからね。
自分の流儀に合わないからと言って逐一不満をこぼす(ように見えるような書き込みをする)
のもどうかと思いますよ。

改善要望があるならば簡潔にまとめて作者に提言すべきかと。



KA

リンク

2013/5/27(Mon) 11:47:21|NO.54352

最初の方で
------------------------------
初心者が、いきなり難しい事をしようと思っても、それま無理でしょう。
>>私は日ごろの仕事ではExcelと関数とVBAを使う
それを覚えた方法と比較して下さい。
------------------------------
と、書いたのに反応なし。

あくまで、自分の知識との比較に終始しているようにも見えます。
マニュアルは細かく見ているが、応用出来ない感じも受けます。

「簡単だと聞いて連休で覚えようとしたが、いきなり難しい所から
やったので覚えられなかった。何ナノこれ」という心理状態が見え
隠れしている気もします。



woods57

リンク

2013/5/29(Wed) 01:08:53|NO.54403

NO.54336の発言について非難されているようです。
「雑談」トピックだから問題点を指摘してくださいと言う訳でも
ないが、初心者が悩んでいるメインのテーマについてのアドバイスは無く
枝葉の部分について指摘され(教えられ)たことに端を発し、乗じて
エスカレートさせているようだ。またはこれまでに溜まった不愉快感を
解消するのは今だとまくしたてたと。経験者を自負するならメインテーマ
にコメントしてくれないの?自負しないのなら横ヤリ入れるな。
私にはNO.54336が不満たらたらいいながら無目的に作業していると見えることが
信じられん。他人の感覚は千差万別だからどう取っても自由なのだが。
=======
自分の書きたいように作り、感じたままに発言する
それがいいんじゃないのか。

それを読んで仮に不満なら、「不愉快だ〜」と言えばいいんじゃないのか。

冷静を装って説教したり、初心者が・・と喧嘩を吹っ掛けたりするのが
幼稚だ。

HSP大好きで気に入ってるAが、HSPのここが嫌いというBを嫌いというのは
可愛がってる愛犬がぶさいくだと言われた飼い主の気分だということは
想像できる。

2件についてHSPの仕様がそうなんだからと説明されても
それが変でしょとまだ考えているが、
あなたの発言が衝突を招くなどと脅しのような発言は、そりゃ全く違うだろ。

プログラムが少々書けるようになったといっても人格や判断力、包容力その他の人徳が
比例して高まるという訳ではありません。勘違いしないでね。

HSP右派に言ったつもりもないが、掲示板だからねえ、しかたがないのか
万人に受け入れられる発言をという気はないしできない。

私は、screen命令の第4パラメータから勉強を再開したいと思います。
第2、3パラメータの勉強をしていての「雑談」トピックとして投稿しましたが
タイトルと違う方向に行きましたが
いろいろ教えていただき勉強になりました、ありがとうございました。
私もその意図を汲み取ろうと努力しました。
しばらくさようなら。
HSPの、他の言語に無い良い点というのももちろん持っています。
キーワードは「デッドロック」ですが多分発言することはないでしょう。
HSPに対する要望は数件出しています。しかしこんなこと言う必要もないことやね。



閲覧者

リンク

2013/5/29(Wed) 03:32:19|NO.54404

本筋の議論とは異なる内容のため興味なければ読まなくて結構.

検索エンジンにかければすぐ解決するような小中学生の質問が多い中で,
HSP歴が長い方々でも試行錯誤が必要な議論ということで興味深く見てきたが,
結局いったい何がしたかったのか.


プログラムの書き方などそれぞれの言語での文化的な側面があるわけだから,
相手方のコミュニティで相手の文化を否定すれば反感を買ってもそれは仕方ないだろう.

この方法ではできなかった,どうすればよいか,と聞くだけなら,問題に対する共感は
得られずとも解決に向けたアドバイスはもらえるはずだし,実際にアイデアは出ていた.
そもそもここのユーザは引数に変数を入れて結果を受け取ることに抵抗がないから,
あなたが持つ問題を解決しても大したメリットは感じない.
そこをいちいち,仕様がおかしいだのマニュアルが不親切だの書くから周囲が不愉快になる.
万人に受け入れられる必要はないかもしれないが無用な反発を防ぐくらいはしてもよいのではないか.


言語の穴をつく書き方が必ずしも悪いとは思わないが,自身でも初心者と称する段階で
見た目にしか影響しない部分にこだわるのは頭が固すぎないか.
過去で扱った他言語の(曰く数少ない)経験にとらわれすぎているように思える.

さらにはそこまでHSPの仕様を変だ変だといいながらなぜHSPを使おうとするのか理解に苦しむ.
HSPを使えるようになりたいというのであれば,構文規則を否定する前にまずは一通り使って見れば良い.
数十行程度の規模でソースの見た目が原因で致命的な状況に陥るとは思えない.
大規模なシステムを作るころには慣れて気にならないかもしれないし,
まだ気になるというのであればその時に考えれば良い.
HSPに対する理解も今よりは深まり解決への道筋も見つけやすくなっているはずである.
あなたがHSPの仕様を受け入れるということも,消極的ながら解決法の一つであることは理解いただきたい.



ZAP

リンク

2013/5/29(Wed) 08:07:27|NO.54405

他の方も書いていますが、主張の内容もさることながら、
言葉の選び方の問題だと思います。

飲み屋で愚痴るオッサンみたいで、端で聞いていても気持ちの良いモンじゃありません。
残念ながら。



f(現場前)

リンク

2013/5/29(Wed) 09:40:27|NO.54406

ありゃ?
結局こうなったのか。

で、結局自己弁護だけして去っちゃったのか・・・



しばらく前にも感じたことがあるが、やっぱり、どこかに

「珍妙な内容でスレッド立ててHSP掲示板住人を釣ろうずwww」

とか言うスレッド建ってねえ?



KA

リンク

2013/5/29(Wed) 09:55:40|NO.54407

>>「雑談」トピックだから問題点を指摘してくださいと言う訳でも
>>ないが、初心者が悩んでいるメインのテーマについてのアドバイスは無く

そもそも、なぜ「雑談」にしたのか意図不明。
「雑談」だから、何を回答しようが問題なし。



晩御飯

リンク

2013/5/29(Wed) 20:22:48|NO.54409

いろんな意味で大型新人だった



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