以下は、問題を解決するためにJSL Debuggerを使用するケーススタディです。これは、問題が特定されている実際のスクリプトに基づいています。あなたが文脈の中で問題を見たいと思うならば、私はスクリプトを作成しました - オリジナルからずっと単純化された - それは問題を示す。あなたが「一緒に遊ぶ」ことをご希望の場合は、ダウンロードすることができます DebuggerDemo-SolvingProblems.jsl JMP File Exchangeから(ダウンロードには無料のSASプロファイルが必要です)。
私はオリジナルのスクリプトを説明していますが、コードスニペットと写真はすべてこのサンプルスクリプトからのものです。一緒に従ってください!
問題
先日、スクリプトに問題があるJSLスクリプト作成者が私に助けを求めました。彼女のスクリプトは英語で正常に実行されましたが、簡体字中国語でスクリプトを実行しているテスターはエラーを受け取りました。
問題は文字列が英語対中国語で扱われていた方法にあるように思われました:具体的に、エスケープ引用符( 」 )除外されていました。
英語では、これは構築されたサンプル文字列です:
"dt <<場所を選択(dt:Numbers == 45&dt:ピック文字列== \!" South \!")"
中国語では、文字列は次のようになりました。
"dt <<場所を選択(dt:Numbers == 45&dt:Pick Strings == South)"
行方不明に注意してください \!"... \!" まわり南これは、文字列が解析されたときにエラーが発生し、その引用符で囲まれていない値を解決できませんでした。
英語以外の言語で文字列内の引用符を処理するときにJMPにバグがありましたか?
初見
彼女はスクリプトとそれを実行するのに必要なデータを私に送ってくれました。このスクリプトは900行に満たず、インタラクティブなレポートを作成しました。最初の130行がセットアップされ、131〜886行で式が定義され、それから残りのスクリプトではそれらの式が使用されました。
私が最初にしたことは、私が同じ問題を抱えているかどうかを確かめるために、英語で、次に中国語でスクリプトを実行することでした。やった。それから私はフランス語でそれを走らせました、そしてそれは問題が中国語だけでなく英語以外のどんな言語にもあることを確認しました。残りのテストは英語とフランス語で実行しました。フランス語は中国語よりも読みやすいからです。
先端: Windows上でJMPを実行している言語を切り替えるのは簡単です。[ファイル]> [設定]を選択し、[Windows固有]カテゴリを選択します。上部の[表示言語]で言語を選択します。Macintoshの場合は、最初にJMPを終了してから(アップルメニューの)「システム環境設定」を開き、「言語とテキスト」カテゴリを選択します。新しい言語をリストの一番上にドラッグします。このウィンドウを閉じないでください。それはあなたのコンピュータの言語を設定します。JMPを起動すると、リストの最初の言語で実行されます。終了したら、JMPを終了し、英語(または通常コンピュータで使用している任意の言語)を一番上にドラッグします。システム環境設定ウィンドウを閉じても安全です。
上記の文字列を構成する行はいくつかありましたが、それらはすべて1行ずつ実行し、複数の式を入力および終了し、私が見ていたものを理解するのは困難で時間がかかりました。
適切な文字列構築行だけを実行すると(スクリプトがこれらの変数をすべて初期化するために1回実行された後)、エスケープされた引用符が正しく使用され、同じ結果がすべての言語で得られました。しかし、文字列を構成する行は、2つのデータテーブルの値と、最初の2つから作成された3つ目の値を使用しています。
つまり、これはJSLデバッガの仕事でした。
JSLデバッガに入る
JMPを英語で実行しているときに、スクリプトを開いて[デバッグ]をクリックしました。私はすでにスクリプトを実行していたので、その変数はすべてグローバルの下にリストされていました。そしてそれらの多くがありました - 私が台本を通って動いたので追跡するには多すぎます。(私はこれを実行してこれを発見した可能性がありますグローバルを表示 () ログを見るのはとても長くなります。)
それが私が知っている必要があるすべてだったので、私は自分の環境が完全にクリーンになるようにJSL Debuggerを終了し、JMPを終了して再起動しました。スクリプトを開き、デバッガをもう一度起動しました。
私は構築されている文字列だけに興味があったので、私はその変数をウォッチリストに追加しました。そのためには、JSLデバッガに示されているようにスクリプト内で変数を選択し、右クリックして[ウォッチの追加]を選択しました。

セットアップ部分が終了した後の最初の行(最初の行131、私の例の行34)にブレークポイントを追加し、すべての式を作成した後の最初の「実際の」命令行に別のブレークポイントを追加しました。オリジナル、これは私のサンプルにはありません)。そのために、デバッガに表示されているスクリプトの行番号の横にあるをクリックしました。

先端: ブレークポイントは、何らかのアクションを実行する行に配置した場合にのみ機能します。空白行、閉じ括弧のみを含む行、またはコメントアウトされている行のブレークポイントは無視されます。
最初の "setup"部分を実行したところ、私の文字列変数はまだ作成されていないことがわかりました。私はワンクリックでそのことを学びました - スクリプトを手動で1行ずつ実行するよりもはるかに速いのです。
2番目の部分は、すべての式を単純に作成したものです。
今こそ行動の時でした。
脚本の「肉」は、元の脚本の下部にわずか10行で収められていました。最初の部分は、2つの式(これは、式と呼ばれる、式と呼ばれるなど)を呼び出すループでした。何が起こっているのかを調べるために、各表現にステップインするためにステップインボタンを使用しました。
先端: 式、ユーザー定義関数、または含める () が呼び出され、そのコード全体を実行し、結果を返し、実行ポイントを次の行に配置します。1行ずつ進む必要がない場合、これは不要なものをスキップするための迅速な方法です。その一方で、式、関数、またはインクルードされたスクリプトが何をしているのかを正確に把握する必要がある場合もあります。代わりに[ステップイン]を使用すると、そのコードを1行ずつステップスルーできます。
結果
私が発見したのは、弦の各部分は、もし () 式:情報を含む列が文字の場合、値はエスケープ引用符で引用されています。それ以外の場合、値は引用符で囲まれていません。
これはまた、ほぼ900行のコードのうち、19行の小さな部分にしか興味がないということを意味しました(それにもかかわらず、他の800行に依存していました)。これらの行は、私のサンプルの38行目から54行目で再作成(および簡略化)されています。
私はJMPをフランス語で実行するように変更し、終了して再起動し、そして再びデバッガを通過しました。
突然、すべてが明らかになった...
JMPはローカライズされています!(誰かわかったね?)
問題は、文字列を作成した割り当てにはありませんでした。私がすぐにデバッガで見た問題はフランス語では、内の条件ですもし () 列が文字であるかどうかを判別する式ではないキャラクター。文字列の場合、スクリプトはフランス語とフランス語で異なるコードポイントを実行しました。
実際には、フランス語の条件は常に戻ります 0 。のコンディションピースもし () 式はこれです(私のサンプルでは40行目と48行目)。
解析する ( "dt:" || ColumnNames [ thisCol ] ) << データ型を取得 () == "キャラクター"
英語で、コル << データ型を取得 () 戻る "キャラクター" 文字列の場合 フランス語で、それは戻ります 「カラテール」 と等しいと評価されることはありません "キャラクター" 。
コル << データ型を取得 () ローカライズされた回答を常に返します。
問題の列が次の値と等しいと判断されることはありません。 "キャラクター" 中国語(またはフランス語、またはJMPがサポートする英語以外の言語)で実行した場合、文字列はセル値が数値であるかのように構成されました。それが、英語の文字列が引用符をエスケープし、中国語の文字列がエスケープしなかった理由です。
注意: JSLデバッガは、の結果を表示しませんが。 << データ型を取得 () メッセージ - 比較の結果だけ - デバッガを簡単に終了し、選択して実行することができます解析する ( "dt:" || ColumnNames [ thisCol ] ) << データ型を取得 () 実際に返された内容を確認する デバッガによって、問題を素早く簡単に見つけることができました。
アクションの呼び出し
JMPにバグはありません。これは設計どおりに機能しています。このスクリプトは、どの言語でも動作するためにわずかな変更のみが必要です。
スクリプトを言語を超えて使いやすくするためのアプローチは複数あります。あなたならどうしますか?私たちが取ったアプローチを1〜2週間でコメントに追加します。