stuncloud / UWSCR

UWSC互換スクリプト実行ツール
MIT License
50 stars 5 forks source link

BoolのTrue/Falseはファイルに書き出すと文字列の"True"/”False”に変わってしまう。 #169

Open DIYJii opened 4 months ago

DIYJii commented 4 months ago

概要

表題通り

UWSC では BoolのTrue/False は 1/0 に変換されてファイルに書かれているので、 再読み込みしたものは、そのままでTrue/Falseの働きをする。

再現スクリプト

No response

再現手順

No response

バージョン

1.0.1

不具合発生環境

Windows 10

stuncloud commented 4 months ago

UWSCにおいてはVARIANT絡みの動作であると思われるが詳細は不明

UWSCRにおいてはfputの第二引数が文字列を受けるため、Object::Bool(b)bにより"True"または"False"という文字列に変換される これを単に"1"または"0"と変換するように変更した場合、"true" == TRUE の等式が成立しなくなるなどの弊害があるため、std::fmt::Displayの実装は現状維持としておきたい

ひとまずfputの引数でのみ"1"または"0"と変換するのが妥当か 他の関数で同様の変換が必要になことが発覚した場合は都度対応とする

cocco84 commented 4 months ago

文字列想定のところに真偽値を入れるとどうなるか?なのかなと思いましたので比較してみた結果です。 なかなか試す機会もないですが、、ご参考までです。

print pos(1, True)     //UWSCR:0 UWSC:1
print pos(0, False)    //UWSCR:0 UWSC:1
print pos("1", True)      //UWSCR:0 UWSC:1
print pos("0", False)     //UWSCR:0 UWSC:1
print pos("True", True)   //UWSCR:1 UWSC:0
print pos("False", False) //UWSCR:1 UWSC:0
print copy(True, 1)    //UWSCR:True  UWSC:1
print copy(False, 1)   //UWSCR:False UWSC:0
print replace(True, "1", "2")    //UWSCR:True UWSC:2
print replace(True, 1, "2")      //URSCR:True UWSC:2
print replace(True, "True", "2") //UWSCR:2 UWSC:1
print replace(True, True, "2")   //URSCR:2 UWSC:2
stuncloud commented 4 months ago

再読み込みしたものは、そのままでTrue/Falseの働きをする。

issue作成者のこの書き込みは条件式を想定したものだと思われるが、この修正を行ってもUWSCRではこのように動作しない "0"や"1"は長さ1以上の文字列であり条件式においては真であるため

stuncloud commented 4 months ago

関連: #171

DIYJii commented 4 months ago

新しく

「BoolのTrue/Falseはクリップ・ボードに書き出すと文字列の"True"/”False”に変わってしまう。」

を別途Issueを立てるかどうか、迷ってます。 ファイルもクリップ・ボードもアプリ間のパラメーターやデータの橋渡しに使う事が有るので、 両方まとめてここで扱うのもありかなとも思いますし・・・

cocco84さん、スッキリと分かり易い対比表、ありがとうございます。

stuncloud commented 4 months ago

「BoolのTrue/Falseはクリップ・ボードに書き出すと文字列の"True"/”False”に変わってしまう。」

を別途Issueを立てるかどうか、迷ってます。

実装的には同一内容となるのでここで良いと思います

sendstrを含め 文字列を受ける引数 はすべてその様に変換されるのが現在の仕様です 引数が要求する型についてはドキュメントに記載されています それ以外にも暗黙の型変換で文字列にされる場合にもこの変換が行われます

// 暗黙の型変換の例
print "abc" + TRUE // abcTrue

ファイルもクリップ・ボードもアプリ間のパラメーターやデータの橋渡しに使う事が有るので、

そのような用途であれば"True""False"といった文字列のままであったほうがeval関数でTRUE, FALSE が得られるため"0""1"になるよりも良いと考えることもできますが、どうでしょうか

仮にファイルやクリップボードに書き込まれた"0""1"を読み取ったとして、それをそのままifの条件式に当ててしまうといずれも真になるのは #171 で示した通りです

