頭の体操のために作ってみました。
特に意味はありませんが、GitHubにリポジトリを上げました。
元ネタ: Can (a ==1 && a== 2 && a==3) ever evaluate to true?
他の言語の先駆者:
- a == 1 && a == 2 && a == 3がtrueになるRubyスクリプト
- a == 1 and a == 2 and a == 3 がTrueになるPythonスクリプト
- C言語でもa == 1 && a == 2 && a == 3をtrueにしてみたい
追記:
別の書き方を思いついたので載せておきます。
(a == 1 && a == 2 && a == 3) を常に真にできますか? その2
簡単なあらまし
元ネタのサイトにありますが、変数aを1にも2にも3にも等しくするということです。
一見すると訳が分かりませんが、これを疑似コードで表すと、次の通りです。
if a == 1 && a == 2 && a == 3:
print("True!")
解法として様々あるようです。
- aをオブジェクトとして呼ばれる度にaの戻り値を変更する
- aの後ろの半角スペースをハングルの半角スペースにすることで別の変数として処理する
僕の考えた最強の解法
自分で考えて、とりあえず実装してみた2つを紹介します。
シジルの変更によって全ての真偽値判定を真にする
シジルとは、スカラや配列を表す$
や@
といった、Perlにおいて変数の種類を表すために、変数の前に付ける記号のことです。
Perl固有の書き方ができます。
use strict;
use warnings;
my $a = 1;
my @a = (1, 2);
sub a { 3 };
if ($a == 1 and @a == 2 and &a == 3) {
print "True!\n";
}
$ perl by_changing_sigil.pl
True!
元ネタではJavascriptが対象のため、Perlを用いる場合は変数aにシジルを付けなければなりません。
この時にシジルを変更することで、簡単に戻り値を変えることができます。
$a == 1;
# 変数$aと1が等しい場合は真を返す。
@a == 2;
# 配列@aの要素数と2が等しい場合は真を返す。
&a == 3;
# 関数&aの戻り値と3が等しい場合は真を返す。
ちなみにand
演算子で繋げていますが、&a
が見づらくなるために変更しているだけで、&&
でも同じ動作をします。
==
演算子のオーバーロードによって全ての真偽値判定を真にする
overload
モジュールを使うことで、オブジェクトにおける演算子のオーバーロードができます。
これを利用して、==
演算子による処理を変更します。
package AllEqualObject;
use overload
"==" => \&operator_eq;
sub new {
my $self = shift;
bless [@_], $self;
}
sub operator_eq {
my $self = shift;
return 1;
}
1;
package main;
use strict;
use warnings;
my $a = AllEqualObject->new;
if ($a == 1 && $a == 2 && $a == 3) {
print "True!\n";
}
$ perl by_overloading_operator.pl
True!
ここでは、AllEqualObject
のインスタンスで==
を利用すると、operator_eq
関数を呼出し、数値1を返します。
Perlにおいて数値1は真なので、$a == 1
でも$a == 0
でも$a == -1
でも真を返します。
終わりに
小さいことですが、いろいろ勉強になりました。
ここまで読んでくださってありがとうございました!
もしおかしい点、気づいた点がありましたら教えてください。
特に、もっと面白い解法がある場合は教えてくれると嬉しいです!