truthy の意味を考えた

truthyという単語は英和辞書には載っていない。ネットで英英辞書もいくつか見てみたが載っていなかった。

trueっぽい、というような意味だと思ってはいたが、きちんと調べたことがなかったので調べてみた。

この言葉を知ったきっかけは、Minitest の refute のエラーメッセージだ。Minitest と test-unit の refuteRailsassert_not は動きとしては同じなので、truthy は「真」という意味だと思った。

(「真」という言葉についてはこちらの記事)


Minitest refuteのエラーメッセージ

Expected #<Blog:0x00007f9da82c2a20> to not be truthy.

オブジェクトは truthy でないことが期待されています。


test-unit refuteのエラーメッセージ

<#<Blog:0x00007f973c845ff0>> is neither nil or false.

オブジェクトは nil でも false でもありません。


ActiveSupportRailsassert_notのエラーメッセージ

Expected #<Blog:0x00007f9da82c1440> to be nil or false

オブジェクトは nil または false であることが期待されています

truthy とは?

JavaScript において、 truthy は Boolean コンテキストに現れた時に true とみなされる値のことです。 falsy として定義された値 (つまり、false, 0, -0, 0n, "", null, undefined, NaN) を除くすべての値は truthy です。
Truthy - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDNS

truthyで検索したら最初にこれが出てきた。JavaScript の話だけど参考になりそう。Ruby では nilfalse 以外は「真」。やっぱり truthyは、この「真」という意味のようだ。

ただ、引っかかるのがこれ。assert_notの定義部分に書いてあるコメントだ。

rails/assertions.rb at 77932446895bd70f38a3aaa1ab288bf8a7b7142c · rails/rails · GitHub

# Asserts that an expression is not truthy. Passes if <tt>object</tt> is
# +nil+ or +false+. "Truthy" means "considered true in a conditional"
# like <tt>if foo</tt>.
#
#   assert_not nil    # => true
#   assert_not false  # => true
#   assert_not 'foo'  # => Expected "foo" to be nil or false
#
# An error message can be specified.
#
#   assert_not foo, 'foo should be false'
def assert_not(object, message = nil)
  message ||= "Expected #{mu_pp(object)} to be nil or false"
  assert !object, message
end

表現が truthy ではないことを主張します。オブジェクトが nil か false の場合にパスするのです。"truthy" は if foo のように "条件付きで true とみなされる" ことを意味します。

先日も書いたのだが、DeepLさんで訳すとこんな感じになった。

truthyが「真」という意味だったら、Ruby において下の2つは同じ意味になるはずだ。

  • オブジェクトは truthy でないことが期待されています
  • オブジェクトは nil または false であることが期待されています

truthy でない => 「真」でない => 偽である => nil または false である

どこが問題なのかわからない。

ところで、refuteの反対のassertはどうなっているだろうと思って調べてみた。

class BlogTest < ActiveSupport::TestCase
  test "assertのテスト" do
    obj = nil
    assert obj
  end
end

RailsActiveSupport)のテストを失敗させてエラー文を見てみた。truthyが入っている!

Expected nil to be truthy.

assertメソッドの定義場所を調べたら Minitest だった。こちらは assert_not とは違い ActiveSupport では定義されていないようだ(つまりスーパークラスの Minitest のメソッドがそのまま使われる)。

minitest/assertions.rb at master · seattlerb/minitest · GitHub

# Fails unless +test+ is truthy.

def assert test, msg = nil
  self.assertions += 1
  unless test then
    msg ||= "Expected #{mu_pp test} to be truthy."
    msg = msg.call if Proc === msg
    raise Minitest::Assertion, msg
  end
  true
end

結局、assertは Minitest のがそのまま使われていて、assert_notエイリアスでもなくわざわざ ActiveSupport で定義されているということしかわからなかった。これからassert_notの歴史を調べる予定なので、そこで何かわかるかもしれない。

まとめ(まとまってない)

truthyについて自分なりにまとめると以下のようになる(が、全然自信はない)。

truthyは、trueっぽいというような意味で、「真」という意味合いで使われることもあるが、正確には「条件付きでtrueとなる」という意味であり、Ruby ではあまり使わない言葉(JavaScript と違って Ruby ドキュメントでは 英語版/日本語版 どちらにも出てこないので)。

ここまで書いて気づいた。「条件付きでtrueとなる」は "considered true in a conditional" の訳のつもりだが、これって「真偽判定するとtrueになる」って意味なのでは?

conditional に a がついているということは名詞っぽい。名詞だと「条件文」という意味がある!エラーメッセージを変えたいから別で定義したと思い込んでたときに訳したので先入観があったかもしれない。

Asserts that an expression is not truthy. Passes if object is nil or false. "Truthy" means "considered true in a conditional" like if foo.

式が truthy(真)でないことを明らかにします。オブジェクトが nil か false の場合にパスします。"truthy(真)"は if foo のように "条件文で true とみなされる" ことを意味します。

が正解かも!エラーメッセージは単により明確にしただけのことかもしれない。DeepLさんにはいつもお世話になってるけどやっぱり英語の勉強も大事。

となるとやはりtruthyは「真」という意味でよさそう。もし違ったら教えてください。お願いします。