[erlang-questions] Proposal for is_iolist/1 guard

Richard O'Keefe ok@REDACTED
Wed May 27 01:10:47 CEST 2009

On 26 May 2009, at 11:57 pm, Maxim Treskin wrote:

> Hello
> I see, erlang does not have is_iolist/1 guard, while iolist() type  
> used in some places in OTP (i.e. ports interaction).
> Is it possible to add this BIF?

Possible?  Certainly.
Wise?  You will get a long argument about that one!

 From http://www.erlang.org/doc/man/erlang.html

	iodata() = iolist() | binary()
	iolist() = [char() | binary() | iolist()]
		   a binary is allowed as the tail of the list

is_iodata(B) when is_binary(B) -> true;
is_iodata(L) -> is_iolist(L).

is_iolist([]) -> true;
is_iolist([X|Xs]) when is_integer(X), X >= 0, X =< 255 ->
is_iolist([X|Xs]) ->
     case is_iodata(X)
       of true -> is_iodata(Xs)
        ; false
is_iolist(_) -> false.

I think I've got that right.

Now guards are a special sublanguage in Erlang.
They are supposed to be fast.  The one thing that
stops them always being fast is that length/1 is
allowed, which was arguably a mistake.  However,
at least length/1 is tail recursive, so all
existing guards can execute in bounded space, if
not (thanks to length/1, drat it) bounded time.
But if you look at the is_iodata/1 and is_iolist/1
functions above, you will see body recursion (just
after 'case').  Of course this could be implemented
some other way without actually using Erlang or C
function calls to do it.  Converting recursion to
iteration is an old and very well understood game.
You still need some kind of stack.  So this appears
to require unbounded space.

Actually, there's another old technique that could
be used:  pointer reversal, keeping the stack in the
list one is examining.  So I believe that with fairly
extreme care, this *could* be implemented to run in
bounded space in an Erlang system.  If this were an
exceptionally useful operation, it might be worth it.
I doubt it though.

Now that we have the Dialyzer, it's worth investigating
to what degree you can check this kind of thing without
_any_ run-time test.

But body recursion it is,

     if is_integer(X), X >= 0, X =< 255 -> is_iodata(Xs)
      ; is_binary(X) -> is_iodata(Xs)
      ; true -> case is_iolist(X)
                  of true -> is_iodata(Xs)


More information about the erlang-questions mailing list