On Tuesday, 23 June 2020 at 04:01:45 UTC, Denis wrote:
(1) Assign an unused value for the flag (e.g. -1 when the
function returns an int), and return the combined value/flag.
This happens in some Phobos algorithms, and might be the most
common on this list.
(2) Return a tuple with the value and the flag
(3) Return a struct or tuple with named value and flag members
Would certainly work, but I don't think it's common in D.
(4) Set the function return value normally, and put the flag in
an "out" variable passed as an argument to the function
(5) Return the flag, and put the value in an "out" variable
passed to the function (i.e. the reverse of #4)
Both of these happen. I don't know which is more common. In C#
these are probably the most common way (except for exceptions) to
signal these cases.
(6) Use two separate functions, one that returns the value, and
another that can be called afterwards to check the flag (like
eof(), for example)
(7) Use a side effect and set a designated global variable
Global variables are frowned upon, so probably not this. :p
One thing I feel is missing here (perhaps because
std.variant.Algebraic is egregious):
(8) Return a Maybe!T or Algebraic!(T, ErrorCode)
It's what I personally would prefer, but I have only rarely seen
it in D code. Given a properly written Maybe, this could enforce
proper handling of the error case, either by throwing on trying
to get at Maybe!T.getValue when it's holding None, or by
presenting an interface that only compiles when both cases are
covered, like fun().match((T t) => t, () => Error()).
--
Simen