为什么 Perl 使用空字符串来表示布尔假值? [英] Why does Perl use the empty string to represent the boolean false value?

查看:18
本文介绍了为什么 Perl 使用空字符串来表示布尔假值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在标量(布尔)上下文中计算表达式时,如果表达式计算为真,Perl 使用显式值 1 作为结果,如果表达式计算为假,则使用空字符串作为结果.我很好奇为什么 Perl 使用空字符串来表示布尔假值而不是 0 看起来更直观.

When evaluating an expression in a scalar (boolean) context, Perl uses the explicit value 1 as a result if the expression evaluates to true and the empty string if the expression evaluates to false. I'm curious why Perl uses the empty string to represent boolean false value and not 0 which seems more intuitive.

请注意,我不关心 Perl 在标量(布尔值)上下文中将空字符串视为 false.

Note that I'm not concerned with Perl treating the empty string as a false in scalar (boolean) context.

编辑

使用真字符串(例如"false")作为假值的字符串表示如何改变现有代码的含义?我们是否可以说在这样的更改之后更改语义的代码不如它本来的健壮/正确?我猜字符串上下文在 Perl 中非常普遍,导致语义合理的唯一选择是布尔值是否在往返字符串后保留其值...

How would using string which is true ("false" for instance) as a string representation of false values change the meaning of existing code? Could we say that code that changes semantics after such a change is less robust/correct than it could have been? I guess string context is so pervasive in Perl that the only option leading to sane semantics is if boolean value preserve its value after round tripping to and from a string...

推荐答案

各种逻辑运算符不返回空字符串,它们在所有三种简单标量类型中都返回 false 或 true 值.它看起来只是返回一个空字符串,因为 print 在其参数上强制使用字符串上下文:

The various logical operators don't return an empty string, they return a false or true value in all three simple scalar types. It just looks like it returns an empty string because print forces a string context on its arguments:

#!/usr/bin/perl

use strict;
use warnings;

use Devel::Peek;

my $t = 5 > 4;
my $f = 5 < 4;

Dump $t;
Dump $f;

输出:

SV = PVNV(0x100802c20) at 0x100827348
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 1
  NV = 1
  PV = 0x100201e60 "1"
  CUR = 1
  LEN = 16
SV = PVNV(0x100802c40) at 0x100827360
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x100208ca0 ""
  CUR = 0
  LEN = 16

对于那些不熟悉 Perl 5 内部结构的人来说,PVNV 是一个标量结构,它包含所有三种简单的标量类型(整数 IV、双精度浮点 NV 和字符串 PV).标志 IOKNOKPOK 表示整数、双精度和字符串值都是同步的(对于某些同步定义) 所以它们中的任何一个都可以使用(即,如果您将其用作整数、双精度数或字符串,则不需要进行转换).

For those not familiar with the Perl 5 internals, a PVNV is a scalar structure that holds all three simple scalar types (integer IV, double precision float NV, and string PV). The flags IOK, NOK, and POK mean that the integer, double, and string values are all in sync (for some definition of in sync) so any one of them may be used (i.e. no conversions need to take place if you use it as an integer, double, or string).

我假设为假字符串选择了空字符串,因为它更小并且"0"更符合假字符串的概念.忽略我关于它更小的声明,"""1" 的大小相同:16 个字符.它在转储中说得很好.Perl 5 为字符串添加了额外的空间以允许它们快速增长.

I assume the empty string was chosen for the false string because it is smaller and is more in keeping with the idea of a false string than "0". Ignore my statement about it being smaller, both "" and "1" are the same size: sixteen characters. It says so right in the dump. Perl 5 adds extra space to strings to allow them to grow quickly.

哦,我讨厌你.在研究这个时,我发现我在 perlopquick 撒谎,现在必须找到一种方法来解决它.如果你能像其他羊一样,接受 Perl 5 表面的怪异事实,我的工作就会少一些.

Oh, and I hate you. In researching this I have found that I have lied in perlopquick and will now have to find a way to fix it. If only you had been like all of the other sheep and just accepted Perl 5's surface weirdness as fact, I would have less work to do.

对编辑部分中问题的回答:

Answers to the questions in the EDIT section:

使用真字符串(例如假")作为假值的字符串表示如何改变现有代码的含义?

How would using string which is true ("false" for instance) as a string representation of false values change the meaning of existing code?

关于 PL_sv_yes 和 PL_sv_no(比较运算符返回的规范 true 和 false 值)的唯一特殊之处在于它们是只读的,并且由 perl 创建,而不是由正在运行的程序创建.如果您更改它们,则不会更改真实性测试,因此设置为 "false" 的 PL_sv_no 将被视为真.您甚至可以使用 perl 的未记录功能自己完成(此代码在 Perl 5.18 和最新 Perl 之间的某个时间点停止工作):

The only special things about about PL_sv_yes and PL_sv_no (the canonically true and false values returned by comparison operators) are that they are read only and are created by perl not the program that is running. If you change them, it does not change the truthiness test, so a PL_sv_no that is set to "false" will be treated as true. You can even do this yourself (this code stops working at some point between Perl 5.18 and the latest Perl) using undocumented features of perl:

#!/usr/bin/perl

use strict;
use warnings;
use Scalar::Util qw/dualvar/;

BEGIN {
        # use the undocumented SvREADONLY function from Internals to
        # modify a reference to PL_sv_no's readonly flag
        # note the use of & to make the compiler not use SvREADONLY's
        # prototype, yet another reason prototypes are bad and shouldn't
        # be used
        &Internals::SvREADONLY(!!0, 0);

        # set PL_sv_no to a dualvar containing 0 and "false"
        ${!!0} = dualvar 0, "false";
}

if (5 < 4) {
        print "oops
";
}

输出

opps

这是因为真实性测试首先查看字符串.

This is because the truthiness test looks at strings first.

我们是否可以说在这样的更改之后更改语义的代码不如它本来可以做到的那么健壮/正确?

Could we say that code that changes semantics after such a change is less robust/correct than it could have been?

它会被直接破坏.即使您限制自己将其设置为 int 0 或字符串0"(两者均为假),它也会破坏一些有效代码.

It will be straight up broken. Even if you restrict yourself to setting it to an int 0 or a string "0" (both of which are false), it will break some valid code.

我猜字符串上下文在 Perl 中非常普遍,导致语义合理的唯一选择是布尔值是否在往返字符串后保留其值...

I guess string context is so pervasive in Perl that the only option leading to sane semantics is if boolean value preserve its value after round tripping to and from a string...

是的.

这篇关于为什么 Perl 使用空字符串来表示布尔假值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