2010-09-17 36 views
5

¿Cómo sería una función FunctionQ, tal vez de una manera que incluso puedo especificar la cantidad de argumentos permitidos?¿Prueba si una expresión es una función?

+0

No entiendo muy bien su pregunta. ¿Quiere decir que quiere escribir una función FunctionQ [input_] que devuelve True si la entrada es una función, de lo contrario es falso? ¿Qué forma toma la entrada? –

+0

@Mark: la primera pregunta que respondería con Sí. La forma que la entrada tomaría es una expresión de Mathematica ... –

Respuesta

10

Realmente me siento mal posteando después de Simon y Daniel, pero sus códigos fallan en funciones que no son símbolos. La comprobación de que y la adición de un cheque por órdenes internas a través de NumericFunction, según lo sugerido por Simon, se llega a algo así como

FunctionQ[_Function | _InterpolatingFunction | _CompiledFunction] = True; 
FunctionQ[f_Symbol] := Or[ 
    DownValues[f] =!= {}, 
    MemberQ[ Attributes[f], NumericFunction ]] 
FunctionQ[_] = False; 

que debería funcionar en algunos casos de la vida real (suspiro)

In[17]:= 
FunctionQ/@{Sin,Function[x,3x], Compile[x,3 x],Interpolation[Range[5]],FunctionQ,3x,"a string", 5} 
Out[17]= {True,True,True,True,True,False,False,False} 

Si Conozco la firma de la función que está buscando (es decir, cuántos argumentos y de qué tipo), estoy de acuerdo con Simon en que el camino a seguir es tipar pato: Apply la función a argumentos típicos, y buscar resultados válidos. El almacenamiento en caché puede valer la pena:

AlternativeFunctionQ[f_]:=AlternativeFunctionQ[f]= 
    With[{TypicalArgs={1.0}},NumericQ[Apply[f,TypicalArgs]]]; 

In[33]= AlternativeFunctionQ/@{Sin,Function[x,3x], Compile[x, 3x],Interpolation[Range[5]],FunctionQ,3x,"a string", 5} 
Out[34]= {True,True,True,True,False,False,False,False} 
+0

¡Definitivamente no te sientas mal! Ese es el MO de SO: construir uno sobre el otro para llegar a la mejor respuesta posible. Gran trabajo en esto, por cierto! – dreeves

+0

Estaba revisando esto otra vez, y noté que 'FunctionQ' no es una función de var por' AlternativeFunctionQ'. Entonces, si bien es efectivo para encontrar funciones numéricas, no puede encontrar otros tipos. – rcollyer

+0

@rcollyer: El 'AlternativeFunctionQ' se entiende como un ejemplo: los argumentos típicos, así como el resultado válido deben adaptarse al caso en cuestión. Supongo que esto no es muy elegante desde el punto de vista de la arquitectura, pero a menudo encaja bastante bien. – Janus

2

Aquí es algo rápido y sucio que puede hacer lo que se necesita:

FunctionQ[x_] := Head[x] == Function || DownValues[x] =!= {} 
+0

¡Gracias! Intento el lunes y acepto tu respuesta, entonces ... –

3

Como dijo Daniel, su prueba (que probablemente debería leer)

FunctionQ[x_] := Head[x] === Function || DownValues[x] =!= {} 

Es rápido y sucio. Fallará para las funciones integradas, p. FunctionQ[Sin] devolverá False (Muchas funciones integradas se detectarán al buscar AttributeNumericFunction). También fallará para cosas como f[x_][y_] etc ... Probablemente también debería probar UpValues, SubValues y quizás NValues (ver here por sus significados).

Este problema fue discutido en thread. Hay muchas ideas útiles en este hilo, por ejemplo, maneras de encontrar el número de argumentos que pueden tomar algunas funciones, pero no se llegó a un consenso real en la discusión.

Creo que el mejor enfoque es un tipo de duck typing. Probablemente sepa cuántos y qué tipo de argumentos quiere que su función tome, así que pruébelo con ValueQ. Luego asegúrese de detectar los errores usando Check.

EDITAR: Otro comp.soft-sys.math.mathematica thread.

Cuestiones relacionadas