我有一个函数接受坐标(元组)作为其参数之一:
func({X, Y}, Something) when is_integer(X), is_integer(Y) -> ...
我想确保坐标:
我可以使用上面的防护,它可以正常工作。但是,我有许多使用坐标的函数,我想知道我是否可以以某种方式清理这个构造(一些宏?)所以会有类似的东西:
func(XY, Something) when ?is_coord(XY) -> ... % how to define ?is_coord
这样做是否有干净且惯用的方式?是erlang-ish吗?
修改
Erlang docs明确阻止防御性编程:
3.13不要“防御性地”编程
防御性程序是程序员不“信任”的程序 将数据输入到他们正在编程的系统部分。一般来说 一个人不应该测试输入数据到函数的正确性。大多数 系统中的代码应该假设为 输入有关功能的数据是正确的。只有一小部分 代码应该实际执行任何数据检查。这是 通常在数据第一次“进入”系统时完成一次 数据在进入系统后已经过检查 假设是正确的。
答案 0 :(得分:7)
有一个干净的,我认为相当于Erlang-ish的方式来定义is_coord
宏:
-define(is_coord(C), tuple_size(C) =:= 2
andalso is_integer(element(1, C))
andalso is_integer(element(2, C))).
func(Coord, Something) when ?is_coord(Coord) ->
...
请注意tuple_size/1也暗示is_tuple/1检查。
答案 1 :(得分:3)
这个快速黑客有效:
-define(GUARD(Name, Args), Name({X, Y}, Args) when is_integer(X), is_integer(Y)).
-export([myfun/2]).
?GUARD(myfun, [A, B, C]) ->
io:format("hi~n"),
ok.
虽然我个人并不喜欢它...如果您真的需要它,可能会进行解析转换:http://chlorophil.blogspot.com.ar/2007/04/erlang-macro-processor-v1-part-i.html,或者使用模板引擎预处理您的源代码,例如小胡子:https://github.com/mojombo/mustache.erl
希望它有所帮助!答案 2 :(得分:3)
Ning和marcelog的答案既好又高效,但我个人会让代码保持原样或使用其中一个,然后:
1)定义一个类型
-type point() :: {integer(),integer()}.
2)使用Erlang的dialyzer
答案 3 :(得分:3)
另一种方法是使用像guardian这样的解析变换库,并编写如下代码。
-compile({parse_transform, guardian}).
func(XY, Something) when is_coord(XY) ->
do(Something);
func(XY, A) ->
filering_out.
is_coord({X, Y}) when is_integer(X), is_integer(Y)->
true;
is_coord(_) ->
false.
将func函数转换为Ning的case语句函数所写的类似函数。
答案 4 :(得分:2)
您可以使用case
:
-module(lab).
-compile(export_all).
go() ->
func({1, 2}, "1st try"),
func({a, 2}, "2nd try"),
func({1, 2, 3}, "3rd try").
func(XY, Something) ->
case is_coord(XY) of
true -> io:format("~p~n", [Something]);
false -> io:format("Not a coord~n")
end.
is_coord(XY) ->
case XY of
{X, Y} when is_integer(X), is_integer(Y) ->
true;
_ ->
false
end.
试运行:
> c(lab), lab:go().
"1st try"
Not a coord
Not a coord
ok
答案 5 :(得分:1)
我刚刚意识到我们可以有另一种解决方案。
我们可以将coord
记录定义为:
-define(coord, {x = 0, y = 0}).
然后我们可以做到:
func(XY, Something) when is_record(XY, coord) -> ...
我们需要确保在创建x
记录时使用整数初始化y
和coord
。 (不应该很难:))
... X和Y都是整数 [已选中]
和is_record(XY, coord)
保证XY
的结构。
...是2项(X和Y)的元组 [已选中]
答案 6 :(得分:1)
我会说记录检查(is_record)不能保证两个元素都是整数。所以,如果你需要确保你有2个元素元组的元组,我会用
-define(is_coord(X), size(X)== 2 andalso is_integer(element(1,X)) andalso is_integer(element(2,X))).
rr(X) when ?is_coord(X) -> coord;
rr(_) -> not_coord.