Björn Gustavsson <bjorn(at)erlang(dot)org>
Final/R12B-0 Proposal is implemented in OTP release R12B-0
Standards Track

EEP 6: New BIFs for tuple and binary sizes #

Abstract #

This EEP describes the two new guards BIFs tuple_size/1 and byte_size/1 as a preferred alternative to the size/1 BIF.

Specifications #

byte_size/1::bitstring() -> integer()

Returns the number of bytes needed to store the entire bitstring (see EEP 4). This BIF will return the same value as (bit_size(Bin)+7) div 8 (that is, the number of bytes will be rounded up if number of bits is not evenly divisible by 8). This BIF is allowed in guards.

tuple_size/1::tuple() -> integer()

Returns the size of a tuple. This BIF will fail if passed anything that is not a tuple. This BIF is allowed in guards.

Rationale #

The size/1 BIF accepts either a binary or a tuple, and returns either the size of binary in bytes or the size of the tuple.

Because size/1 accepts two different types, it is difficult to optimize uses of it, both in the compiler and in the run-time system. Adding the two new BIF will facilitate optimization, and will also help Dialyzer.

It could be argued that byte_size/1 should only work for binaries (bitstrings whose size in bits is disivible by 8) to catch the bug that the code cannot handle general bitstrings and still does not use an is_binary/1 guard test. In my opinion, if the programmer must round up the result from bit_size/1 to a whole number of bytes, he or she is more likely to get that wrong: The “obvious” expressions bit_size(B) / 8 + 1 or bit_size(B) div 8 + 1 are both wrong, and the correct expression (bit_size(B)+7) div 8 is not immediately obvious.

Implementation #

The implementation is trivial.

Backwards Compatibility #

Code containing local functions named tuple_size/1 or byte_size/1 need to be changed.

The compiler will issue a warning that size/1 is deprecated and will be removed in R14B for code that uses size/1.