【问题标题】:Are nested functions possible in VBA?VBA中可以嵌套函数吗?
【发布时间】:2014-06-30 04:51:11
【问题描述】:

我正在尝试通过从私有范围内的函数中剥离参数来清理代码,如下所示:

Function complicatedFunction(x as Double, param1 as Double, param2 as Double)
    ...
End Function

Function mainActionHappensHere(L as Double, U as Double ...)
    Function cleaner(x)
        cleaner = complicatedFunction(x, L, U)
    End Function
    ...
    cleaner(x)                       'Many calls to this function
    ...
End Function

这可能吗?编译器抱怨“预期结束函数”,因为我在结束外部函数之前开始了一个函数。 Google 也帮不上忙 :( PS 我不能在 mainActionHappensHere() 之外定义cleaner(),因为那样正确的 L 和 U 就不会被传递进去。

【问题讨论】:

  • 不,VBA 中没有嵌套函数,但如果你想让它更精简,然后将函数声明为私有,那么只有该模块可以看到它。为什么不能在外面用L、U、x的参数声明呢。从 mainActionHappensHere 传入 L 和 U 是等价的。
  • 在逻辑上是等价的,但不是cleaner。我将在所有地方都编写 complexFunction(x,L,U),并且我希望通过在所有地方编写 clean(x) 来更容易理解代码。 PS 如果我在mainActionHappensHere() 之外声明cleaner(),mahh() 仍然能够“看到”cleaner(),但是当我从cleaner() 中调用complexFunction() 时,它将不知道“L”是什么和“U”指的是,因为它们超出了范围!
  • 如果你真的想要这个,那么将 L 和 U 声明为模块级别而不是方法级别。但我仍然认为这是一个从无到有的问题 - 调用 mySub x, y, z 与调用 mySub x 相比,尽管 在功能上 暗示 mySub x, y, z 在实现中几乎没有“清理”任何东西。跨度>

标签: vba parameter-passing nested-function inline-functions


【解决方案1】:

VB.Net 可以做到这一点,但我不相信 VBA 可以。

重载函数或可选参数可以帮助您以其他方式简化此代码的两个功能。下面是一个使用可选参数的例子:

Function complicatedFunction(x as Double, Optional param1 as Double = L, Optional param2 as Double = U) As Object
...
End Function

complicatedFunction(x)

但是,L 和 U 必须是常量才能正常工作。

FWIW,如果你真的在使用 VB.Net 方言,VB.Net 语法如下所示:

Sub complicatedFunction(x as Double, param1 as Double, param2 as Double) 
    ...
End Sub

Function mainActionHappensHere(L as Double, U as Double ...)
    Dim cleaner As Func(Of Double, Object) = 
        Function(x) 
            Return complicatedFunction(x, L, U)
        End Function

    Dim y = cleaner(x)                       'Many calls to this function
    ...
End Function

【讨论】:

  • 不仅是 VB.NET,还有 VB.NET >= 2010 年多行 lambda 表达式首次出现。
  • 是的,虽然这很简单,可以在需要时简化为单行 lambda。
  • Dang,我希望我现在正在使用 VB.net……这些 lambda 表达式将是我的解决方案!作为记录,cleaner(x) 确实有一个返回值(它需要是一个函数,而不是一个子),我在上面省略了。
【解决方案2】:

VB 中没有嵌套函数,无论是 VBA、VB6 还是 VB.NET。

将范围限制为 VBA,您的选择是:

  • 使用GoSub,这是最古老的 VB 命令之一,在 VB.NET 中已被弃用、不赞成且没有等效升级:

    Function mainActionHappensHere(L as Double, U as Double ...)
        Dim ResultOfCleaner As Variant
        ...
        x = 5 : GoSub cleaner                       'Many calls to this function
        'Use ResultOfCleaner here
        ...
        x = 42 : GoSub cleaner                      'Many calls to this function
        'Use ResultOfCleaner here
        ...
        Exit Function
    
    cleaner:
        ResultOfCleaner = complicatedFunction(x, L, U)
        Return
    End Function
    
  • 手动创建一个闭包。

    定义一个将LU 公开为字段或属性的类。实例化该类,设置一次LU,然后调用同样在该类中定义的函数Cleaner,使用存储的LU 调用complicatedFunction

    显然这会产生一些开销。

【讨论】:

  • 我想最后一个选项,取决于他的设置,是声明 L 和 U 模块级别,并声明为一个普通函数,该函数在模块级别 L 和 U 中传递给极其复杂的函数. '虽然会很丑;)
  • vb.net 可以嵌套函数,如下所示。
  • @Cor_Blimey 在模块级别使用 LU 时,顶层函数变为不可重入安全。
  • @JoelCoehoorn 这些不是嵌套函数,它们是 lambda。您在函数中声明一个局部变量并为其分配一个“lambda”类型的对象。您仍然没有嵌套函数。
  • 这个目的是一样的。
【解决方案3】:

你可以使用这个语法

Dim fSomeFunction As Func(Of String, Boolean) = Function(ByVal something As String) As Boolean
                                                                     Return True
                                                                 End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2019-02-15
    • 2012-03-16
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多