2011-01-04 15 views
17

Czy istnieje prosty sposób sprawdzenia, czy istnieje definicja x? Potrzebuję funkcję, która pobiera coś formularza f, f[_] lub f[_][_] i zwraca True jeśli istnieje definicja toSprawdzanie, czy zdefiniowano symbol

być naprawdę konkretne, ja przechowywania rzeczy za pomocą konstruktów jak f [x] = b, a g [x] [y] = z i muszę sprawdzić, czy f [x] ma definicję dla każdego x na jakiejś liście i czy g [x] [y] ma definicję dla każdego x, y w pewnym zbiorze wartości

Odpowiedz

15

Jeśli dobrze rozumiem, myślę, że funkcja ValueQ jest tym, czego szukasz. Zwróci wartość true, jeśli zdefiniowano zmienną lub funkcję, a false, jeśli nie została zdefiniowana.

Czytaj więcej na http://reference.wolfram.com/mathematica/ref/ValueQ.html

+0

Świetnie, wydaje się działać zgodnie z oczekiwaniami dla wszystkich 3 formularzy –

1
  • Dla symboli w systemie "sprawdź opcję SyntaxInformation dla opcji ArgumentsPattern.
  • Dla innych symboli, sprawdź DownValues, UpValues, SubValues, etc ...

Jakie jest przeznaczenie?

+0

Mam funkcję, która daje lawinę błędów jeśli go uruchomić gdy brakuje niektórych definicji, więc chcę dodać automatyczne kontrole, aby przerwać i wydrukować rzeczy w stylu "błąd, xyz [] [] nie zdefiniowane" –

20

Właściwie funkcja ValueQ nie jest niewinny, ponieważ przecieki ocenę dla kodu z efektów ubocznych. Przykłady:

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

Jeśli usuniesz ReadProtected atrybutem ValueQ i spojrzeć na kod, widać dlaczego - kod jest bardzo proste i robi dobrej pracy dla zaledwie OwnValues. Tutaj jest bardziej skomplikowana wersja którą opracowano w celu uniknięcia tego problemu (można sprawdzić, że, przynajmniej na powyższych przykładach, to nie przecieka ocenę):

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]]; 

To nie jest pełna albo, ponieważ nie robi Uwzględnij UpValue, NValue i FormatValues, ale wydaje się to wystarczające dla twoich określonych potrzeb, a także reguły dla tych trzech dodatkowych przypadków mogą być również dodane w taki sam sposób jak powyżej.

+0

Myślę, że ValueQ działa dla mnie, ponieważ używam f [] i f [] [] jako słownika do przechowywania stałych, ale zachowam ten przepis na uwadze, jeśli pojawi się bardziej ogólne zapotrzebowanie, dzięki –

1

Oto ładne, proste rozwiązanie, które działa, jeśli dany obiekt ma wystarczającą wewnętrzną strukturę.

Można użyć

Length[variable] 

wykryć czy variable został przypisany do czegoś więcej niż jednej części. Zatem:

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

Następnie można użyć Length[variable]>0 dostać True w tym drugim przypadku.

nie to, chociaż, jeśli istnieje szansa, że ​​variable być przypisany do wartości atomowej, takich jak pojedynczy łańcuch lub numer:

variable=1 
Length[variable] 
(*---> 0*) 
Powiązane problemy