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-IObservable1-Subscribe(System.IObserver1 [FunScript.TypeScript.MouseEvent])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}

Итак, мои вопросы:

  1. Почему Expr.TryGetReflectedDefinition терпеть неудачу с IObservable.Subscribe вместо Async.AwaitObservable?
  2. Почему Expr.TryGetReflectedDefinition бросить исключение вместо возврата None?
  3. Это ошибка отраженных определений F# или неизбежное ограничение? Можно ли это исправить?

Заранее большое спасибо за вашу помощь!

1 ответ

Решение

Хорошо, кажется, на это нет простого ответа, поэтому я постараюсь ответить на свой вопрос. После дальнейшего расследования...

  1. Кажется, что из-за Async.AwaitObservable каким-то образом перегружает сохраненные отраженные определения (это "как-то" - это то, что остается необъяснимым), теряет след реализации типа IObservableи именно поэтому они не знают, какая реализация Subscribe должен быть использован.
  2. Я предполагаю, что это предполагаемое поведение: возвращение None означает, что Отраженное определение не было найдено, но здесь было неоднозначное совпадение, так что это другой случай.
  3. Я пока не знаю, является ли это ошибкой или "особенностью", но в любом случае я исправил проблему в этой конкретной ситуации, используя CompiledName атрибут и давая другое имя для каждой перегрузки. Теперь все работает отлично:)

Надеюсь, в следующий раз я опубликую вопрос, на который действительно можно ответить;) Спасибо всем, кто нашел время, чтобы прочитать это.

Другие вопросы по тегам