F# Expr.TryGetReflectedDefinition с перегруженными методами
Я пишу некоторые расширения для проекта FunScript (F# для компилятора Javascript). Если вы заинтересованы, вы можете найти источник здесь.
Я пытался эмулировать расширение AwaitObservable Томаса Петричека. Однако, если я использую перегруженные методы, такие как AwaitObservable(w), AwaitObservable(w1,w2)...
Я получаю следующую ошибку, когда пытаюсь скомпилировать проект в Javascript:
An unhandled exception of type 'System.Reflection.AmbiguousMatchException' occurred in FSharp.Core.dll
Additional information: Ambiguous match found.
FunScript хранит кеш-словарь отраженных определений в проекте, и эта ошибка возникает, когда он пытается добавить новое в кеш, используя Expr.TryGetReflectedDefinition
, Ошибка исчезает, если я использую другие имена вместо перегрузок (AwaitObservable2, AwaitObservable3...
). Это обходной путь, который я сейчас использую, но я хотел бы узнать больше о проблеме и о том, возможно ли ее исправить, чтобы пользователи расширений могли нормально использовать перегруженные методы.
Я могу себе представить, что отраженные определения в F# не поддерживают перегруженные методы и не могут различать методы только по количеству аргументов (я не мог проверить это, потому что я не нашел реализацию Expr.TryGetReflectedDefinition
в исходном хранилище fsharp GitHub). Однако меня озадачивает то, что ошибка возникает не при поиске AwaitObservable, а в следующем методе:
{System.IDisposable System-IObservable
1-Subscribe(System.IObserver
1 [FunScript.TypeScript.MouseEvent])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
Итак, мои вопросы:
- Почему
Expr.TryGetReflectedDefinition
терпеть неудачу сIObservable.Subscribe
вместоAsync.AwaitObservable
? - Почему
Expr.TryGetReflectedDefinition
бросить исключение вместо возврата None? - Это ошибка отраженных определений F# или неизбежное ограничение? Можно ли это исправить?
Заранее большое спасибо за вашу помощь!
1 ответ
Хорошо, кажется, на это нет простого ответа, поэтому я постараюсь ответить на свой вопрос. После дальнейшего расследования...
- Кажется, что из-за
Async.AwaitObservable
каким-то образом перегружает сохраненные отраженные определения (это "как-то" - это то, что остается необъяснимым), теряет след реализации типаIObservable
и именно поэтому они не знают, какая реализацияSubscribe
должен быть использован. - Я предполагаю, что это предполагаемое поведение: возвращение
None
означает, что Отраженное определение не было найдено, но здесь было неоднозначное совпадение, так что это другой случай. - Я пока не знаю, является ли это ошибкой или "особенностью", но в любом случае я исправил проблему в этой конкретной ситуации, используя
CompiledName
атрибут и давая другое имя для каждой перегрузки. Теперь все работает отлично:)
Надеюсь, в следующий раз я опубликую вопрос, на который действительно можно ответить;) Спасибо всем, кто нашел время, чтобы прочитать это.