为什么这不会永远运行?

时间:2014-11-20 20:53:08

标签: perl for-loop constants infinite-loop

我正在考虑一个相当不确定的question,关于当你想要进行无限循环时是否最好用于(;;)或while(1),我在C中看到了一个有趣的解决方案可以#define“永远”作为常数等于“;;”并且字面上循环for(EVER)

我知道定义一个额外的常量可能不是最好的编程实践,但纯粹出于教育目的,我想看看是否可以用Perl完成。

我试图使Perl等效,但它只循环一次然后退出循环。


#!/usr/bin/perl -w

use strict;
use constant EVER => ';;';

for (EVER) {
    print "FOREVER!\n";
}

输出:

FOREVER!

为什么这不适用于perl?

4 个答案:

答案 0 :(得分:5)

它不会永远运行,因为';;'是普通字符串,而不是预处理器宏(Perl没有等效的C预处理器)。因此,for (';;')只运行一次,$_设置为';;'一次。

答案 1 :(得分:5)

C的预处理器常量与大多数语言中的常量非常不同。

正常常量就像一个变量,你只能设置一次;它有一个值,可以在变量可以在大多数地方传递,有一些好处,你和编译器知道它不会改变。这是Perl's constant pragma给你的常量类型。将常量传递给for运算符时,它只是将其视为字符串值,并相应地运行。

但是,C有一个在编译器甚至看到代码之前运行的步骤,称为预处理器。这实际上操纵了源代码的文本而不知道或关心它的大部分含义,因此可以做各种你在语言本身无法做到的事情。在#DEFINE EVER ;;的情况下,您告诉预处理器将EVER的每一次出现替换为;;,以便在实际编译器运行时,它只会看到for(;;) 。您可以更进一步,将单词forever定义为for(;;),它仍然可以使用。

正如Andrew Medico在评论中所提到的,最接近Perl的预处理器是source filters,实际上手册中的一个示例是#define的仿真。这些实际上甚至比预处理器宏更强大,允许人们编写像Acme :: Bleach这样的模块(用空格替换你的整个程序,同时保持功能)和Lingua :: Romana :: Perligata(解释用语法正确的拉丁语编写的程序) ,以及更明智的功能,例如为类和方法声明添加关键字和语法。

答案 2 :(得分:3)

Andrew Medico在评论中提到你可以和source filter.

一起破解它

我证实了这一点,这是一个例子。

use Filter::cpp;
#define EVER ;;
for (EVER) {
    print "Forever!\n";
}

输出:

Forever!
Forever!
Forever!
... keeps going ...

我不认为我会建议这样做,但这是可能的。

答案 3 :(得分:0)

这在Perl中是不可能的。但是,您可以定义名为forever的子例程,该子例程将代码块作为参数并一次又一次地运行:

#!/usr/bin/perl
use warnings;
use strict;

sub forever (&) {
    $_[0]->() while 1
}

forever {
    print scalar localtime, "\n";
    sleep 1;
};