2011-06-03 18 views
5

Pensé que podría hacer esto con las citas, pero no puedo ver cómo.Llamar a una función desde su nombre como una cadena en f #

¿Debo simplemente usar una tabla de las funciones con sus nombres, o es su forma de hacer esto?

Gracias.

Para obtener más información ......

Voy a llamar a una gran cantidad de funciones f # de excel y me preguntaba si podría escribir # función AF

Let fs_wrapper (f_nombre: string) (f_params: lista doble) = este bit llamadas fnombre con f_params

y luego usar

= fs_wrapper ("mi_func", 3,14, 2,71)

en la hoja en lugar de envolver todas las funciones por separado.

+1

¿Puedes mostrar un poco más de lo que estás tratando de hacer? – Daniel

Respuesta

9

Deberá usar la reflexión .NET estándar para hacer esto. Las citas no van a ayudar, ya que representan llamadas a funciones usando .NET estándar MethodInfo, por lo que tendrá que usar la reflexión de todos modos. El único beneficio de las citas (en comparación con la reflexión ingenua) es que puedes compilarlas, lo que podría darte un mejor rendimiento (pero la compilación no es perfecta).

En función de su situación específica (por ejemplo, donde se encuentran las funciones), que tendría que hacer algo como:

module Functions = 
    let sin x = sin(x) 
    let sqrt y = sqrt(y) 

open System.Reflection 

let moduleInfo = 
    Assembly.GetExecutingAssembly().GetTypes() 
    |> Seq.find (fun t -> t.Name = "Functions") 

let name = "sin" 
moduleInfo.GetMethod(name).Invoke(null, [| box 3.1415 |]) 

a menos que necesite algo de extensibilidad o tienen un gran número de funciones, el uso de un diccionario que contiene cadena como un valor clave y la función que el valor puede ser una opción más fácil:

let funcs = 
    dict [ "sin", Functions.sin; 
     "sqrt", Functions.sqrt ] 

funcs.[name](3.1415) 
+0

Gracias, esto funciona bien. También puedo pasar el nombre del módulo como una cadena. Lo siguiente es la administración del tipo de parámetro, pero lo dejaré por un tiempo. ¿Para qué es la 'caja'? – b1g3ar5

+0

@ b1g3ar5 - El método 'Invoke' toma argumentos como una matriz de objetos (' obj [] ') porque no puede conocer el tipo real de parámetros. La operación 'box' ejecuta el valor' float' en el valor 'obj'. El tipo de '[| 3.14 |] 'sería' float [] ', que no coincidiría con el tipo esperado. –

+0

Todo este bla sintáctico me está haciendo perder Python/Ruby. Incluso C# con dinámica, si tienes. – GregC

2

Hay muchos métodos, pero una forma es utilizar la reflexión, por ejemplo:

typeof<int>.GetMethod("ToString", System.Type.EmptyTypes).Invoke(1, null) 
typeof<int>.GetMethod("Parse", [|typeof<string>|]).Invoke(null, [|"112"|]) 

GetMethod toma opcionalmente una matriz de tipos que definen la firma, pero puede omitir eso si su método no es ambiguo.

Cuestiones relacionadas