5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Erlangの andalso は第2引数が boolean() じゃなくても良い

Last updated at Posted at 2014-06-03

概要

Erlangの短絡評価 andalsoorelse は第2引数が boolean() でなくても良い。
ここで「第2引数」とは「演算子の右の値」のことである。
ex. Expr1 andalso Expr2 の「第2引数」は Expr2 のこと。

andalsoorelse は次のような挙動を取る。

1> true andalso false.
false
2> true andalso ok.
ok
3> false orelse true.
true
4> false orelse ok.
ok

検証

さて、問題はこれが仕様かどうかである。

1. 公式ドキュメント

From R13A, Expr2 is no longer required to evaluate to a boolean value.

boolean valueである必要はないそうです。

参考URL: Erlang -- Expressions # 8.14 Short-Circuit Expressions

2. 一般的な短絡評価について

今まであまり気にしたことはなかったが、色々調べていると、この仕様はErlangだけではないみたいだ。

短絡評価.png

参考URL: 短絡評価 - Wikipedia

JavaScript、Perl、Ruby、Lisp等で似たような挙動があるみたいである。

また、内容は割愛するが、他にも以下のようなページに似たような内容のことがまとめられていた。

参考ページURL

以上より、 Expr1 andalso Expr2Expr1 orelse Expr2Expr2boolean() じゃなくて良いということである。

何ができるか

こんな際どい仕様を見つけて、何ができるのだろうか。

例えば、 defined_list() = [{Key::atom(), Value::any()}] | undefined からある Key に一致する Value を取り出すとしよう。
一般的には次のように書ける。

sample_code1.erl
get_value(_Key, undefined) ->
    {error, not_match}; %% NOT_MATCH_PROCESS
get_value(Key, DefiendList) ->
    case proplists:get_value(Key, DefinedList) of
        {Key, Value} -> {ok, Value};
        _            -> {error, not_match} %% NOT_MATCH_PROCESS
    end.

しかし、 orelse の第2引数が boolean() でなくてもよいことを使うと、もう少し短くコードを書くことができる。

sample_code.erl
get_value(Key, DefinedList) ->
    case DefinedList =:= undefined orelse proplists:get_value(Key, DefinedList) of
        {Key, Value} -> {ok, Value};
        _            -> {error, not_match} %% NOT_MATCH_PROCESS
    end.

※上記コードは説明で使うことを考え簡単に書いてあるため、そのままでは使えないと思われる。(エラー処理等)

このコードでは値がない場合の処理が短いのでそんなに得をした感じはしないが、値がない場合の処理(NOT_MATCH_PROCESS) {error, not_match} の部分の処理が長くなった場合、後者のように共通化しておいた方が、メンテコストは下がると思われる。

まとめ

Erlangの短絡評価 andalsoorelse は第2引数が boolean() でなくても良い。

ただ、可読性等もあるので、場所を選んで使って行きたい。


ちなみに…

上の8.14 Short-Circuit Expressionsの引用部分の後には次の様に続いている。

As a consequence, andalso and orelse are now tail-recursive. For instance, the following function is tail-recursive in R13A and later:

all(Pred, [Hd|Tail]) ->
    Pred(Hd) andalso all(Pred, Tail);
all(_, []) ->
    true.

僕は今はまだ短絡評価を末尾再帰で使った覚えはないが、使えるところがあれば使っていきたい。

5
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?