A. *_*Rex 43 loops programming-languages control-structure
有时当我编程时,我发现某些特定的控制结构对我来说非常有用,但在我的编程语言中却无法直接使用.我认为我最常见的愿望是"分裂时"(我不知道该怎么称呼它):
{
foo();
} split_while( condition ) {
bar();
}
Run Code Online (Sandbox Code Playgroud)
此代码的语义将foo()始终运行,然后检查条件.如果为true,则bar()运行,然后返回第一个块(因此foo()再次运行等).感谢reddit用户zxqdms的评论,我了解到Donald E. Knuth在他的论文"使用go to语句进行结构化编程"(参见第279页)中写到了这种结构.
您认为哪些替代控制结构是组织计算的有用方法?
我的目标是为自己和他人提供构建代码的新方法,以改进分块和推理.
注意:我不是在询问如何概括所有可能的控制结构,无论是使用jne,if/ goto,Lisp宏,continuation,monads,组合器,夸克还是其他任何东西.我问的是什么专业在描述代码时很有用.
Jor*_*dão 20
一个相当普遍的是无限循环.我想这样写:
forever {
// ...
}
Run Code Online (Sandbox Code Playgroud)
Jor*_*dão 20
有时,我需要一个带索引的foreach循环.它可以写成这样:
foreach (index i) (var item in list) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
(我不是特别喜欢这种语法,但你明白了)
Jor*_*dão 18
用else循环:
while (condition) {
// ...
}
else {
// the else runs if the loop didn't run
}
Run Code Online (Sandbox Code Playgroud)
mun*_*ent 18
大多数语言都有内置函数来覆盖常见的情况,但是"fencepost"循环总是一件苦差事:循环你希望在每次迭代中做某事,并在迭代之间做其他事情.例如,使用分隔符连接字符串:
string result = "";
for (int i = 0; i < items.Count; i++) {
result += items[i];
if (i < items.Count - 1) result += ", "; // This is gross.
// What if I can't access items by index?
// I have off-by-one errors *every* time I do this.
}
Run Code Online (Sandbox Code Playgroud)
我知道折叠可以涵盖这种情况,但有时你想要一些必要的东西.如果你能这样做会很酷:
string result = "";
foreach (var item in items) {
result += item;
} between {
result += ", ";
}
Run Code Online (Sandbox Code Playgroud)
mun*_*ent 14
{
foo();
} split_while( condition ) {
bar();
}
Run Code Online (Sandbox Code Playgroud)
您可以使用常规方法轻松完成此操作while:
while (true) {
foo();
if (!condition) break;
bar();
}
Run Code Online (Sandbox Code Playgroud)
我现在经常这样做,因为我克服了我的非理性厌恶break.
Has*_*ant 13
如果你看一下Haskell,虽然各种控制结构都有特殊的语法,但控制流通常是按类型捕获的.最常见的这种控件类型是Monads,Arrows和applicative functors.因此,如果你想要一种特殊类型的控制流,它通常是某种高阶函数,你要么自己编写,要么在Haskells包数据库(Hackage)中找到一个非常大的.
这些函数通常位于Control命名空间中,您可以在其中找到用于并行执行错误处理的模块.通常在过程语言中找到的许多控制结构在Control.Monad中都有一个函数副本,其中包括循环和if语句.如果其他是Haskell中keyworded表达,如果没有其他的表达就没有意义了,但非常有意义的单子,所以没有其他的if语句是由功能捕捉when和unless.
另一种常见情况是在更一般的上下文中进行列表操作.功能语言非常喜欢fold,而且专业版本喜欢map和filter.如果你有一个monad,那么就有了它的自然延伸fold.这就是所谓的foldM,因此也有你可以想到的任何专业版折叠的扩展,比如mapM和filterM.
Man*_*ero 11
这只是一般概念和语法:
if (cond)
//do something
else (cond)
//do something
also (cond)
//do something
else
//do something
end
Run Code Online (Sandbox Code Playgroud)
始终评估ALSO条件.ELSE像往常一样工作.
它也适用于案例.可能这是消除break语句的好方法:
case (exp)
also (const)
//do something
else (const)
//do something
also (const)
//do something
else
//do something
end
Run Code Online (Sandbox Code Playgroud)
可以理解为:
switch (exp)
case (const)
//do something
case (const)
//do something
break
case (const)
//do something
default
//do something
end
Run Code Online (Sandbox Code Playgroud)
我不知道这是有用还是简单,但它是一个例子.
小智 10
使用(lisp风格)宏,尾部调用和延续,这一切都很古怪.
对于宏,如果标准控制流构造对于给定的应用程序来说是不够的,程序员可以编写自己的(以及更多).它只需要一个简单的宏来实现你给出的结构作为例子.
通过尾调用,可以将复杂的控制流模式(例如实现状态机)分解为函数.
Continuations是一个功能强大的控制流原语(try/catch是它们的受限版本).结合尾调用和宏,复杂的控制流模式(回溯,解析等)变得直截了当.此外,它们在Web编程中很有用,因为它们可以反转控制的反转; 你可以有一个功能,要求用户输入一些信息,进行一些处理,要求用户提供更多输入等.
要解释Scheme标准,您应该尝试删除使其他功能显得必要的限制,而不是将更多功能堆积到您的语言上.
如果不:
unless (condition) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
而不是:
until (condition) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
标记循环是我发现自己有时从主流语言中丢失的东西.例如,
int i, j;
for outer ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
if ( l1[ i ] == l2[ j ] )
break outer;
Run Code Online (Sandbox Code Playgroud)
是的,我通常可以使用a来模拟这个goto,但是相当于continue需要你在标签之后将增量移动到循环体的末尾,这会损害可读性.您也可以通过在内部循环中设置一个标志并在外部循环的每次迭代中检查它来完成此操作,但它总是看起来很笨拙.
(额外奖励:我有时希望有一个和它redo一起去.它会在没有评估增量的情况下返回到循环的开始.)continuebreak
我提议"然后"运算符.它在第一次迭代时返回左操作数,在所有其他迭代中返回右操作数:
var result = "";
foreach (var item in items) {
result += "" then ", ";
result += item;
}
Run Code Online (Sandbox Code Playgroud)
在第一次迭代中,它将""添加到所有其他添加","的结果中,因此您获得一个字符串,其中包含用逗号分隔的每个项目.
if (cond)
//do something
else (cond)
//do something
else (cond)
//do something
first
//do something
then
//do something
else (cond)
//do something
else
//do something
end
Run Code Online (Sandbox Code Playgroud)
如果3个条件中的任何一个被评估为真,则FIRST和THEN块运行.FIRST块在条件块之前运行,THEN在条件块运行之后运行.
FIRST和THEN语句之后的ELSE条件或最终写入独立于这些块.
它可以读作:
if (cond)
first()
//do something
then()
else (cond)
first()
//do something
then()
else (cond)
first()
//do something
then()
else (cond)
//do something
else
//do something
end
function first()
//do something
return
function then()
//do something
return
Run Code Online (Sandbox Code Playgroud)
这些功能只是一种阅读形式.他们不会创造范围.它更像是来自Basic的gosub/return.
作为讨论事项的实用性和可读性.
怎么样
alternate {
statement 1,
statement 2,
[statement 3,...]
}
Run Code Online (Sandbox Code Playgroud)
循环通过每个连续通过的可用语句.
编辑:琐碎的例子
table_row_color = alternate(RED, GREEN, BLUE);
player_color = alternate(color_list); // cycles through list items
alternate(
led_on(),
led_off()
);
Run Code Online (Sandbox Code Playgroud)
编辑2:在上面的第三个例子中,语法可能有点令人困惑,因为它看起来像一个函数.实际上,每次传递只评估一个语句,而不是两者.更好的语法可能是类似的
alternate {
led_on();
}
then {
led_off();
}
Run Code Online (Sandbox Code Playgroud)
或者那种效果.但是我确实喜欢这样的想法,即如果需要可以使用其结果(如颜色示例中所示).
我想我应该提到CityScript(的脚本语言CityDesk其中有一些非常奇特的循环结构).
从帮助文件:
{$ forEach n var in (condition) sort-order $}
... text which appears for each item ....
{$ between $}
.. text which appears between each two items ....
{$ odd $}
.. text which appears for every other item, including the first ....
{$ even $}
.. text which appears for every other item, starting with the second ....
{$ else $}
.. text which appears if there are no items matching condition ....
{$ before $}
..text which appears before the loop, only if there are items matching condition
{$ after $}
..text which appears after the loop, only of there are items matching condition
{$ next $}
Run Code Online (Sandbox Code Playgroud)