2017-01-14 2 views
6

Может кто-нибудь, пожалуйста, объясните мне это действительно странное наблюдение?Можно ли вызвать методы расширения Rx с помощью lambdas внутри скрипта IronPython?

Я пытаюсь вызвать методы расширения Rx изнутри IronPython, и это оказывается просто невозможным. Я открутил его до этого простого примера:

import clr 
clr.AddReference("System.Core") 
from System.Linq import Enumerable 

def process(value): 
    return Enumerable.Select(value, lambda x:x) 

В этом случае мы начинаем с обычного LINQ. Если я вызываю функцию process из моей среды размещения с массивом или любым другим объектом IEnumerable, он работает совершенно нормально.

Итак, я попытался просто заменить ссылки использовать Observable методы расширения, как так:

import clr 
clr.AddReference("System.Reactive.Linq") 
from System.Reactive.Linq import Observable 

def process(value): 
    return Observable.Select(value, lambda x:x) 

В этом случае, если я называю process функцию с IObservable объекта, сбои вызовов с уродливым сообщение об ошибке:

expected IObservable[object], got Select[int, int]

кто попал на что-то вроде этого? Я что-то пропустил? Есть ли какой-то особый случай взлома, чтобы сделать Enumerable работой с делегатами лямбды, что Observable отсутствует? Я должен признать, что я здесь полностью озадачен.

Кстати, так же, как проверки вменяемости, следующий пример работает просто отлично:

import clr 
clr.AddReference("System.Reactive.Linq") 
from System.Reactive.Linq import Observable 

def process(value): 
    return Observable.Sum(value) 

Я хотел оставить его там просто чтобы понять, что проблема на самом деле в методе вызова Observable.Select.

+0

Я подал [вопрос] (https://github.com/IronLanguages/main/issues/1564) в хранилище IronPython с большим количеством выводов. Теперь я считаю, что это более общая ошибка с разрешением вызова метода IronPython, но по-прежнему будет лучше понимать проблему. – glopes

ответ

2

Часть проблемы, я подозреваю, что методы перегружены. Среда выполнения IronPython сделает все возможное, чтобы найти наилучшую перегрузку, но может иногда ошибиться. Возможно, вам придется помогать в устранении перегрузок.

Из сообщения об ошибке кажется, что вы пытаетесь называть его IObservable<int>. Похоже, что перегрузка разрешается здесь и пытается назвать ее Observable.Select<object, object>(). Вам нужно указать некоторые подсказки о том, какую перегрузку вы хотите использовать.

def process(value): 
    return Observable.Select[int,int](value, Func[int,int](lambda x:x)) 
+0

Отлично, это сработало и на самом деле в этом случае вам даже не нужны явные типы для общего метода: достаточно явно ввести лямбда. Тогда возникает вопрос, почему это необязательно для класса Enumerable, где методы имеют одинаковые перегрузки (например, lambdas с разными номерами аргументов). – glopes

+1

Если бы мне пришлось рисковать догадкой, наблюдаемый экземпляр передавал бы в действие многие, возможно, конфликтующие интерфейсы, и, должно быть, поразил случай, когда он не знал, как решить, какой тип лямбда должен принять. Большинство коллекций просты, поэтому легче найти лучшую перегрузку. Я не могу проверить это сейчас, но, возможно, есть явно реализованный интерфейс, который где-то использует «объект», и он использовал это. –

+0

На самом деле, я понимаю очевидный факт, что IronPython не может вывести тип любой лямбда, как это делает LINQ, даже в случае с 'Enumerable.Select'. Учитывая, что python является динамически динамическим языком, тело селектора может в принципе возвращать что-либо каждый раз, поэтому единственным разумным типом возвращаемого значения является «объект».Так много для скриптинга LINQ таким образом. – glopes

Смежные вопросы