Вызов функции по ее имени в виде строки в f #

Я думал, что смогу сделать это с помощью цитат, но не понимаю, как.

Должен ли я просто использовать таблицу функций с их именами - или это их способ сделать это?

Спасибо.

Для получения дополнительной информации......

Я вызываю множество функций f # из excel, и мне стало интересно, могу ли я написать функцию f #

let fs_wrapper (f_name: string) (f_params: list double) = этот бит вызывает fname с f_params

а затем используйте

= fs_wrapper ("my_func", 3.14, 2.71)

в листе, а не обертывать все функции по отдельности.


person b1g3ar5    schedule 03.06.2011    source источник
comment
Можете ли вы показать немного больше того, что вы пытаетесь сделать?   -  person Daniel    schedule 04.06.2011


Ответы (3)


Для этого вам нужно будет использовать стандартную .NET Reflection. Цитаты не помогут, потому что они представляют вызовы функций с использованием стандартного .NET MethodInfo, поэтому вам все равно придется использовать отражение. Единственное преимущество цитат (по сравнению с наивным размышлением) состоит в том, что вы можете их скомпилировать, что может дать вам лучшую производительность (но компиляция не идеальна).

В зависимости от вашего конкретного сценария (например, где расположены функции) вам нужно будет сделать что-то вроде:

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

Если вам не нужна расширяемость или у вас есть большое количество функций, использование словаря, содержащего строку в качестве ключа и значение функции в качестве значения, может быть более простым вариантом:

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

funcs.[name](3.1415)
person Tomas Petricek    schedule 03.06.2011
comment
Спасибо, это хорошо работает. Я также могу передать имя модуля в виде строки. Следующее - управление типами параметров, но я оставлю это на время. Для чего нужна «шкатулка»? - person b1g3ar5; 04.06.2011
comment
@ b1g3ar5 - Метод Invoke принимает аргументы как массив объектов (obj[]), потому что он не может знать фактический тип параметров. Операция box переводит значение float в значение obj. Тип [| 3.14 |] будет float[], что не соответствует ожидаемому типу. - person Tomas Petricek; 04.06.2011
comment
Из-за всей этой синтаксической чепухи я скучаю по Python / Ruby. Даже C # с динамическим, если хотите. - person GregC; 04.06.2011
comment
@GregC - Вы можете использовать динамический оператор F # ? и написать что-то вроде funcs?sin(3.14), если хотите. Всю эту синтаксическую мля, конечно, можно спрятать внутри простой функции. - person Tomas Petricek; 06.06.2011
comment
Есть ли причина использовать GetTypes и перечислять результат вместо использования GetType? - person Edward Brey; 26.01.2015

Есть много методов, но один из них - использовать Reflection, например:

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

GetMethod необязательно принимает массив типов, определяющих подпись, но вы можете пропустить это, если ваш метод однозначен.

person Guvante    schedule 03.06.2011

В продолжение того, о чем говорил Томас, взгляните на Использование и злоупотребление оператором динамического поиска F # Мэтью Подвизоцкого. Он предлагает синтаксически чистый способ динамического поиска в F #.

person GregC    schedule 06.06.2011