2011-01-04 6 views
17

Есть ли простой способ проверить, существует ли определение для x? Мне нужна функция, которая принимает что-то в виде f, f[_] или f[_][_] и возвращает True если есть определение егоПроверка наличия символа

Чтобы быть действительно конкретным, я хранить вещи, используя конструкцию типа Р [х] = Ь, g [x] [y] = z и мне нужно проверить, имеет ли f [x] определение для каждого x в некотором списке, и если g [x] [y] имеет определение для каждого x, y в некотором наборе значений

ответ

15

Если я правильно понял, я думаю, что функция ValueQ - это то, что вы ищете. Он вернет true, если определена переменная или функция, а false, если она не определена.

Подробнее на http://reference.wolfram.com/mathematica/ref/ValueQ.html

+0

Отлично, кажется, работает как ожидалось для всех 3 форм –

1
  • Для символов в System`, проверьте SyntaxInformation для параметра ArgumentsPattern.
  • Для других символов, чековые DownValues, UpValues, SubValues, и т.д ...

Что предполагаемое использование?

+0

У меня есть функция, которая дает лавину ошибок, если я запускаю его когда некоторые определения отсутствуют, поэтому я хочу добавить автоматические проверки, чтобы прервать и распечатать вещи по строкам «error, xyz [] [] not defined» –

20

На самом деле, функция ValueQ не невинна, так как она просачивается оценками для кода с побочными эффектами. Примеры:

ClearAll[f, g]; 
f[x_] := Print[x]; 
g[x_][0] := Print[x]; 
{ValueQ[f[1]],ValueQ[g[2][0]]} 

Если удалить ReadProtected атрибут ValueQ и посмотреть на код, вы увидите, почему - код очень упрощенно и делает достойную работу для всего OwnValues. Вот более сложный вариант, который я разработал, чтобы избежать этой проблемы (вы можете проверить, что, по крайней мере, на приведенных выше примерах, не вытекла оценки):

ClearAll[symbolicHead]; 
SetAttributes[symbolicHead, HoldAllComplete]; 
symbolicHead[f_Symbol[___]] := f; 
symbolicHead[f_[___]] := symbolicHead[f]; 
symbolicHead[f_] := Head[Unevaluated[f]]; 

ClearAll[partialEval]; 
SetAttributes[partialEval, HoldAllComplete]; 
partialEval[a_Symbol] /; OwnValues[a] =!= {} := 
    Unevaluated[partialEval[a]] /. OwnValues[a]; 

partialEval[a : f_Symbol[___]] /; DownValues[f] =!= {} := 
    With[{dv = DownValues[f]}, 
     With[{eval = Hold[partialEval[a]] /. dv}, 
     ReleaseHold[eval] /; 
      (First[Extract[eval, {{1, 1}}, HoldComplete]] =!= 
      HoldComplete[a])]]; 

partialEval[a_] := 
    With[{sub = SubValues[Evaluate[symbolicHead[a]]]}, 
     With[{eval = Hold[partialEval[a]] /. sub}, 
     ReleaseHold[eval] /; 
      (First[Extract[eval, {{1, 1}}, HoldComplete]] =!= 
      HoldComplete[a])]]; 

ClearAll[valueQ]; 
SetAttributes[valueQ, HoldAllComplete]; 
valueQ[expr_] := partialEval[expr] =!= Unevaluated[partialEval[expr]]; 

Это не полный либо, так как он не учет UpValues, NValues ​​и FormatValues, но этого, кажется, достаточно для ваших заявленных потребностей, а также правила для этих трех дополнительных случаев, возможно, также могут быть добавлены по тем же линиям, что и выше.

+0

Я думаю, что ValueQ работает для меня, потому что я использую f [] и f [] [] в качестве словаря для хранения констант, но я буду помнить этот рецепт, если возникнет более общая потребность, спасибо –

1

Вот хорошее, простое решение, которое работает, если объект, о котором идет речь, имеет достаточную внутреннюю структуру.

Вы можете использовать

Length[variable] 

обнаружить ли variable был назначен на что-то с более чем одной части. Таким образом:

Remove[variable] 
Length[variable] 
(*---> 0*) 
variable={1,2,3}; 
Length[variable] 
(*---> 3*) 

Вы можете использовать Length[variable]>0 получить True в последнем случае.

Это не удается, хотя, если есть шанс, что variable быть назначена атомарным значение, например, в виде одной строки или номера:

variable=1 
Length[variable] 
(*---> 0*) 
Смежные вопросы