这是正确的做法:
repeat{
...
} until(<condition>)
在普罗梅拉?
我试过了:
do::
//..
(condition) -> break;
od
和
do ::
//..
if::(condition) -> break;
else
fi;
od
答案 0 :(得分:2)
您的首次尝试不正确,因为如果<condition>
不是true
,则该过程将永远阻止。
您的第二次尝试在功能上是正确的。就个人而言,我更喜欢您的解决方案的一个小变体,它不会丢弃执行批量代码的true
条目。
鉴于
repeat{
// bulk code
} until(<condition>)
您有以下选择:
do:
do
:: true ->
// bulk code
if
:: <condition> ->
break;
:: else;
fi;
od;
或
do
:: true ->
// bulk code
if
:: ! <condition>;
:: else ->
break;
fi;
od;
goto:
L1:
// bulk code
if
:: <condition>;
:: else
-> goto L1;
fi;
或
L1:
// bulk code
if
:: ! <condition>
-> goto L1;
:: else;
fi;
unless (不要使用!):
do
:: true ->
d_step {
// bulk code
}
od unless { <condition> };
请注意,这种方法有两种方法:
它假定<condition>
的值在// bulk code
内更改,而不是代码中的任何其他位置(,例如通过其他某个进程)
取决于// bulk code
的内容,可能根本无法使用d_step
。
仅在改变<condition>
评估的指令正确 // bulk code
内的最后一个的情况下,才允许一个删除d_step
而不影响语义。
要了解为何会出现这种情况,请在以下代码示例中观察Spin
的行为:
active proctype example()
{
int cc = 0;
do
:: true ->
printf("before %d\n", cc);
cc++;
printf("after %d\n", cc);
od unless { cc == 3 };
}
具有以下输出:
~$ spin test.pml
before 0
after 1
before 1
after 2
before 2
1 process created
由于cc++
改变了cc == 3
的评估,但不是代码序列的最后一条指令,因此屏幕上永远不会打印语句after 3
。
修改强>
当然,我们也可以使用unless
语句尝试另一种代码变体,例如
bool flag;
do
:: true ->
// bulk code
flag = true;
flag = false;
od unless { flag && <condition> };
这显然总是正确的,即使在一般情况下,但它会使用不属于原始问题的其他变量阻塞源代码,所以我仍然不鼓励使用unless
来替换do/until
。
以下是如何使用它的示例:
active proctype example()
{
int cc = 0;
bool flag = false;
do
:: true ->
printf("before %d\n", cc);
cc++;
printf("after %d\n", cc);
flag = true;
flag = false;
od unless { flag && (cc == 3) };
}
确实产生了正确的输出:
~$ spin test.pml
before 0
after 1
before 1
after 2
before 2
after 3
1 process created