DEV Community

loading...

Erlang/OTP で <<15,254>> を <> にする方法

voluntas
A software developer using Erlang/OTP at work. Founder of 時雨堂 (shiguredo).
・1 min read

もう、何度も作っててツラくなってきた。早く標準ライブラリとして実装して欲しい。

今後皆が使うべき実装

<< <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= <<0,1,253,255>> >>.

よく使ってた実装

> list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= <<0,1,254,255>> ]).
<<"0001FEFF">>
-spec hexlify(binary()) -> binary().
hexlify(Binary) ->
    list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= Binary ]).

もっとシンプルで早い方法があれば是非教えて欲しい。

皆様の実装

https://twitter.com/k0u_chang/status/600686773279199232

> << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= <<0,1,253,255>> >>.
<<"0001FDFF">>

https://twitter.com/hio/status/600690978287013888

> << <<(X + if X < 10 -> $0; true -> $A - 10 end)>> || <<X:4>> <= <<0,1,254,255>> >>.
<<"0001FEFF">>

https://gist.github.com/sile/c8df7cc9a106c7d86039

コンパイルをすると ...

測定大会

環境

Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
> timer:tc(fun() -> list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= list_to_binary(lists:seq(0,255)) ]) end).
{3486,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
> timer:tc(fun() -> << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= list_to_binary(lists:seq(0,255)) >> end).
{6650,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
> timer:tc(fun() -> << <<(X + if X < 10 -> $0; true -> $A - 10 end)>> || <<X:4>> <= list_to_binary(lists:seq(0,255)) >> end).
{9026,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}

https://gist.github.com/sile/c8df7cc9a106c7d86039

実行は提案者の環境

> timer:tc(fun() -> hexlify:hex1(list_to_binary(lists:seq(0,255))) end).                                                                   
{220,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}

> timer:tc(fun() -> hexlify:hex2(list_to_binary(lists:seq(0,255))) end).
{36,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
-module(hexlify).

-export([hex1/1, hex2/1]).

hex1(Bin) ->
  list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= Bin ]).

hex2(Bin) ->
  << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= Bin >>.

Discussion (0)