Як я можу використовувати булеві змінні в Perl?


220

Я намагався:

$var = false;
$var = FALSE;
$var = False;

Жоден з цих не працює. Я отримую повідомлення про помилку

Баревор "хибний" не дозволений, поки використовується "суворий абонемент".

37
Ви можете почати з моєї книги « Навчання Perl» . Простіше, ніж здогадуватися, що робити, поки не зрозумієш правильно (мавпи, друкарські машини та Гамлет, і все таке). :)
Брайан d foy

Відповіді:


285

У Perl такі умови оцінюються як хибні в умовних умовах:

0
'0'
undef
''  # Empty scalar
()  # Empty list
('')

Решта - правда. Немає баревок для trueабо false.


2
@BlueWaldo: ви також можете використовувати cmp і <=> при порівнянні та присвоєнні результатів порівняння скаляру. $ var = $ var1 cmp $ var2; 'cmp' і '<=>' (використовується для числових порівнянь) повертає -1, 0 або 1, якщо аргумент лівого аргументу менше, рівний або більший, ніж правий аргумент. Це не логічно, але іноді ви можете дізнатися, чи один аргумент рівний чи менший або більший, ніж інший замість просто рівного чи не рівного.
користувач118435

9
Проблема 1: Порожній список неправдивий, оскільки неможливо перевірити, чи список справжній чи неправдивий. Повертається порожній список у скалярному контексті undef.
ikegami

4
Завдання 2: ('')і ''мають однакове значення. Я думаю, ви хотіли навести список із елементом, який складається з порожнього рядка (навіть якщо парени не створюють списки), але, як я вже згадував, неможливо перевірити, чи є список правдивим.
ikegami

6
Проблема 3: Об'єкти з перевантаженим булевим оператором також можуть бути помилковими.
ikegami

15
@eternicode, Perl має два конкретні значення, які він використовує, коли йому потрібно повернути істинне та хибне, тому він має не тільки булеві, але істинний ( !0ака PL_sv_yes) і false ( !1ака PL_sv_no). Або ви кажете, що Perl повинен кричати, коли щось, крім цих двох значень, перевіряється на правдивість? Це було б абсолютно жахливо. Наприклад, це запобігло б$x ||= $default;
ikegami

71

Найбільш повне, стисле визначення помилкового, яке я натрапив, це:

Все, що стрифіфікується на порожній рядок або рядок, 0є помилковим. Все інше правда.

Тому такі значення помилкові:

  • Порожній рядок
  • Числове значення нуль
  • Невизначене значення
  • Об'єкт із перевантаженим булевим оператором, який оцінює одне з вищезазначених.
  • Чарівна змінна, що оцінює одне з вищезазначених на вибір.

Майте на увазі, що пустий літеральний список оцінюється до невизначеного значення у скалярному контексті, тому він оцінює щось неправдиве.


Примітка про "справжні нулі"

Хоча числа, які строковують 0як помилкові, рядки, які нумізуються нулем, не обов'язково. Єдиними помилковими рядками є 0і порожня рядок. Будь-який інший рядок, навіть якщо він дорівнює нулю, є істинним.

Нижче наведені рядки, які є істинними як булеві та нульові як число:

  • Без попередження:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • З попередженням:
    • Будь-який рядок, для якого Scalar::Util::looks_like_numberповертається хибним. (наприклад "abc")

якщо я зрозумів, що ви правильно, це слово true у той час, як числа, які позначають значення 0 є істинними, повинні бути хибними або (щоб уникнути плутанини), оцініть значення false .
user907860

1
Ваше "стисле" визначення не відповідає вашому більш тривалому поясненню. Розглянемо: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Тепер $valueбуде переведено на "XXX", але збільшиться на false.
tobyink

1
@tobyink, Лаконічна версія не є досконалою, просто найкращою, яку я знайшов. Це повинно бути практичним, а не всеосяжним. Зверніть увагу, що значення, повернене вашим boolфайлом, позначається строком 0. Крім того, вам не рекомендується створювати непослідовні перевантаження, і значення, які ви повертаєте, можна вважати такими. (Наприклад, &&можуть бути оптимізовані в ||, так що, якщо вони були суперечливими, ви повинні були б проблеми.)
Ikegami

Я не впевнений, чи 0x00охоплюється тут.
Заїд

@Zaid, Ви маєте на увазі значення, повернене кодом 0x00(числове значення нуль) або рядком 0x00(для якого looks_like_numberпомилковим)? Так чи інакше, це вже висвітлено.
ikegami

59

