Boost logo

Boost :

From: Rob Stewart (stewart_at_[hidden])
Date: 2002-08-02 09:39:56


        <000301c238bc$53dcc6a0$0100a8c0_at_kbmain><01e501c238d7$e251c910$4100a8c0_at_CEREBUS><006801c2393a$b16de190$d53afea9_at_[hidden]>
        <027101c2398d$6160eff0$4100a8c0_at_CEREBUS>
        <003501c23a14$59c1df70$d53afea9_at_[hidden]>
X-BeenThere: boost_at_[hidden]
X-Mailman-Version: 2.1b1
Precedence: bulk
Reply-To: boost_at_[hidden]
List-Help: <mailto:boost-request_at_[hidden]?subject=help>
List-Post: <mailto:boost_at_[hidden]>
List-Subscribe: <http://lists.boost.org/mailman/listinfo.cgi/boost>,
        <mailto:boost-request_at_[hidden]?subject=subscribe>
List-Id: Boost mailing list <boost.lists.boost.org>
List-Unsubscribe: <http://lists.boost.org/mailman/listinfo.cgi/boost>,
        <mailto:boost-request_at_[hidden]?subject=unsubscribe>
List-Archive: http://lists.boost.org/MailArchives/boost/
X-List-Received-Date: Fri, 02 Aug 2002 14:34:29 -0000

From: "Richard Peters" <R.A.Peters_at_[hidden]>
>
> David Brownstein wrote:
> >
> >> IMHO, this is completely the wrong direction. It always bothers me
> >> if return values are misused as error codes. When a function returns
> >> a value, it should be the result of a calculation, that is what
> >> functions do.
> > I disagree- many functions perform operations. For example, I hardly
> > think that the sockets function select() could be thought of as a
> > "calculation". Is writing a file a "calculation"?
>
> You are right, they aren't functions, they're operations, or procedures (in my
> view). I find this the most annoying thing in C/C++. I usually see 'void
> something(params)' as a procedure, not as a function returning void. I like Pascal's
> 'procedure ...' better. (though in templates, C++'s form can be quite convenient)

I view functions as a body of code that you can call. What it does and what it
returns is a function -- no pun intended -- of its implementation. The function
name should reveal a little something about the purpose and behavior of the
function, of course.

> The result of a function (ie, T something(params) with T != void) should reflect
> something about its parameters, though. IMO, errors don't belong to this.

I have no such biases.

> A function may have side effects, but it shouldn't consist of side effects alone.

I don't agree with this statement. Then again, I don't have a Pascal bias and
I'm not a theoretical mathmetician such that I take "function" in its C/C++
application to mean something so pure.

> I'd rather write void DoSomething(char& somevalue) in those cases.

I'd find that quite awkward as I couldn't use DoSomething()'s return value in
another function call, a conditional, etc. I also couldn't create and
initialize a char in the same statement:

   char a(DoSomething());

> If you write a = DoSomething(), you think "Hey! Something happens to a!"

I'm afraid I don't think that. I think, "Hey! DoSomething() does something and
returns a value that is copied into a."

> If you write DoSomething(a), you think "Hey! Something happens!" and when you look
> closer, you see that also something happens with a, but that that thing is less
> significant to the purpuse of the function. The most important thing that happens
> here are the things in DoSomething, not the value of a.

I'm afraid I don't think that either. I think that DoSomething() does something
using the value of a. If DoSomething() were named otherwise, I might think it
was manipulating a. However, making "a" a parameter doesn't change my view that
calling DoSomething() means that I'm invoking some code. If DoSomething()'s
name doesn't evoke how it uses its parameters and what its return value might
indicate, then it is poorly named. IOW, if DoSomething() were to return a
Boolean value, I would expect it to start with "is" -- or some variant
(std::vector<>::empty() notwithstanding).

> When select() times out, it returns 0. That's exactly its postcondition: The select
> function returns the total number of socket handles that are ready and contained in
> the FD_SET structures.
> When an error occurs in select() (which almost never happens, IIRC), it returns -1,
> an error. If it threw an exception, your code would be pretier, you just load the
> result of select into a counter, and check for counter times your FD_SET. Now you
> have to add code for -1 _at the wrong place_ in your code. You can choose where to
> put your exception handlers, you can't choose where to put your error handling code.

The C library -- and those that follow suit -- approach of combining error codes
and return values is a bad idea. If a function only returns a returns an error
code, however, that can often be simpler than having it throw an exception.
However, if you need to ensure that the error is not ignored, an exception is
still the best choice. There's also the consideration that with exceptions,
code can allow the exception to propagate to higher-level code for handling,
whereas with return codes, the caller must detect the error and then return an
error code or throw an exception itself. The point is that the choice between
exception and error code is non-trivial. There are many considerations one must
make.

-- 
Rob Stewart                           stewart_at_[hidden]
Software Engineer                     http://www.sig.com
Susquehanna International Group, LLP  using std::disclaimer;

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk