WB(質問に答えるのに実際には必要ありません)は別として、問題は、割り当て中に式がどのように評価されるかにのみ基づいて、簡単な答えを持っているようです。次に例を示します:
In[1505]:=
notGoodQ[x_]:=True;
Clear[g];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
In[1509]:= g/:cccQ[g[x0_]]:=True
During evaluation of In[1509]:= g::nogood: -- Message text not found -- (x0_)
Out[1509]= $Aborted
それを機能させるために、私は意図的にnotGoodQ
の定義を作成しました 常にTrue
を返す 。さて、なぜg[x0_]
TagSetDelayed
による割り当て中に評価されます ?答えは、TagSetDelayed
(およびSetDelayed
)割り当てh/:f[h[elem1,...,elemn]]:=...
f
のルールは適用されません 持っている可能性がありますが、h[elem1,...,elem2]
を評価します 、およびf
。次に例を示します:
In[1513]:=
ClearAll[h,f];
h[___]:=Print["Evaluated"];
In[1515]:= h/:f[h[1,2]]:=3
During evaluation of In[1515]:= Evaluated
During evaluation of In[1515]:= TagSetDelayed::tagnf: Tag h not found in f[Null]. >>
Out[1515]= $Failed
TagSetDelayed
という事実 HoldAll
です 引数を評価しないという意味ではありません。引数が未評価で到着することを意味するだけであり、評価されるかどうかはTagSetDelayed
のセマンティクスに依存します。 (これについては上記で簡単に説明しました)。 SetDelayed
についても同じことが言えます したがって、「引数を評価しない」という一般的に使用されるステートメントは、文字通り正しくありません。より正しいステートメントは、評価されていない引数を受け取り、特別な方法でそれらを評価することです-r.h.sを評価しませんが、l.h.s。の場合、ヘッドと要素を評価しますが、ヘッドのルールは適用しません。これを回避するには、HoldPattern
でラップすることができます。 、このように:
Clear[g,notGoodQ];
notGoodQ[x_]:=EvenQ[x];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
g/:cccQ[HoldPattern[g[x0_]]]:=True;
これは通過します。使用法は次のとおりです:
In[1527]:= cccQ[g[1]]
Out[1527]= True
In[1528]:= cccQ[g[2]]
During evaluation of In[1528]:= g::nogood: -- Message text not found -- (2)
Out[1528]= $Aborted
ただし、HoldPattern
の必要性に注意してください 定義を作成するときの左側の内側は、多くの場合、関数呼び出し中に頭の中の式も評価される可能性があり、コードが破損する可能性があることを示しています。これが私の言いたいことの例です:
In[1532]:=
ClearAll[f,h];
f[x_]:=x^2;
f/:h[HoldPattern[f[y_]]]:=y^4;
このコードは、h[f[something]]
のようなケースをキャッチしようとします 、ただし、f[something]
なので、明らかに失敗します。 評価がh
になる前に評価します :
In[1535]:= h[f[5]]
Out[1535]= h[25]
私にとって、HoldPattern
の必要性 l.h.s.自分のデザインを再考する必要がある兆候です。
編集
WBでのロード中のデバッグに関して、実行できることの1つ(IIRC、現在チェックできません)は、古き良き印刷ステートメントを使用することです。その出力はWBのコンソールに表示されます。個人的には、この目的のためにデバッガーの必要性を感じることはめったにありません(ロード時にパッケージをデバッグする)
編集2
質問の編集に応じて:
定義の順序について:はい、これを行うことができ、この特定の問題を解決します。しかし、一般的に、これは堅牢ではなく、私はそれを良い一般的な方法とは見なしません。状況から少し外れているため、当面のケースについて明確なアドバイスを与えることは困難ですが、UpValues
の使用は私には思えます ここは不当です。これがエラー処理のために行われる場合、その他の方法
UpValues
を使用せずにそれを行うには 。
通常、UpValues
オーバーロードされる関数にルールを追加せずに、安全な方法で一部の関数をオーバーロードするために最も一般的に使用されます。 1つのアドバイスは、UpValues
の関連付けを避けることです。 DownValues
もあるヘッドを使用 そして、評価するかもしれません-これを行うことによって、あなたは評価者とゲームを始め、最終的には負けます。最も安全なのは、UpValues
を添付することです 不活性なシンボル(ヘッド、コンテナ)に変換します。これは、特定の関数をオーバーロードするオブジェクトの「タイプ」を表すことがよくあります。
HoldPattern
の存在に関する私のコメントについて 悪いデザインを示しています。確かに HoldPattern
の正当な使用法 、このような(やや人工的な)もの:
In[25]:=
Clear[ff,a,b,c];
ff[HoldPattern[Plus[x__]]]:={x};
ff[a+b+c]
Out[27]= {a,b,c}
多くの場合、Plus
であるため、ここでは正当化されます。 未評価のままであり、未評価の形式で役立ちます-合計を表すと推測できるためです。 HoldPattern
が必要です Plus
の方法のためにここに は単一の引数で定義され、パターンは定義中にたまたま単一の引数であるため(通常、複数の引数を記述している場合でも)。したがって、HoldPattern
を使用します ここでは、パターンが通常の引数として扱われないようにしますが、これはPlus
の使用目的とはほとんど異なります。 。これが当てはまる場合はいつでも(定義は意図されたユースケースで問題なく機能すると確信しています)、HoldPattern
結構です。この例も壊れやすいことに注意してください:
In[28]:= ff[Plus[a]]
Out[28]= ff[a]
それでもほとんど問題ない理由は、通常はPlus
を使用しないためです。 単一の引数で。
ただし、通常提供される引数の構造が定義に使用されるパターンの構造と同じである場合の2番目のグループがあります。この場合、割り当て中のパターン評価は、関数呼び出し中に実際の引数で同じ評価が行われることを示しています。あなたの使用法はこのカテゴリーに分類されます。設計上の欠陥についての私のコメントは、そのような場合でした。パターンが評価されないようにすることはできますが、これを機能させるには、引数も評価されないようにする必要があります。また、完全に評価されていない表現に対するパターンマッチングは脆弱です。また、関数は、引数に対して(型チェックできる範囲を超えて)いくつかの追加の条件を想定してはなりません。