【问题标题】:Perl booleans, negation (and how to explain it)?Perl 布尔值,否定(以及如何解释)?
【发布时间】:2013-07-03 16:22:44
【问题描述】:

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

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

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

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

现在事实上。来自perlop

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

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

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

很自然:

!true  -> false
!false -> true

但是 perl 没有 boolean 变量 - 只有一个 truth system,而所有的东西都不是 0'0' undef'' 是 TRUE。问题来了,当将 逻辑否定 应用于 非逻辑值 例如数字。

例如如果某个数字 IS NOT 3,那就意味着它 IS ZERO 或为空,而不是 现实生活 的意思,如果某物不是 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'

什么是不是41,而不是4!

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

所以问题是:

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

【问题讨论】:

  • 我觉得这里试图提出一些深刻的论点我只是看不出它是什么。
  • 要和我的妻子和啤酒一起尝试 perl 的逻辑 :)
  • 我没有喝过三杯啤酒。这是否意味着我已经喝了四瓶啤酒?
  • 可能你的妻子使用了重载的! 运算符。 :) 检查overload::Overloaded $beer
  • ! 运算符适用于布尔值。表达式!3!(3 != 0) 的简写,括号中的表达式表示被否定的隐式布尔值。因为(3 != 0) 为真或1,它的否定为0 或假。这就是为什么!3 == !4

标签: perl


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    • 正如我已经说过的,我不太了解其他语言 - 在每种语言中都是 !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 表示“与 some 非假值相反,这当然是假的”。这称为“上下文”——在否定运算符强加的布尔上下文中,“3”不是数字,它是真/假的陈述。

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

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


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

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

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

    【讨论】:

    • +!0 :) 这就是我所说的 THE answer 对于“不容易”的问题。 ;) 不错。
    【解决方案3】:

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

    my_variable != 3;
    

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

    【讨论】:

      【解决方案4】:

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

      历史/实施视角

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

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

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

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

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

      务实的视角

      当我们处理计数时,方便将除零之外的所有数字都视为true

      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
      

      是假的。许多在数学上有坚实基础的语言不会考虑任何错误,而是特殊的错误值。在 Lisps 中,'()nil 通常为假,但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 3 的建议行为为真可能是不可取的:4 和“所有不是三的事物”不相等,四个只是众多事物之一不是三个。我们应该正确地写它:

      4 != 3    # four is not equal to three
      

      not( 4 == 3 )   # the same
      

      !not 视为logical-negation-of 可能会有所帮助,而不是except

      如何教学

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

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

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

      Perl 是关于快捷方式的。

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

      • 列表上下文
        • 大小均匀的列表上下文
      • 标量上下文
        • 数字上下文
        • 字符串上下文
        • 布尔上下文
      • 空上下文

      【讨论】:

      • +~0 。从来没有希望得到类似的答案。非常感谢您。是的,这是不存在boolean 变量和boolean operations 之间的区别。 Perl 没有 bool 变量,而是 doing 布尔运算。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      相关资源
      最近更新 更多