【问题标题】:Why doesn't this run forever?为什么这不会永远运行?
【发布时间】:2015-01-18 21:21:58
【问题描述】:

我正在寻找一个相当不确定的question,关于当你想要进行无限循环时最好使用 for(;;) 还是 while(1),我在 C 中看到了一个有趣的解决方案,你可以@ 987654322@ "EVER" 作为常数等于 ";;"并从字面上循环for(EVER)

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

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


#!/usr/bin/perl -w

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

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

输出:

FOREVER!

为什么这在 perl 中不起作用?

【问题讨论】:

    标签: perl for-loop constants infinite-loop


    【解决方案1】:

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

    【讨论】:

    • 啊,我明白了...这是否意味着在 perl 中无法模仿此功能?在这一点上,我只是好奇是否可以做到。
    • 你可以用source filter 破解它。
    • @tjwrona1992 您可以使用字符串 eval 和变量插值来做到这一点。例如。 eval "for ($ever) ..." 但是,当您可以简单地使用 while 循环时,为什么要这样做呢? while (EVER) ...
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      #!/usr/bin/perl
      use warnings;
      use strict;
      
      sub forever (&) {
          $_[0]->() while 1
      }
      
      forever {
          print scalar localtime, "\n";
          sleep 1;
      };
      

      【讨论】:

        【解决方案4】:

        Andrew Medico 在他的评论中提到你可以用source filter. 一起破解它

        我确认了这一点,这里有一个例子。

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

        输出:

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

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

        【讨论】:

          猜你喜欢
          • 2012-05-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-26
          • 2016-08-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多