また、UWSCであっても真偽値が"0""1"として書き込まれるからといって、読み出しで期待するものが"0""1"であるのならば、安全のためにTRUEFALSEではなく10として書き込むほうがコードとしては良いと考えます

[!TIP] もっと安全にするならjson文字列を使うという手もあります 僕がUWSCでファイルなど文字列情報を経由する場合はjsonを使っていました UWSCではjsonオブジェクトの扱いがやや面倒でしたがUWSCRでは標準サポートです

なお、UWSCにおける真偽値から文字列へのVARIANT変換は以下のようになっています

print vartype(TRUE, VAR_USTR) // True
print vartype(TRUE, VAR_ASTR) // True

print vartype(FALSE, VAR_USTR) // False
print vartype(FALSE, VAR_ASTR) // False

なので、UWSCがなぜ文字列引数において真偽値を数値にしているのかは不明です

@cocco84 さんの調査結果を見るにUWSCでは文字列引数での真偽値は一律0または1になると考えても良いのかしら

修正の是非について

個人的にはかなり悩みどころで、これをやっても #171 があるためそちらを解決しない限りこちらを修正する動機が弱いんですよね やるとしたら文字列引数で真偽値は0か1に変換するということになるとは思いますが、その影響がどれほどあるのか計り知れないことも懸念点となります

どうしましょうね

DIYJii commented 4 months ago

考慮すべき点は2点

  1. "True"/"False"方式か"1"/"0"方式か   2. 真偽性評価を導入したことによる不都合 

1.については、cocco84さんの調査も合わせて考えると、UWSCRの"True"/"False"方式だと、UWSCユーザーにとっては変更点が多すぎるので、"1"/"0"方式の方が良いと思います。そんな使い方するのかと、思われるかもしれませんが、ユーザーは何でも自分の目的に合った事をしてくれる物が有れば、本来の目的に合わなくてもそれを利用します。これをするには、あなたの方に大きな負担が掛かりますが、正直言ってcocco84さんの調査結果では、UWSCの戻り値の方がすんなり腑に落ちる感じですので、今の内に手を打っておかないと、何時までもユーザーからの質問やクレームに対応する羽目になり、かえってコスト高になります。

2.については、"0"も”False”も文字列なのでTrueになって困るわけですが、新しい真偽性評価を使いたい人は其れなりに覚悟してコーディングするはずなので今のままの仕様で心配ないと思います。しかし、まだ慣れないUWSCユーザーやUWSCから移行する人にとっては、真偽性評価はかえって困る訳ですから、UWSCと同じ仕様の If 関数に戻して欲しいわけです。 ということで、今のOPTION ForceBoolを止めて ForceUWSCIf とか言う名の、UWSCと同じ仕様のIf関数が使える新しいOPTIONを作ってもらえれば良いのではないでしょうか?

ただ、これは、私個人の意見ですので、もっと広くユーザーの意見を求めるべきと思います。可成り、基本の部分の話ですので、色々な人の多彩な使い方の違いが関係してきますので。 それと、あなたはUWSCRのオーナーですから、ご自分の方針に従って最終決定をすればよい訳で、あくまで1ユーザーの意見として聞いておいて下さい。

p.s. マニュアルの真偽判定に「UWSCRとの違い」とあるのは、「UWSCとの違い」の様に思いますが・・・

stuncloud commented 4 months ago

この件についての対応はやってやれないことはないんですが、僕が一番引っかかっている点はUWSCにおいて

ことです またこの仕様は明文化されておらず、どのような状況でどちらが採択されるかはコードを実行してみないとわかりません 僕としては、このような仕様はなくしたいと考えています つまり、True/Falseか1/0のいずれかで統一したいというわけです

以前の議論にもあったEMPTYと空文字の比較でもそうですが、一つの状態から複数の結果が生じるのがプログラミング言語としては望ましくないわけですね、しかも今回の件は見えないところで生じる副作用ですから余計にたちが悪いと言えます

というわけで、現行仕様のままにしておきたいのが本音です

ということで、今のOPTION ForceBoolを止めて ForceUWSCIf とか言う名の、UWSCと同じ仕様のIf関数が使える新しいOPTIONを作ってもらえれば良いのではないでしょうか?

