エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

式を式のまま受け取り左辺と右辺を別々に評価する

Elixir のテストの assert は引数が一つで、一つの式を与えるのですが、左辺と右辺のそれぞれの値を把握しています。

例えば。

適当なプロジェクトを作り、

$ mix new foo
$ cd foo

テストをこんな風に書いて、

# test/foo_test.exs
defmodule FooTest do
  use ExUnit.Case

  test "1 + 2 == 4 ...?" do
    assert 1 + 2 == 4
  end
end

テストを実行してみると、

$ mix test


  1) test 1 + 2 == 4 ...? (FooTest)
     test/foo_test.exs:4
     Assertion with == failed
     code:  assert 1 + 2 == 4
     left:  3
     right: 4
     stacktrace:
       test/foo_test.exs:5: (test)



Finished in 0.02 seconds
1 test, 1 failure

こんな感じになります。

Elixir の assert はマクロで記述されていて、引数を評価前の式の構造のままで受け取ることで実現しているようです。

おもしろい…と思っていたのだけれど、似たようなことが Prolog でも書けることに気がつきました。

% foo_test.prolog

judge(L, L) :-
  format("OK", []),
  !.

judge(L, R) :-
  format("failed~n  left:  ~d~n  right: ~d~n", [L, R]).

assert(LHS == RHS) :-
  L is LHS,
  R is RHS,
  judge(L, R).

いつものように GNU Prolog で実行。

$ gprolog
GNU Prolog 1.4.4 (64 bits)
| ?- ['foo_test.prolog'].
| ?- assert(1 + 2 == 4).
failed
  left:  3
  right: 4

yes

述語 assert は引数に LHS == RHS という構造の式を受け取ります。Prolog では引数として式を書くと評価されずに式のまま述語に渡されます。受け取る側では式の形でマッチさせることで右辺と左辺を取り出すことができるわけです。

以前にも評価されるまで式の形のままで受け渡しができることを利用した Key-Value ペアを扱う方法について書きましたので、興味がある方はどうぞ。