【发布时间】:2020-02-13 06:30:57
【问题描述】:
我的愿望是通过 AddressOf 使用一个输入参数按名称运行给定函数,例如Function Foo(x as Integer) As Integer。我需要递归函数的两个输入是函数名称_name As String 和某种类型的对象_list As t(整数、双精度、列表(整数)等)。目标是处理具有函数名称的元素或元素列表,因为有多次我需要通过给定函数处理列表,并且我不希望在每个位置复制列表处理代码。我尝试调用这种类型的函数(如下)并没有完全崩溃的最佳方式导致了这个错误:
警告:List.Test 操作失败。重载解析失败,因为无法使用这些参数调用公共“进程列表”: '公共共享函数 ProcessList(Of t)(_func As Func(Of Object,t), _list As System.Object) As IEnumerable(Of t)': 参数匹配参数“_func”的类型参数推断失败。
Iterator Function ProcessList(Of t)(_func As Func(Of Object, t), _list As Object) As IEnumerable(Of t)
If _list.GetType = GetType(List(Of t)) Then
Yield _list.SelectMany(Function(l) ProcessList(_func, l))
Else
Yield _func(_list)
End If
End Function
作为参考,我发现了一个 Python 代码的 sn-p 可以有效地满足我的需要,但是我对这个方向的翻译(Python 到 VB.net)有点生疏,而且我不太熟悉VB.net 中的这种类型的编程。 Python sn-p 是:
def ProcessList(_func, _list):
return map(lambda x: ProcessList(_func, x) if type(x)==list else _func(x), _list)
任何关于我需要如何调用这个函数,或者如果我的方法有缺陷如何重做这个函数的任何帮助,将不胜感激!
更新:
我根据@djv 的信息重新检查了我是如何调用函数的,以及我的方法正在运行的其他一些事情。首先,由于我与这些函数的交互方式的性质,我必须通过以下方式公开上述函数:
Public Shared Function Foo(ByVal _input As Object) As Object
Return Utilities.ProcessList(AddressOf Bar, _input)
End Function
我现在也收到错误消息:
警告:List.Test 操作失败。 无法将“System.Int32”类型的对象转换为“System.Collections.Generic.IList`1[System.Int32]”类型。
此时的问题可能在于我调用 ProcessList 函数的方法,而不是我想的函数本身。我正在与一个对自己调用 ProcessList 不满意的 GUI 进行交互,因此我需要这个中间“帮助器”函数,但我显然没有正确使用它。
【问题讨论】:
-
我不确定您需要
ProcessList做什么。Enumerable.Select不正是您所需要的吗? -
我的印象是我需要
ProcessList来实现函数的递归性,因为理想情况下这可以在任何形式的嵌套列表上复制,并且source的每个元素本身都可以是一个列表,其元素需要通过Foo。如果不是这样,我将研究如何使Enumerable.Select以这种方式发挥作用。 -
@pmackni 您提供的 vb.net 代码使用 AddressOf 工作。您是否只想更改它以便可以将函数名作为字符串传递?
-
@djv 这对于故障排除来说更可取,但如果它按原样工作,我将不得不再看看我是如何称呼它的,以及我在我的测试。
-
我可以看到传递函数名而不是委托的潜在问题,因为委托将包含函数的返回类型,但函数名不会。您的
ProcessList(Of t)(_func As Func(Of Object, t)从委托中获取 t 的类型。这将要求您将其称为ProcessList(Of Integer)("foo1", i),这违背了泛型的目的。
标签: vb.net recursion generic-function