それに関してはむしろFORCEBOOLを使ってより安全なコードを書くようにしてもらったほうが良いですよね

あと、仮にForceUWSCIfを実装したとしてもFORCEBOOLをなくす必要はないでしょう、FORCEBOOLの導入経緯についてはお話していたと思いますけどコードの安全のためですから必要です

まあでもUWSCのような条件式の判定にするためのオプションはあっても良いかもしれませんね (再現性を高めるためにVARIANT変換をすることになるのでその分速度が犠牲となりますけど) これは別issueでお願いします

そして、改めて忠告させていただきますがif関数というものはないので、それだけはいい加減覚えてください…

もっと広くユーザーの意見を求めるべきと思います。

それができればしたいんですけどね discordもほぼ機能してないのでなかなか難しいです やり取りの中でお気づきかもしれませんが僕の性質がひどい有り様なので求心力なんかがまるでないんですよ

p.s. マニュアルの真偽判定に「UWSCRとの違い」とあるのは、「UWSCとの違い」の様に思いますが・・・

わあ、これはとんだ誤字でしたね…気付きませんでした なるべく早めに修正しておきます


あと一点だけ もしかしてなんですが @DIYJii さんは本件とif等の条件式についてが切り離せていないのではないか?と感じています これらは全く別の話なのでこのissueでは分けて考えてください ここでは真偽値の文字列変換についてのみフォーカスさせてください

stuncloud commented 4 months ago

ドキュメントの誤字を修正しました ドキュメントに関する問題報告もissueを立ててもらってOKです その際は documentation ラベルをつけてください 近い内にissueテンプレートを準備します

DIYJii commented 4 months ago

総合的に考えて矛盾のない解決策を探すとなると、どうしても関連のある話題も取り込む事に成るので、私の話はいつもこんな風になります。すんません。

はい、真偽値の文字列変換に集中します。

調べたところ、ファイルやクリップ・ボードにUWSCが書き出したものは、True/False, 1/0 ,"1"/"0" の全てが、UWSCRで受け取ってみると "1"/"0", Length = 1, TYPE_STRING でした。考えてみれば、ファイルやクリップ・ボード上ではTYPE_STRINGしか存在し得ないですよね。 その上で考て、"1"/"0"か"True"/"False"かの選択となれば、"1"/"0"の方が、そのままでも再読み込みしても元の意味を失わないし、短いデータになるので、"1"/"0"の方が良いと私的には思います。 ま、今のままで、ドキュメントで説明しておけば良いのかもしれませんが。私の方は現状に合わせてコーディングし直してありますので、気にしないで良いです。

いっそのこと、 ForceUWSCIf ではなく、割り切って UWSCMode というOPTION を作ってこの件と#171の件は、UWSCに合わせた仕様で動くというのはどうでしょう。他にも、そのようなものがあれば、ここに加える事も良いと思いますし。このまま、妥協点を見つける努力を続けるのはしんどいのではないでしょうか?

171で議論すべきですが、いっそのこと"True"/"False"は文字列の働きしか出来ないとしたら、どんな問題が発生するのか、今、私なりに考え中です。

別の話ですが、さきに話題になったユーザーの声云々など、全般的な事を議論できるコーナーが有ればなとも思いますが。

cocco84 commented 4 months ago

幅広い意見とありましたので一人でも多いほうが良いのかと考えますので意見を。 UWSCRは既にUWSCと完全互換という訳ではありませんし、 ドキュメントに記載さえあればUWSCと全く同じ結果を得られなくても良いと思っています。

同じ結果を得たければUWSCを使用すれば良いですし、 UWSCRで拡張された機能を使用したければそれに応じたコードに手直しするべきと感じます。

私の考えとしてはこれまでの移行で不便を感じた事もありませんので、 仕様の変更は不要ではないかという結論です。

UWSCと同じ結果を得られたいのであればユーザー側でどうとでもできるとは思います。

かなり乱暴ですが新たなIf文やオプションを実装しなくても @DIYjii さんがお求めの事であれば以下で実現出来るような気もしますがいかがでしょうか。

