friend 让我看this page ,并注意到一位论坛用户的签名中有一段奇怪的代码。
代码是一行代码,如下所示:
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
已移除滚动:
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
非常令人兴奋的是,如果您将代码按原样粘贴(然后不要再次触摸它!)到有效的过程级作用域中,则该代码可以编译(我没有尝试运行它,但这无关紧要)。
一些观察:
On Local Error
可以简化为On Error
Debug.Assert True
代替了该系列的转换和比较。使代码始终如一地编译,因此其中的某些内容会弄乱编译器。 Local
),它会停止编译,并且似乎没有任何东西让 VBA 理解它,除非该行被删除并重新粘贴。 问题是 ,此代码如何设法根据 VB 语言规范进行编译?它是 VB[6|A|E] 实现中的错误吗?换句话说,它为什么/如何工作?
我认为它与指令分隔符(
:
)和 inline-if 语法有关 - 鉴于没有 End If
声明,事物是单行而不是块。但是,是什么让那个特定的代码成为薛定谔的代码呢?是什么让它同时合法和非法?
如果代码被使用正式语法定义 (ANTLR) 生成的解析器正确解析,那么它一定是合法的构造吗?那么为什么当您仅返回到该行并按 ENTER 时它就不再合法了?
最佳答案
对于这么长的代码行,很难发现编译错误是从哪里潜入的,但是有一个微妙的区别,似乎是 VBE 在解析该行时或更可能在解析它之后对行应用自动更正。
这是原始行 - 从剪贴板粘贴
该行看起来像这样 直到 您将光标移动到另一行。
注意冒号,粗体, Loop
之间和 Else
关键词 陈述:
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency:
Loop: Else
Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
这是将光标移动到另一行后的行:
请注意,冒号已被 VBE 自动删除。似乎 VBE 解析器识别了该语句,然后“优化”了“冗余”冒号。
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency:
Loop Else
Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
如果您将冒号添加回处于无效语法状态的行,则自动更正会再次启动,但您的行将恢复为有效但脆弱的代码。
因此,似乎 VBE 解析该行,识别优化(冗余冒号),然后应用修复,但 VBE 并未意识到优化的行存在语法问题。
但为什么这条线最终变得脆弱?行中有很多分散注意力和不相关的关键字,所以让我们大幅减少它:
做 While..Loop
If we minimize the complexity of the line, to isolate the problem, we can simplify the line to:
If True Then Do While True: Beep: Loop: Else
Which, again, VBE autocorrects to a fragile line:
If True Then Do While True: Beep: Loop Else
But we can go even further and reduce the line to an illogically short line:
If True Then Do: Loop: Else
And VBE, once again, dutifully removes the colon to produce this line: (DO NOT EXECUTE THIS LINE OR YOU WILL HANG EXCEL)
If True Then Do: Loop Else
而..温德
Repeating the line, but swapping out the
Do While Loop
, for the olderWhile Wend
syntax:
If True Then While True: Beep: Wend: Else
Again, VBE optimizes away the colon, to give:
If True Then While True: Beep: Wend Else
But now the line is not fragile anymore!
因此,While..Wend 是较旧的构造,而 Do..Loop 构造较新(且更灵活),但似乎 VBE 解析器(和语法优化器)与 Do..Loop 构造存在冲突。
关键点:不要使用
Do..Loop
在单线If
包含 Else
的语句陈述。
关于vba - 为什么这段代码在粘贴时会编译,否则会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37147979/