如何测试一个Elixir(或erlang)值是否可以写成二进制
问题描述:
我认为这个问题与询问如何检查值是否为io_list
相同。我希望这样做尽可能高效,因此不希望将该值转换为二进制文件,作为检查它是否为io_list的一部分。如何测试一个Elixir(或erlang)值是否可以写成二进制
答
在浏览了Erlang的stdlib之后,我相信你的最佳选择是使用:erlang.iolist_size
并捕获ArgumentError
来检测无效的iolist。
iolist? = fn x ->
try do
:erlang.iolist_size(x)
true
rescue
ArgumentError -> false
end
end
IO.inspect iolist?("foo")
IO.inspect iolist?(["foo"])
IO.inspect iolist?(:foo)
输出:
true
true
false
在我的高度不科学的标杆,这大约是三倍快:erlang.iolist_to_binary/1
。
iolist = List.duplicate([[[1, "2"], '3'], ?4], 1000000)
IO.inspect :timer.tc(:erlang, :iolist_to_binary, [iolist])
IO.inspect :timer.tc(:erlang, :iolist_size, [iolist])
{82291,
<<1, 50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1,
50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1, 50, 51, 52, 1,
50, 51, 52, 1, 50, 51, 52, 1, ...>>}
{25577, 4000000}
我不认为有任何函数来检查这一点,但我相信调用'iolist_size/1'的价值和醒目'ArgumentError'应该是相当快的。如果它引发'ArgumentError',它不是一个有效的iolist。 – Dogbert
不管你做什么,为了检查是否是io_list,系统将不得不遍历(可能的)io_list中的每个元素。你永远不应该*不知道*你自己的程序产生了什么数据。如果它是来自不可信来源的代码,那么您必须验证它,无论如何,从那时起应该知道。真正的答案是在编译时使用Dialyzer,而不是运行时检查。 – zxq9