print UWSCBoolean("false") //0
print UWSCBoolean(FALSE)   //0
print UWSCBoolean("0")     //0
print UWSCBoolean(0)       //0
print UWSCBoolean("")      //0
print UWSCBoolean("empty") //0
print UWSCBoolean(EMPTY)   //0
print UWSCBoolean("null")  //0
print UWSCBoolean(NULL)    //0
print UWSCBoolean("true")  //1
print UWSCBoolean(TRUE)    //1
print UWSCBoolean("1")     //1
print UWSCBoolean(1)       //1
print UWSCBoolean("hoge")  //エラー

function UWSCBoolean(v)
    select TRUE
        case "" + v = "FALSE", "" + v = "0", "" + v = "", "" + v = "EMPTY", "" + v = "NULL", v = NULL
            result = 0
        case "" + v = "TRUE", "" + v = "1"
            result = 1
        default
            //- raise("真偽値ではない")
            result = v
    selend
fend

if文の条件式に UWSCBoolean(v) を使うイメージです。

@stuncloudさん ついでにご質問させください。

"" + EMPTY"" + "" の扱いですか? ドキュメントからだと"" + "EMPTY"なのかなと思った次第です。

stuncloud commented 4 months ago

@cocco84

"" + EMPTYは "" + "" の扱いですか?

その通りです 文字列との加算なので右辺のEMPTYは暗黙の型変換が行われ文字列となり、""となります

ドキュメントからだと"" + "EMPTY"なのかなと思った次第です。

そのように読み取れる箇所がありましたでしょうか ドキュメントを修正します

cocco84 commented 4 months ago

@stuncloud 私の勘違いですね。 EMPTYが暗黙の型変換で文字列になった場合は"EMPTY"ではなく""なんですね。 よく考えたら当たり前ですね、失礼しました。

・文字列 + その他の値 上記例以外の値型はすべて文字列として扱われます

とあったのでそこだけ読んで勝手に"EMPTY"になるのかと思ってしまっていました。

DIYJii commented 4 months ago

@cocco84さん、UWSCBoolean( )の提案ありがとうございます。でも、私のコードは@stuncloudさんに教えられてevalを使う事にしましたので、大丈夫です。 ここの首題の、ファイル/クリップ・ボードに書き出す値を "1"/"0" か "True"/"False" どちらを選ぶか?についてのご意見はどうですか?

私が、UWSCRに移行したのは、今、開発半ばのアプリでは出来ないUWSC以上の機能を取り入れたかったのと、いつWindowsのアップデートでUWSCが使えなくなるかもしれないとの心配からです。 ただ、私は、レベルが低いせいで、Javaレベルの話にはなかなかついて行けず、色々皆さんにご迷惑を掛けていますが、ご容赦の程を。

ところで、 「どうせ完全互換性がないのだから」、みたいな宣言をしてしまうと、下の文章は矛盾しますし、誰もBugレポートを上げて来なくなるのではないでしょうか?

issue種別の選び方  以下の場合はバグ報告のissueを作成してください

 UWSCと異なる結果を返す

cocco84 commented 4 months ago

@DIYJii

sendstr(0, false)
print getstr(0)  //UWSCR:False UWSC:0

sendstr(0, UWSCBoolean(false))
print getstr(0)  //UWSCR:0 UWSC:0

私の見解についてはどうしてもUWSCと同じ結果を得たいのであれば ユーザー側で上記のようにすればよいのではないか?という事です。 fputについても同様ですね。

ですので現状のUWSCRの仕様のまま変更なしで良いのではないかという意見です。

stuncloud commented 4 months ago

@DIYJii

ところで、 「どうせ完全互換性がないのだから」、みたいな宣言をしてしまうと、下の文章は矛盾しますし、誰もBugレポートを上げて来なくなるのではないでしょうか?

issue種別の選び方  以下の場合はバグ報告のissueを作成してください

 UWSCと異なる結果を返す