У Perl немає нативного булевого типу, але ви можете використовувати порівняння цілих чисел або рядків, щоб отримати таку саму поведінку. Приклад Алана - хороший спосіб зробити це, використовуючи порівняння цілих чисел. Ось приклад

my $boolean = 0;
if ( $boolean ) {
    print "$boolean evaluates to true\n";
} else {
    print "$boolean evaluates to false\n";
}

Одне, що я робив у деяких своїх програмах, - це те саме поведінка, використовуючи константу:

#!/usr/bin/perl

use strict;
use warnings;

use constant false => 0;
use constant true  => 1;

my $val1 = true;
my $val2 = false;

print $val1, " && ", $val2;
if ( $val1 && $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

print $val1, " || ", $val2;
if ( $val1 || $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

Рядки, позначені в "константа використання", визначають константу з ім'ям true, яка завжди оцінюється на 1, і константу з ім'ям false, яка завжди оцінюється на 0. Через те, як константи визначені в Perl, також виходять з ладу наступні рядки коду:

true = 0;
true = false;

Повідомлення про помилку повинно сказати щось на зразок "Неможливо змінити константу в скалярному призначенні".

Я бачив це в одному з коментарів, які ви запитували про порівняння рядків. Ви повинні знати, що оскільки Perl поєднує рядки та числові типи у скалярних змінних, у вас є різний синтаксис для порівняння рядків і чисел:

my $var1 = "5.0";
my $var2 = "5";

print "using operator eq\n";
if ( $var1 eq $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

print "using operator ==\n";
if ( $var1 == $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

Різниця між цими операторами є дуже поширеним джерелом плутанини в Perl.


5
use warnings;замість#! perl -w
Бред Гілберт

11
Використовувати константи як бідний манок макроси таким чином небезпечно. Ці приклади коду не еквівалентні: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, що може бути очевидним для випадкового спостерігача. (І так, останній приклад - поганий стиль програмування, але це поруч із сутью).
Зано

16

Рекомендую use boolean;. Вам потрібно встановити boolean модуль із cpan, хоча.


7
У Перлі, як і в житті, існує багато істин. Недосвідчені люблять писати дурні речі на кшталт if ($my_true_value == true). Прикидатися, що існує Єдина справжня правда, на мій досвід, це шлях до болю і неефективного коду.
tjd

2
Перл є філософським за своєю суттю
ILMostro_7

13

Мої улюблені завжди були

use constant FALSE => 1==0;
use constant TRUE => not FALSE;

яка повністю незалежна від внутрішнього представництва.


5
Блискуча. Ви однозначно зафіксували мову програмування Perl!
Nostalg.io

8

Я натрапив на підручник, в якому є чітке пояснення про те, які значення є правдивими та хибними в Perl . У ньому зазначено, що:

Наступні скалярні значення вважаються помилковими:

  • undef - невизначене значення
  • 0 число 0, навіть якщо ви записуєте його як 000 або 0,0
  • '' порожній рядок.
  • '0' рядок, який містить одну цифру 0.

Усі інші скалярні значення, включаючи наступне:

  • 1 будь-яке не-0 число
  • ' ' рядок з пробілом у ньому
  • '00' два або більше 0 символів у рядку
  • "0\n" a 0, після чого новий рядок
  • 'true'
  • 'false' так, навіть рядок "false" оцінюється як true.

Є ще один хороший підручник, який роз'яснює про Perl правдивим і хибним .


6

Прекрасне пояснення, яке дає bobf для булевих значень: правда чи помилково? Короткий довідник

Тести на істинність для різних значень

                       Result of the expression when $var is:

Expression          | 1      | '0.0'  | a string | 0     | empty str | undef
--------------------+--------+--------+----------+-------+-----------+-------
if( $var )          | true   | true   | true     | false | false     | false
if( defined $var )  | true   | true   | true     | true  | true      | false
if( $var eq '' )    | false  | false  | false    | false | true      | true
if( $var == 0 )     | false  | true   | true     | true  | true      | true

Погана відповідь, але сильне, поважне джерело на сайті perlmonks.org. Було б непогано мати якийсь реальний контент замість коментаря та посилання. : - /
ILMostro_7

0

використовуйте наступний префікс файлу, це додасть ваш сценарій perl eTRUE та eFALSE, він буде фактично істинним (!) істинним та хибним (як і java)

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

use constant { #real true false, compatible with encode_json decode_json for later (we don't want field:false... will be field:0...)
                eTRUE  =>  bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                eFALSE =>  bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
             };

Насправді мало причин, чому ви повинні використовувати це.

Моя причина полягає в тому, що, працюючи з JSON, я отримав 0 і 1 як значення ключів, але цей хак забезпечить збереження правильних значень уздовж вашого сценарію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.