I saw a post on the erlang-china.org asking this question reference has not understood iolist, what is the difference with list? Thank you for your advice ..
I have read the Erlang document for a long time and I haven't written it clearly, so let's look at the source code:
ERTs/emulator/beam/utils. c
Java code
- 3015int io_list_len (eterm OBJ)
- 3016 {
- 3017 eterm * objp;
- 3018 Sint Len = 0;
- 3019 declare_estack (s );
- 3020GotoRochelle again;
- 3021
- 3022While(! Estack_isempty (s )){
- 3023 OBJ = estack_pop (s );
- 3024 l_again:
- 3025If(Is_list (OBJ )){
- 3026 l_iter_list:
- 3027 objp = list_val (OBJ );
- 3028/* head */
- 3029 OBJ = car (objp );
- 3030If(Is_byte (OBJ )){
- 3031 Len ++;
- 3032}Else If(Is_binary (OBJ) & binary_bitsize (OBJ) = 0 ){
- 3033 Len + = binary_size (OBJ );
- 3034}Else If(Is_list (OBJ )){
- 3035 estack_push (S, CDR (objp ));
- 3036GotoRochelle iter_list;/* on head */
- 3037}Else If(Is_not_nil (OBJ )){
- 3038GotoRochelle type_error;
- 3039}
- 3040/* tail */
- 3041 OBJ = cdr (objp );
- 3042If(Is_list (OBJ ))
- 3043GotoRochelle iter_list;/* on tail */
- 3044Else If(Is_binary (OBJ) & binary_bitsize (OBJ) = 0 ){
- 3045 Len + = binary_size (OBJ );
- 3046}Else If(Is_not_nil (OBJ )){
- 3047GotoRochelle type_error;
- 3048}
- 3049}Else If(Is_binary (OBJ) & binary_bitsize (OBJ) = 0) {/* tail was binary */
- 3050 Len + = binary_size (OBJ );
- 3051}Else If(Is_not_nil (OBJ )){
- 3052GotoRochelle type_error;
- 3053}
- 3054}
- 3055
- 3056 destroy_estack (s );
- 3057ReturnLen;
- 3058
- 3059 l_type_error:
- 3060 destroy_estack (s );
- 3061Return-1;
- 3062}
3015int io_list_len (eterm OBJ) 3016 {3017 eterm * objp; 3018 Sint Len = 0; 3019 declare_estack (s); 3020 goto l_again; 30213022 while (! Estack_isempty (s) {3023 OBJ = estack_pop (s); 3024 l_again: 3025 if (is_list (OBJ) {3026 l_iter_list: 3027 objp = list_val (OBJ ); 3028/* head */3029 OBJ = car (objp); 3030 if (is_byte (OBJ) {3031 Len ++; 3032} else if (is_binary (OBJ) & binary_bitsize (OBJ) = 0) {3033 Len + = binary_size (OBJ); 3034} else if (is_list (OBJ) {3035 estack_push (S, CDR (objp); 3036 goto l_iter_list;/* on head */3037} else if (is_not_nil (OBJ) {3038 goto l_type_error; 3039} 3040/* tail */3041 OBJ = cdr (objp); 3042 if (is_list (OBJ) 3043 goto l_iter_list; /* on tail */3044 else if (is_binary (OBJ) & binary_bitsize (OBJ) = 0) {3045 Len + = binary_size (OBJ ); 3046} else if (is_not_nil (OBJ) {3047 goto l_type_error; 3048} 3049} else if (is_binary (OBJ) & binary_bitsize (OBJ) = 0) {/* tail was binary */3050 Len + = binary_size (OBJ); 3051} else if (is_not_nil (OBJ) {3052 goto l_type_error; 3053} 3054} 30553056 destroy_estack (s); 3057 return Len; 30583059 l_type_error: 3060 destroy_estack (s); 3061 return-1; 3062}
From the source code, we can see that iolist is defined as follows:
1. []
2. Binary
3. list, each element is int (0-255) or binary or iolist.
Binary indicates bitsize % 8 = 0.
Int is 0-255
Root @ Ubuntu:/usr/src/OTP # ERL
Erlang r13b04 (erts-5.7.5) [Source] [SMP: 2: 2] [RQ: 2] [async-threads: 0] [hipe] [kernel-Poll: false]
Eshell v5.7.5 (abort with ^ g)
2> iolist_size (<> ).
0
3> iolist_size (<1:1> ).
** Exception error: bad argument
In function iolist_size/1
Called as iolist_size (<1:1>)
4> iolist_size (<> ).
1
5> iolist_size ([]).
0
6> iolist_size (<1, 2> ).
2
7> iolist_size ([1, 2]).
2
8> iolist_size ([1, 2, <1, 2>]).
4
9> iolist_size ([1, 2, <1, 2>, [2]).
5
10> iolist_size ([1, 2, <1, 2>, [2]).
5
11> iolist_size ([<1:1>]).
** Exception error: bad argument
In function iolist_size/1
Called as iolist_size ([<1:1>])
12>
Iolist is used to send data to the port. because the underlying system calls such as writev Support Vector writing, unnecessary flat operations such as iolist_to_binary are avoided, which greatly improves the efficiency.
Recommended multi-purpose. Reproduced: http://mryufeng.iteye.com/blog/634867