それはissue作成の指針ですから、そのような場合にユーザーはひとまずそれをバグと判断してください、という話です そこから、それは仕様であるとか、バグなので修正するといった対応を僕がするわけです 開発の方針とは別の話なのでそこに矛盾はありません

完全互換ではないという話は例えばgetitemの戻り値であるとか、UWSCの仕様が不便であるがゆえにUWSCから見れば破壊的変更を行ってるものがすでにあるわけで、そこは許容してもらうしかないですよね、という意味でおっしゃられていたのだと思いますけど

もしも今後、getitemの戻り値を数値に戻してALL_ITEM_LISTに結果を入れるようにしてくれ、というリクエストがあってもそこはもう完全に拒否しますし、なにもかもUWSCとは同じにはならないです

chkimgなんて戻り値どころか引数すら異なるまったくの別物ですけど、今のところそれに関してなにか言われたということはないですね


UWSCRはソースを公開していますしライセンスもMITであるので、それを @DIYJii さんまたは第三者が改変することができるようになっています つまり、それを元にUWSC完全互換の別ソフトとしてリリースすることも自由というわけです 僕としてはUWSCと完全に同じでないことが受け入れられないという方に対してはどうにもできませんので、そういう選択もあるということは覚えておいてください

DIYJii commented 4 months ago

分かりました。 UWSCは有料のPro版を出していた事と、UWSCR はUWSCの後継ソフトと言う理解で、 何となく、UWSCRが、ベンダー・ソフトと同じようにBackward Compatibilityを持つ事等を強く期待していました。 それと、現役時代の経験から、お客様に提供する製品やサービスのあるべき姿をイメージしながら色々発言していました。

しかし今、ネットでオープン・ソフトの勉強をしてみて、今迄私の勝手な妄想で、色々過度な要求をしていた事に気付きました。 基本的に、この世界は、作り手がフリーに使える製品を提供し、使う側は自分にあった製品を自由に使わせて貰えるという中で、 作り手側に何か強く要求するのはあり得ない、ユーザーはBugでもない限り As is で使うのが基本、製品に足りない部分は、 自分なり工夫して使うという事に気付きました。

あなたには、色々無理な要求をして、不愉快な思いをさせてきた事を、心からお詫びします。

@cocco84さん、あなたの返事も、私の理解を正すのに役立ちました。有難うございました。

このIssueは、私はこれでCloseで結構です。

stuncloud commented 4 months ago

UWSCのソースコードが手元にあったならば完全再現を考えていたかもしれませんが、残念ながらそうではありませんでした UWSCのすべての機能において

  1. 実際に動かし
  2. 仕様を予想し
  3. 予想に基づいた実装を行い
  4. 動作を比較し
  5. これらをうまくいくまで繰り返す

ということをやっています 機能が10や20なら良かったのですが、UWSCはとにかく笑っちゃうくらいには多機能だったわけです おかげでここまで3年以上かかっています

外からでは何が起きてるか全くわからない機能も多かったです 機能によって必要な知識も様々であり、ほとんどにおいて一から学び実装することを余儀なくされました umiumi氏の博識さに感服すると共にちょっと恨んだものです、なんてものを作ってくれたんだ!と

とまあ、そんな具合でしたから完全互換という浅はかな希望は最初から捨てていました 動きを寄せることはできても、UWSCの実装はブラックボックスなのですから

条件式やら暗黙の文字列変換やらは、言語機能のベーシックな部分なのでそれこそ最初の実装は3年前になります 実をいうとUWSCがif等で数値変換を経て条件を判定することに気付いたのは @DIYJii さんとのやり取りからで、3年間気付けなかったし他のユーザーからの指摘もありませんでした しかし、ベーシックな機能ゆえに根深い部分であるからこそおいそれと手を入れにくくなってしまったわけです 3年前に気付いていればもう少しうまくやれてたかもしれないのですが、過ぎたことなのでせんなしですね

DIYJii commented 4 months ago

そうですか、随分苦労して来たのですね。それも知らず、ガンガンやっちゃって。 ほんまに、スンマセン。 私の報告の事、そんなに言ってもらって、少し救われました。 アリガトウ。 また、頑張りましょう。応援しています。