Перегрузка поведения вызова функции в F #?

#f# #overloading

#f# #перегрузка

Вопрос:

Можно ли это сделать? Я покопался и ничего не нашел относительно того, возможно ли это.

Основная причина, по которой я хочу перегрузить поведение вызова функции, заключается в том, что в итоге я получил некоторый код, который использует действительно сложные замыкания, которые захватывают много-много локальных состояний для работы.

Я нахожу такого рода вложенные замыкания действительно запутанными и хотел бы преобразовать их в полноценные объекты с четко определенной схемой, наследованием и тому подобным, без изменения интерфейса для остальной части кода.

Ответ №1:

F # не поддерживает перегрузку поведения приложения-функции, поэтому вы не можете написать объект, который может быть вызван тем же способом, что и функция. Боюсь, что вам придется изменить интерфейс, чтобы использовать что-то вроде:

 foo.Invoke(10, "Hello")
  

Вместо:

 foo 10 "Hello"
  

Использование объектов обычно также предполагает, что объект более сложный, поэтому, изменяя интерфейс, вы даете некоторую подсказку разработчику, вызывающему его (говоря, что это сложный тип). В зависимости от вашего домена вам также следует найти какое-нибудь более описательное имя для Invoke .

Я также изменил синтаксис, чтобы использовать параметры метода с кортежами вместо стиля curried — технически, вы также можете использовать стиль curried для членов, но он обычно не используется (он просто лучше работает для простых функций).

Наконец, если вы обнаружите, что замыкания представляют более сложную структуру данных, возможно, вы могли бы сделать структуру данных более явной и определить type для хранения данных. Тогда вы могли бы просто использовать простые функции, но предоставлять им данные в качестве дополнительного аргумента (хотя это всего лишь мысль, которая на самом деле может быть вам не очень полезна).

Комментарии:

1. Основная причина, по которой я хотел избежать этого, заключается в том, что это для DSL, где дополнительный синтаксис невероятно затратен с точки зрения длины и четкости. Думаю, я найду какой-нибудь другой способ сделать это, спасибо!

2. @LiHaoyi Опасения по поводу синтаксиса довольно разумны для DSL. Не могли бы вы определить foo как простую оболочку функции для объекта? Например, написать что-то вроде let foo (inst:MyType) num str = inst.Invoke(num, str) ?

3. то, как я это понял сейчас, связано с цепочкой методов с использованием операторов, например, div-emphasis-float(left)*[...some child divs...] с операторами - и * , выбранными потому, что они выглядели наименее навязчивыми. Это достаточно чисто (даже если не так красиво, как div emphasis float(left) [...] , хотя теперь весь код выглядит как CSS!