2014-02-17 6 views
1

Как небольшая программа, чтобы немного узнать язык, я попытался реализовать метод linq Select (обычно известный как Карта вне .net) в VB, однако мне кажется, что я «в работать с небольшой проблемой, она не позволит мне вызвать функцию рекурсивно, так как он считает, что типы не совпадаютНевозможно рекурсивно вызвать функцию в VB.NET

вот код:

Iterator Function Map(Of A, B)(fun As Func(Of A, B), input As List(Of A)) As IEnumerable(Of B) 
    If input Is Nothing Then 
     Yield Nothing 
    Else 
     Yield fun(Head(input)) 
     Map(fun, Tail(input)) ' error here 
    End If 
End Function 

здесь следует отметить, что Head() функция который возвращает первый элемент списка ввода, а Tail() - это метод, который возвращает все, но первый элемент

Я сделал тест раньше, чтобы узнать, можно ли мне передать Func(Of A, B) в функцию, как я здесь; он работал нормально, поэтому почему это не работает сейчас, я не знаю ...

Может ли кто-нибудь помочь в этом?

ответ

3

Давайте предположим, что Head и Tail имеют следующие подписи:

Function Head(Of T)(lst As IEnumerable(Of T)) As T 
    ... 
End Function 

Function Tail(Of T)(lst As IEnumerable(Of T)) As IEnumerable(Of T) 
    ... 
End Function 

тогда линия в вопросе дает следующую ошибку (Подсказка:. Всегда включать сообщение об ошибке в вашем СЦ вопрос):

Data type(s) of the type parameter(s) in method 'Public Iterator Function Map(Of A, B)(fun As System.Func(Of A, B), input As System.Collections.Generic.List(Of A)) As System.Collections.Generic.IEnumerable(Of B)' cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.

Так что давайте делать то, что просит сообщение об ошибке:

Iterator Function Map(Of A, B)(fun As Func(Of A, B), input As List(Of A)) As IEnumerable(Of B) 
    ... 
     Map(Of A, B)(fun, Tail(input)) 
    ... 
End Function 

И мы получим более конкретную ошибку:

Option Strict On disallows implicit conversions from 'System.Collections.Generic.IEnumerable(Of A)' to 'System.Collections.Generic.List(Of A)'.

Это имеет смысл: Tail возвращает IEnumerable, Map требует List. Поскольку Map не использует список конкретных свойств, давайте просто сделать Map более либеральны в своем входе:

Iterator Function Map(Of A, B)(fun As Func(Of A, B), input As IEnumerable(Of A)) As IEnumerable(Of B) 
    ... 
End Function 

Теперь все компилируется правильно. На самом деле, мы можем теперь удалить(Of A, B) снова, потому что установка тип данных позволил VB.NET правильно вывести необходимые общие параметры типа:

Iterator Function Map(Of A, B)(fun As Func(Of A, B), input As IEnumerable(Of A)) As IEnumerable(Of B) 
    If input Is Nothing Then 
     Yield Nothing 
    Else 
     Yield fun(Head(input)) 
     Map(fun, Tail(input)) ' works 
    End If 
End Function 
+0

Я так привык к неявных преобразований, которые я полностью упускается из виду это. .. спасибо .. Также можно продолжать точно угадывать подписи головы и хвоста! –

+0

Скажите мне, почему функция возвращает только один элемент, а не целую коллекцию? –

+0

@ElectricCoffee: Потому что вы игнорируете возвращаемое значение «Карта». Простым решением будет «For v In Map (fun, Tail (input)): Yield v: Next'. Другим решением было бы не использовать функцию итератора, а скорее регулярную функцию и «Return func (Head (input)). Concat (Map (fun, Tail (input))). – Heinzi

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