如果我将continue
作为eval()
指令的参数包含在内,则它不会按预期工作。例如,执行以下代码时:
listParam = {'a','b','c'};
a = 17;
b = NaN;
c = 4;
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), continue; end']);
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
它会提示错误:
Error: A CONTINUE may only be used within a FOR or WHILE loop.
有谁知道为什么?
注意:我知道我应该避免eval()
,前面的例子可以用更好的编码重构;但我发现了一种奇怪的行为,我很好奇发生了什么。
答案 0 :(得分:3)
传递给eval
的表达式必须是其自身的有效matlab表达式,不考虑任何周围的代码。这意味着每个continue
必须被循环包围。将周围的for
放在您的评估范围内或将continue
放在外面。
答案 1 :(得分:2)
正如@Daniel指出的那样,eval
由脚本调用,而它不是由for
循环直接控制的。您可以将其视为:continue
中的eval
会将程序计数器移动到eval
内的代码头部,而不是for
循环的代码头部。这当然会失败,因为Matlab不允许在行之间跳转。
continue
只能直接显示在for
或while
循环中。但是,你可以破解这样的代码:
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), x=1; else, x=0; end']);
if x
continue;
end
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
奇怪的是,x
恰好出现在脚本的堆栈中。但是,这远远不是一段好的代码。切勿使用此方法。
编辑:关于"控制"范围eval
。
我不是在谈论eval
的变量范围/工作空间。可以在多个文档中找到提示,例如this和this。简而言之,eval
使用"当前"工作区。
然而,我发现以下有趣的事情:
直接在continue
eval
for ii = 1:2
eval('continue')
ii+10
end
如问题所示,这完全失败了。错误为Error: A CONTINUE may only be used within a FOR or WHILE loop.
,这意味着continue
内的eval
无法找到任何循环(for
循环)。
在for
循环中调用单独的脚本
for ii = 1:2
foo
ii+10
end
,而脚本foo.m
是
ii
continue
首先,在foo.m
中,Mlint会发出一个红线警告,通常表示可以阻止代码运行的错误,并指出CONTINUE is only valid in a FOR or WHILE loop
。但是在foo.m
上按F5没有任何问题 - 实际上在任何地方运行单个continue
都不会导致代码崩溃。
运行主脚本提供输出
ii =
1
ii =
2
>>
....所以foo.m
抓住了for
循环?
eval('foo')
- 我真的不了解Matlab
for ii = 1:2
eval('foo')
ii+10
end
结果让我感到有些惊讶。
ii =
1
ans =
11
ii =
2
ans =
12
>>
思想:eval
在独立的控制流中运行代码,但与当前的工作区共享其工作区。它是(某些但不完全)像isolated world模型,其中(在Matlab中)不同的代码片段可以与同一组变量交互,但在控制流的意义上不能相互交互。
不幸的是,我无法找到任何现有资源作为参考来证明这个想法。
这不会改变我的解决方案:在任何情况下,尽量避免使用eval
。