7

我是新来的。在阅读了如何提问和格式化之后,我希望这是一个可以的问题。我对 perl 不是很熟练,但它是我最了解的编程语言。

我尝试将 Perl 应用到现实生活中,但我没有得到很好的理解——尤其是从我的妻子那里。我告诉她:

如果她晚上没有给我带来3杯啤酒,那意味着我得到了零(或没有)啤酒。

正如您可能猜到的那样,没有太大的成功。:(

现在事实上。从perlop

一元“!” 执行逻辑否定,即“非”。

语言,什么有boolean类型(什么只能有两个“值”)是可以的:

如果它不是一个值 ->必须是另一个值。

很自然:

!true  -> false
!false -> true

但是 perl 没有boolean变量 - 只有一个truth system, whrere everything is not 0, '0' undef,''是 TRUE。当对非逻辑值(例如数字)应用逻辑否定时,问题就来了。

例如,如果某个数字不是 3,那意味着它是零或空,而不是现实生活中的意义,如果某物不是 3,则意味着它可以是除 3 之外的任何东西(例如,也为零)。

所以接下来的代码:

use 5.014;
use Strictures;

my $not_3beers = !3;

say defined($not_3beers) ? "defined, value>$not_3beers<" : "undefined";
say $not_3beers ? "TRUE" : "FALSE";

my $not_4beers = !4;
printf qq{What is not 3 nor 4 mean: They're same value: %d!\n}, $not_3beers if( $not_3beers == $not_4beers );
say qq(What is not 3 nor 4 mean: @{[ $not_3beers ? "some bears" : "no bears" ]}!) if( $not_3beers eq $not_4beers );

say ' $not_3beers>',  $not_3beers, "<";
say '-$not_3beers>', -$not_3beers, "<";
say '+$not_3beers>', -$not_3beers, "<";

印刷:

defined, value><
FALSE
What is not 3 nor 4 mean: They're same value: 0!
What is not 3 nor 4 mean: no bears!
 $not_3beers><
-$not_3beers>0<
+$not_3beers>0<

而且:

perl -E 'say !!4'

什么不是 4 IS 1,而不是 4!

上面对妻子的陈述是“错误的”(意思是 0):),但真的试图教我儿子Perl,过了一会儿,他问我妻子:为什么,如果某物不是 3 意味着它是 0 ?.

所以问题是:

  • 如何向我儿子解释这个
  • 为什么 perl 有这个设计,那么为什么!0每次都是 1
  • 这里有什么“背后”需要!0的不是任何随机数,而是 0。
  • 正如我已经说过的,我不太了解其他语言-每种语言都是!3 == 0
4

4 回答 4

12

我认为您过多地关注否定,而很少关注 Perl 布尔值的含义。

历史/实施视角

什么是真理?检测到高于 x 伏特的电压。

在更高的抽象级别上:如果此处设置了此位。

位序列的抽象可以被认为是一个整数。这个整数是假的吗?是的,如果没有设置位,即整数为零。

面向硬件的语言很可能会使用这种对真理的定义,例如 C,以及所有 C 的后代,包括 Perl。

的否定0可以是按位否定——所有位都被翻转到1——,或者我们只是将最后一位设置为1。结果通常会被解码为整数-11分别,但后者更节能。

务实的观点

当我们处理计数时,将除零以外的所有数字都视为真是方便的:

my $wordcount = ...;

if ($wordcount) {
  say "We found $wordcount words";
} else {
  say "There were no words";
}

或者

say "The array is empty" unless @array;  # notice scalar context

像 Perl 这样的实用语言可能会认为零是错误的。

数学视角

任何数字都没有理由是假的,每个数字都是一个定义明确的实体。真或假仅通过谓词、可以是真或假的表达式出现。只有这个真值可以被否定。例如

¬(x ≤ y) where x = 2, y = 3

是假的。许多在数学上有坚实基础的语言不会考虑任何错误,而是特殊的错误值。在 Lisp 中,'()ornil通常为假,但0通常为真。也就是说,一个值只有在它不为 nil 时才为真!

在这样的数学语言中,!3 == 0很可能是类型错误。

回复:啤酒

啤酒很好。任何数量的啤酒都是好的,只要你有一个:

my $beers = ...;

if (not $beers) {
  say "Another one!";
} else {
  say "Aaah, this is good.";
}

啤酒计数变量的布尔化只会告诉我们您是否有啤酒。考虑!!成为一个布尔化运算符:

my $enough_beer = !! $beers;

布尔化并不关心确切的数量。但也许任何 ≥ 3 的数字都是好的。然后:

my $enough_beer = ($beers >= 3);

否定是不够的啤酒:

my $not_enough_beer = not($beers >= 3);

或者

my $not_enough_beer = not $beers;

fetch_beer() if $not_enough_beer;

Perl 标量并不代表整个宇宙。特别是,not 3不是所有非三个实体的集合。表达式3是真值吗?是的。因此,not 3是一个虚假的价值。

建议的4 == not 3to be true 行为可能是不可取的:4并且“所有非三的事物”并不相等,四只是众多非三事物之一。我们应该正确地写它:

4 != 3    # four is not equal to three

或者

not( 4 == 3 )   # the same

!将andnot视为logical-negation-of可能会有所帮助,但不会将其视为except

如何教学

可能值得引入数学谓词:可以为真或假的表达式。如果我们只通过显式测试“创造”真实性,例如length($str) > 0,那么您的问题就不会出现。我们可以将结果命名为: my $predicate = (1 < 2),但我们可以决定永远不将它们打印出来,而是:print $predicate ? "True" : "False"。这回避了考虑truefalse的特殊表示的问题。

直接考虑值是真/假将只是一个捷径,例如foo if $x可以被认为是一个捷径

foo if defined $x and length($x) > 0 and $x != 0;

Perl 是关于快捷方式的。

教授这些快捷方式以及 perl 的各种上下文以及它们出现的位置(数字/字符串/布尔运算符)可能会有所帮助。

  • 列出上下文
    • 偶数列表上下文
  • 标量上下文
    • 数值上下文
    • 字符串上下文
    • 布尔上下文
  • 空上下文
于 2013-07-05T15:30:33.770 回答
8
  • 正如我已经说过的,我不太了解其他语言-每种语言都是!3 == 0?
  • 是的。在 C(以及因此在 C++)中,它是相同的。

    void main() {
        int i = 3;
        int n = !i;
        int nn = !n;
        printf("!3=%i ; !!3=%i\n", n, nn);
    }
    

    打印(见http://codepad.org/vOkOWcbU

    !3=0 ; !!3=1
    

  • 如何向我儿子解释这个
  • 很简单。!3意思是“与一些非假值相反,这当然是假的”。这称为“上下文”——在否定运算符强加的布尔上下文中,“3”不是数字,它是真/假的陈述。

    结果也不是“零”,而仅仅是一种方便 Perl 表示 false 的东西 - 如果在数字上下文中使用它会变成零(但如果在字符串上下文中使用则为空字符串 - 请参阅 和 之间的0 + !3区别!3 . "a"

    布尔上下文只是一种特殊的标量上下文,不会执行到字符串或数字的转换。( perldoc perldata)


  • 为什么 perl 有这个设计,那么为什么 !0 每次都是 1

  • 这里有什么“背后”需要比 !0 不是任何随机数,而是 0。
  • 除了实现的简单性之外,别无他法。生成“1”比生成随机数更容易。

  • 如果你问一个不同的问题“为什么它是 1 而不是原来的 # 被否定得到 0”,答案很简单——当 Perl 解释器否定那个 0 时,它不再知道/记得零是“!3”的结果,而不是导致值为零/假的其他表达式。

于 2013-07-05T14:32:19.080 回答
3

如果你想测试一个数字不是 3,那么使用这个:

my_variable != 3;

使用语法!3,因为!是一个布尔运算符,首先转换3为布尔值(即使perl可能没有正式的布尔类型,它仍然以这种方式工作),由于它是非零的,这意味着它被转换为等价于true. 然后,!true产生false,当转换回整数上下文时,得到0。继续该逻辑显示如何!!3转换3true,然后将其反转为false,再次反转回true,如果此值用于整数上下文,则转换为1。大多数现代编程语言都是如此(尽管可能不是一些更以逻辑为中心的语言),尽管确切的语法可能因语言而异......

于 2013-07-05T14:47:13.133 回答
0

从逻辑上否定一个假值需要选择一些值来表示结果的真值。“1”是一个不错的选择。我想说返回哪个值并不重要(或者相反,重要的是您不要依赖任何返回的特定真实值)。

于 2013-07-05T14:21:38.913 回答