Как я могу остановить запуск кода на этапе компиляции? - PullRequest
6 голосов
/ 15 января 2020

Этот вопрос требует понимания фазы компилятора, против блока BEGIN. Из Программирование Perl: 3-е издание - Страница 467

Также важно понимать разницу между фазой компиляции и временем компиляции, а также между фазой запуска и временем выполнения. Типичная Perl программа получает одну фазу компиляции, а затем одну фазу запуска. «Фаза» - это масштабная концепция. Но время компиляции и время выполнения - это небольшие концепции. Данная фаза компиляции выполняет в основном вещи во время компиляции, но она также выполняет некоторые вещи во время выполнения через блоки BEGIN. Данная фаза запуска в основном выполняет вещи во время выполнения, но она может выполнять вещи во время компиляции с помощью таких операторов, как eval STRING.

Давайте рассмотрим очень простой пример

sub complex_sub {
  die 'code run';
}
sleep 5;
print 'good';
use constant FOO => complex_sub();

если вышеописанное выполняется как есть, то complex_sub с точки зрения пользователя запускается на этапе компиляции. Тем не менее, с небольшими изменениями я могу иметь ..

# Bar.pm
package Bar {
  use constant FOO => main::complex_sub();
}

# test.pl
package main {
  sub complex_sub {
    die 'code run';
  }
  sleep 5;
  print 'good';
  require Bar;
}

В приведенном выше коде complex_sub выполняется в фазе выполнения. В любом случае можно ли дифференцировать эти два случая с точки зрения complex_sub, чтобы включить верхний синтаксис, но запретить нижний синтаксис.

Ответы [ 2 ]

12 голосов
/ 15 января 2020

Используйте переменную ${^GLOBAL_PHASE}. Он содержит «START» в первом случае, но «RUN» во втором.

# RUN
perl -wE'say ${^GLOBAL_PHASE}'

# START
perl -wE'BEGIN {say ${^GLOBAL_PHASE}}'

# RUN
perl -wE'eval q{BEGIN {say ${^GLOBAL_PHASE}}}'

Подробнее см. perlvar .

0 голосов
/ 15 января 2020

Вы можете сделать:

#!/usr/bin/env perl

use Const::Fast;

sub complex_sub {
  die 'code run';
}

sleep 5;
print 'good';

const my $FOO => complex_sub();

Какие выходные данные:

<5 second pause>
code run at /tmp/so1.pl line 6.
good

Это работает, потому что, хотя лексическая переменная объявляется во время компиляции, она не устанавливается до времени выполнения.

...