[erlang-questions] On OTP rand module difference between OTP 19 and OTP 20

Richard A. O'Keefe <>
Fri Sep 1 05:40:00 CEST 2017

On 1/09/17 8:30 AM, Fred Hebert wrote:
> I think 'it depends' truly *is* the best way to go about it.

+1.  The universal expert's answer.  (The other is,
"some do, some don't.")  I'm going to nitpick gently.

> - A function does what is in the doc, but also does a bit more at the
>  same time. Do you fix by removing the additional functionality people
>  may now rely on, or by updating the doc to match the implementation?

There is no pressing need to do either.
Perhaps adding a note to the documentation that
"In some releases this function may accept additional
  arguments and appear to do sensible things.  This is
  subject to change."
is all that is required.

> - The documentation specifies that by sending the atom 'tsl1.3' you can
>  set up a TLS 1.3 connection, but the implementation only accepts
>  'tsl1.3' and crashes on 'tsl1.3'. Do you not update the documentation
>  for what was a typo, or do you add support for 'tsl1.3' as a
>  parameter?

You do both, and you add a note to the documentation that
"Earlier releases incorrectly accepted 'tsl1.3' instead of
  'tls1.3'.  This will be corrected in release N+2."

> - A function for socket handling returns values such as `{error, emfile
>  | enfile | econnrefused}`. Someone finds out that the syscalls it
>  relays data to also may return `{error, eperm | eaccess}` on top of
>  what was specified before. Do you swallow the errors and mask them, or
>  update the docs? Or is it not just a bug in the docs?

This one requires serious digging to find out.  I've been there,
though not with sockets.  Discovering that the C program you wrote
for "UNIX" version x reports an error in "UNIX" version y that
doesn't even exist in version x is a pain.  When I was working at
Quintus I spent weeks trawling through Unix manuals carefully
checking the error returns of every system call we used, and tried
to figure out what to do for each.  My aim was to classify errors
as - the program should not have done this (EINVAL &c)
    - the resource doesn't exist (ENOENT, ECHILD, ...) when it should
      or does exist (EEXIST) when it shouldn't
    - the resource named does exist but is the wrong kind of resource
    - the program doesn't have permission to do this (EPERM, ...)
    - the resource is busy (EBUSY, EDEADLK, ...)
    - some resource ran out (ENOMEM, ENFILE, EMFILE, EFBIG, ENOSPC,...)
    - something went wrong in the system (ENETDOWN, EHOSTDOWN, ...)
I eventually had to stop, but did write a little script using
the C preprocessor to dump all the macros obtained by including
<errno.h> and find all the E[A-Z0-9]+ ones, and check them against
the list of known ones.  It was a lot of work that I hoped POSIX
would render unnecessary in the future.  It didn't.

So this raises the quality-of-documentation issue, "Why did we ever
document this as only raising these specific errors?"

> - A function's doc says it sorts in a stable manner but it does not.
>  Which one should you change? There seems to be no winner on this one.

There is a very clear winner: fix the code.  When quicksort was
invented, it was known to do more comparisons than merge sort.
Hoare's problem was that he needed to sort a bunch of numbers on
a machine with 256 words of data memory, so that (a) he *really*
couldn't afford extra memory, and (b) comparisons were cheap.
Sedgewick's PhD thesis (which I did read once) did a very thorough
examination of quicksort performance and several variations on it,
BUT assumed that a comparison cost 1/4 as much as a memory reference.
Most comparisons of quicksort vs mergesort I've seen were misleading
because they compared numbers rather than strings or richer data
and because they compared a relatively smart quicksort implementation
against a pretty dump merge sort.  You can, for example,
  - do *optimal* sorting for small subfiles
  - not only ping-pong between the two arrays but run alternating
    passes backwards (this gets a bit more leverage out of the cache)
  - do 4-way merge instead of 2-way merge (does as many comparisons
    but is nicer to the memory subsystem)
and you can use a variant of the natural merge like samsort to
exploit existing order.

If you want an efficient algorithm with minimal space overhead,
there's a variant of heapsort that gets NlgN + O(N) comparisons
worst case, which beats quicksort.

> - A function logs information while it operates on data, but the
>  documentation makes no reference to it. Someone working with it in a
>  specific environment has issues with that behaviour.*

The documentation and the code both have to be changed.
The logging has to be made conditional, and the documentation
has to mention it.
> * In adding shell history to Erlang, we got tripped up on disk_log doing
>  just that. We added a new option to force it to be silent when needed,
>  for example, so both the code and the doc required a fix!

Ah, so I agreed with you on that one.  For the 2nd half of my concurrent
programming course, I have strongly recommended LYSE, so it's nice to
find myself on your side...

More information about the erlang-questions mailing list