while 语言
在我的计算语言理论课程中,我们接到了一项作业,要求用一种只有 while 语句进行流程控制(没有 if 语句)的语言来实现一段代码。 这主要是为了证明只用while循环就可以写出图灵完备的语言。
对于那些能够理解语言语法的人,这里是语言规则:
S -> S;S | while C do S od | id := E
E -> E + T | T | E - T
T -> T * F | F | F / T
F -> id | cons | (E)
C -> E = E | E > E | E < E | E >= E | E <= E | E != E | C and C | C or C | not(C)
这是从我的课堂笔记中复制的,所以如果有遗漏或不正确的地方,请不要怪我!
要实现的代码片段是这样的:
if d = 0 do
x := 1
else
x := a / d
无论如何,如果您想继续使用上面的语言规则编写代码,那就继续吧。 否则,请继续用您最熟悉的任何语言编写它。但有一些注意事项!
- 除了 while 循环之外,没有 if 语句或任何其他类型的流程控制。
- 没有作弊:上面的语法不包括任何break语句、return语句或异常。 不要使用它们。
我已经为此编写了一段代码(我发布它只是为了证明这不是一个向我展示代码的帖子)。 我有点好奇其他人能想出什么。
For my theory of computing languages class, we got a homework assignment to implement a piece of code in a language that only has while statements for flow control (no if statements). This is mainly to prove that you can write a Turing-complete language with only a while loop.
For those of you who can understand language grammars, here are the language rules:
S -> S;S | while C do S od | id := E
E -> E + T | T | E - T
T -> T * F | F | F / T
F -> id | cons | (E)
C -> E = E | E > E | E < E | E >= E | E <= E | E != E | C and C | C or C | not(C)
This is copied from my class notes, so don't blame me if something is missing or incorrect!
The piece of code to implement is this:
if d = 0 do
x := 1
else
x := a / d
At any rate, if you want to go ahead and write that using the language rules above, go ahead. Otherwise, go ahead and write it in whatever language you're most comfortable in. But there are a few caveats!
- No if statements or any other kind of flow control other than while loops.
- No cheating: the grammar above doesn't include any break statements, return statements, or exceptions. Don't use them.
I've got my piece of code written for this (which I'll post just to prove this isn't a show me teh codez post). I'm kinda curious what anyone else can come up with though.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
它可以用一个 while 循环来完成,但不太清楚:
解释,如果 d = 0,那么 d 将是 1,a 也将是 1。这结束了循环。
现在 x 设置为 a / d ,这很好,因为如果 d 为 0,则 a / d 的计算结果为 1。
It can be done with a single while loop, but it is not that clear:
Explanation, if d = 0, then d will be 1, also a will be 1. This ends the loop.
Now x is set to a / d which is fine, because if d was 0, a / d evaluates to 1.
这是我的代码:
Here's my code:
这行得通吗?
Would this work?
要实现图灵完备,您需要支持选择和迭代。 While 循环显然是迭代的。 如果条件为真,则可以通过使其循环一次来完成选择,否则根本不循环。
因此,在最坏的情况下,您可以通过应用这些技术来完成您需要做的一切。 我想一些复杂的控制流程会很快变得丑陋。 :-)
To be Turing Complete, you need to support both selection and iteration. While loops obviously iterate. Selection can be accomplished by making it go through the loop once if the condition is true, and not at all otherwise.
So worst case you can do everything you need to by applying those techniques. I'd imagine some complicated control flows would get ugly fast though. :-)
不使用 true 或 false 分支的详细信息,也不重复谓词:
Without using details of the true or false branches, and without repeating the predicate:
这是Eamon 的答案的扩展。
if的语义 然后否则fi 如下:
;then
和else
之间的语句;else
和fi
之间的语句。while的语义 做od
如下:
;while
语句执行完毕;do
和od
之间的语句,并再次执行while
语句。要用
while
表达if A then B else C
,请执行以下转换:令
gensymN
为不用于任何其他变量的名称; 然后发出以下代码该程序的语义是:
A
为真,则为真)B
gensymN = 1
gensymN = 0 和 A
(错误)gensymN = 0
(错误)gensymN = 0
(这是真的)C
gensymN := 1
gensymN = 0
(错误)观察上面的以下子结构:
A
;B
,否则执行C
。A
、B
和C
之外,程序(片段)仅对gensymN
进行摆弄,而 gensymN 并不存在在输入程序中。因此,这个程序与一个脚注具有相同的语义
:如果
A
在求值时为真,它将再次求值(除非and
是短路的)。 如果语言允许在变量中存储布尔值,则可以再引入一个虚拟变量并执行dummy := A; <在此处插入上述程序,用虚拟代替 A>
。 那么dummy
的两次评估本质上只是一个负载。 如果评估布尔表达式不会产生副作用,则不必为了正确性而阻止第二次评估; 它可能是(也可能不是)优化。将上述内容作为“软证明”,加上前一段的附加条件,这是
if
到while
完全通用翻译>。 在我看来,完整的普遍性使这个(=埃蒙的)答案与其他答案区分开来。This is an expansion of Eamon's answer.
The semantics of
if <condition> then <stmt> else <stmt> fi
is the following:<condition>
;then
andelse
;else
andfi
.The semantics of
while <condition> do <stmt> od
is the following:<condition>
;while
statement is done executing;do
andod
, and execute thewhile
statement again.To express
if A then B else C
in terms ofwhile
, perform the following transformation:Let
gensymN
be a name not used for any other variable; then emit the following codeThe semantics of this program is:
gensymN
.gensymN = 0 and A
(it's true iffA
is true)B
gensymN = 1
gensymN = 0 and A
(it's false)gensymN = 0
(it's false)gensymN = 0 and A
was false):gensymN = 0
(it's true)C
gensymN := 1
gensymN = 0
(it's false)Observe the following substructure of the above:
A
;B
, otherwiseC
.A
,B
andC
, the program (fragment) only fiddles withgensymN
, which is not present in the input program.Hence this program has the same semantics as
One footnote: if
A
is true when evaluated, it will be evaluated once again (unlessand
is short-circuiting). If the language allows storing booleans in variables, one can introduce one more dummy variable and dodummy := A; <insert the above program here, with dummy instead of A>
. Then the two evaluations ofdummy
are essentially just a load. If evaluating boolean expressions cannot have side effects, preventing the second evaluation is not necessary for correctness; it may (or may not) be an optimization.Take the above as a "soft proof", with the provisos of the preceding paragraph, that this is a correct fully general translation of
if
towhile
. The full generality sets this (= Eamon's) answer apart from the others, in my view.