2011-01-04 34 views
17

C'è un modo semplice per verificare se esiste una definizione per x? Ho bisogno di una funzione che prende qualcosa della forma f, f[_] o f[_][_] e restituisce True se c'è una definizione per essoControllare se è stato definito un simbolo

Per essere davvero concreto, sto memorizzare le cose usando costrutti come f [x] = b, e g [x] [y] = z e ho bisogno di controllare se f [x] ha una definizione per ogni x in qualche lista e se g [x] [y] ha una definizione per ogni x, y in alcuni set di valori

risposta

15

Se ho capito correttamente, penso che la funzione ValueQ sia quella che stai cercando. Restituisce vero se una variabile o una funzione è stata definita e falsa se non è stata definita.

Continua a http://reference.wolfram.com/mathematica/ref/ValueQ.html

+0

Grande, sembra funzionare come previsto per tutti i 3 moduli –

1
  • Per i simboli in Sistema`, selezionare l'opzione SyntaxInformation per ArgumentsPattern.
  • Per altri simboli, controllare DownValues, UpValues, SubValues, ecc ...

Qual è la destinazione d'uso?

+0

Ho una funzione che dà una valanga di errori se l'eseguo quando mancano alcune definizioni, quindi voglio aggiungere controlli automatici per abortire e stampare le cose lungo le linee di "errore, xyz [] [] non definito" –

20

In realtà, la funzione ValueQ non è innocente, in quanto le perdite di valutazione per codice con effetti collaterali. Esempi:

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

Se si rimuove l'attributo di ReadProtected ValueQ e guarda il codice, si vedrà perché - il codice è molto semplice e fa un lavoro decente per solo OwnValues. Ecco una versione più complessa, che ho sviluppato per evitare questo problema (è possibile verificare che, almeno per gli esempi di cui sopra, non perde di valutazione):

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

Questo non è completa, giacché non è così account per UpValues, NValues ​​e FormatValues, ma questo sembra essere sufficiente per le tue esigenze dichiarate, e anche, le regole per questi tre casi extra possono forse anche essere aggiunte lungo le stesse linee come sopra.

+0

Penso che ValueQ funzioni per me perché sto usando f [] ef [] [] come dizionario per memorizzare le costanti, ma terrò presente questa ricetta se emergerà un bisogno più generale, grazie –

1

Ecco una soluzione semplice e semplice che funziona se l'oggetto in questione ha una struttura interna sufficiente.

È possibile utilizzare

Length[variable] 

per rilevare se variable è stato assegnato a qualcosa con più di una parte. Così:

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

È quindi possibile utilizzare Length[variable]>0 per ottenere True in quest'ultimo caso.

questo non riesce, però, se c'è una possibilità che variable essere assegnato a un valore atomico, come ad esempio una singola stringa o un numero:

variable=1 
Length[variable] 
(*---> 0*) 
Problemi correlati