2009年06月05日 03:30 [Edit]

js/perl/python/ruby/scheme - 真偽のほどはいかに

追加で調べたのは

  • NaNとInfの扱い - 作り方と真偽値
  • 「ジェネリック」な真偽値

JavaScript

Perlと以外と似ている。

  • NaNはNaN、InfはInfinityという名で組み込み
  • ジェネリックな真はtrue、偽はfalse
#!/usr/bin/js

tell_me_the_truth = function(s){
    var p;
    eval('p = ' + s);
    if (p){
        print('\'' + s + '\' (' + p + ')' + ' is TRUE.');
    }
    else{
        print('\'' + s + '\' (' + p + ')' + ' is FALSE.');
    }
};
tell_me_the_truth('true');
tell_me_the_truth('false');
tell_me_the_truth('0');
tell_me_the_truth('1');
tell_me_the_truth('0.0');
tell_me_the_truth('NaN');
tell_me_the_truth('NaN === NaN');
tell_me_the_truth('isNaN(NaN)');
tell_me_the_truth('Infinity');
tell_me_the_truth('Infinity - 1');
tell_me_the_truth('Infinity - Infinity');
tell_me_the_truth('"0"');
tell_me_the_truth('"0.0"');
tell_me_the_truth('""');
tell_me_the_truth('[]');
tell_me_the_truth('{}');
tell_me_the_truth('null');
tell_me_the_truth('undefined');
tell_me_the_truth('!!undefined');
tell_me_the_truth('!!1');

Perl

  • NaNは'nan'+0、Infは'inf'+0
  • 他にも()(空リスト)、空配列、空ハッシュが偽。
  • ジェネリックな真は1、偽は''(空文字列;数値コンテキストでは0扱い)
#!/usr/bin/perl
use strict;
use warnings;

our $nan = 'nan' + 0;
our $inf = 'inf' + 0;

sub tell_me_the_truth{
    my $s = shift;
    my $p = eval $s;
    local $\ = "\n"; # say
    if ($p){
        print "'$s' ($p) is TRUE."
    }
    else{
        print "'$s' ($p) is FALSE."
    }
};

tell_me_the_truth('0');
tell_me_the_truth('1');
tell_me_the_truth('0.0');
tell_me_the_truth('$nan');
tell_me_the_truth('$nan == $nan');
tell_me_the_truth('$inf');
tell_me_the_truth('$inf - 1');
tell_me_the_truth('$inf - $inf');
tell_me_the_truth('"0"');
tell_me_the_truth('"0.0"');
tell_me_the_truth('""');
tell_me_the_truth('my @a = ()');
tell_me_the_truth('my %h = ()');
tell_me_the_truth('[]');
tell_me_the_truth('{}');
tell_me_the_truth('undef');
tell_me_the_truth('!!undef');
tell_me_the_truth('!!1');

Python

  • NaNはfloat('nan')、Infはfloat('inf')
  • !演算子はない。代わりにbool()を使える。
  • ジェネリックな真はTrue、偽はFalse
#!/usr/bin/python

nan = float('nan')
inf = float('inf')

def tell_me_the_truth(s):
    p = eval(s);
    if p:
        print "\'%s\' (%s) is TRUE." % (s, p)
    else:
        print "\'%s\' (%s) is FALSE." % (s, p)


tell_me_the_truth('True')
tell_me_the_truth('False')
tell_me_the_truth('0')
tell_me_the_truth('1')
tell_me_the_truth('0.0')
tell_me_the_truth('nan')
tell_me_the_truth('nan == nan')
tell_me_the_truth('inf')
tell_me_the_truth('inf - 1')
tell_me_the_truth('inf - inf')
tell_me_the_truth('"0"')
tell_me_the_truth('"0.0"')
tell_me_the_truth('""')
tell_me_the_truth('()')
tell_me_the_truth('{}')
tell_me_the_truth('[]')
tell_me_the_truth('None')
tell_me_the_truth('bool(None)')
tell_me_the_truth('bool(1)')

Ruby

  • NaNは0.0/0.0、Infは1.0/0.0で作ることができるが、リテラルはないようだ。
  • ジェネリックな真はtrue、偽はfalse
#!/usr/bin/ruby

@nan = 0.0/0.0
@inf = 1.0/0.0

def tell_me_the_truth(s)
    p = eval(s)
    if p
        puts "'#{s}' (#{p}) is TRUE."
    else
        puts "'#{s}' (#{p}) is FALSE."
    end
end

@elist = ();

tell_me_the_truth('true')
tell_me_the_truth('false')
tell_me_the_truth('0')
tell_me_the_truth('1')
tell_me_the_truth('0.0')
tell_me_the_truth('@nan')
tell_me_the_truth('@nan == @nan')
tell_me_the_truth('@inf')
tell_me_the_truth('@inf - 1')
tell_me_the_truth('@inf - @inf')
tell_me_the_truth('"0"')
tell_me_the_truth('"0.0"')
tell_me_the_truth('""')
tell_me_the_truth('@elist')
tell_me_the_truth('{}')
tell_me_the_truth('[]')
tell_me_the_truth('nil')
tell_me_the_truth('!!nil')
tell_me_the_truth('!!1')

Scheme

Rubyにとても似ている。というよりRubyがとても似ている。

  • NaNは(/ 0 0)、Infは(/ 1 0)で作ることができる。
  • #Fのみ偽。以外は全部真。空リストすら真。
  • ジェネリックな真は#T、偽は#F
  • !!はないが、そもそも演算子という考え方そのものがなく、関数のみであり、!!も普通に定義することが出来る
#!/usr/bin/gosh
(define (tell_me_the_truth s)
  (let ((p (eval s (interaction-environment))))
   (if p 
       (print "(" s ") " p " is TRUE")
       (print "(" s ") " p " is FALSE"))))

(define (! p) (not p))
(define (!! p) (not (not p)))

(tell_me_the_truth 0)
(tell_me_the_truth 1)
(tell_me_the_truth "")
(tell_me_the_truth '())
(tell_me_the_truth #f)
(tell_me_the_truth '(/ 0 0))
(tell_me_the_truth '(= (/ 0 0) (/ 0 0)))
(tell_me_the_truth '(/ 1 0))
(tell_me_the_truth '(- (/ 1 0) 1))
(tell_me_the_truth '(- (/ 1 0) (/ 1 0)))
(tell_me_the_truth '(! 1))
(tell_me_the_truth '(!! 1))

まとめ

各言語におけるtrue/falseまとめ - 床のトルストイ、ゲイとするとのこと
まあこんな感じで、言語によって真偽値の事情は異なるので、 if 文では比較演算子などを省略しない方が安心ですね!!

まさしく。特にRubyとSchemeはそう。あと、!演算子を持つ言語であれば、真偽値を強制するのには!!を使うとよい。

Dan the Man with Too Many Different Trues and Falses to Check


この記事へのトラックバックURL

この記事へのコメント
SchemeはR6RSから、NaNとInfについては +nan.0, +inf.0, -inf.0 というリテラルをサポートしています。Gaucheでも使えます。

(/ 0 0), (/ 1 0)をどう評価するかは処理系依存です。ゼロ除算エラーにする処理系もあります。
Posted by shiro at 2009年06月05日 07:19