Paranoid about style/elegance and function size, please quell

T

Tony

I am not C++ expert in any way.
I like the combination of procedural style and oo style in C++. There
are many things which best be treated in oo style. There are just a
few things which bested be treated in procedual style.
Take y = sin(x). This calculation in my view best be treated as is
like in math, in procedural style. C++ gives us both styles, I think
it is a good thing.
In Java, y = sin(x) is a member of Math class. I found Java way is not
natural.
Tony
 
K

kanze

John Potter said:
On 1 Jul 2003 15:34:11 -0400, Francis Glassborow
ostream& operator<< (ostream&, string const&);
iterator vector<T>::insert(iterator, T const&);

void vector<T>::insert(iterator, size_type, T const&);

I don't think you can quote the C++ library for examples of good design.
There are a few: separating the formatting from the sinking/sourcing in
iostream, for example. But on the whole... Even within a single class,
it can't be consistent.
Your statement is acceptable, but not your intent. Whenever there is
any way to use the imagination to create a sensible return, the
function is not void. Void is a last resort used in inverse
proportion to the sensibleness of the user. :)

If you have to use your imagination or your creativeness to invent a
return value, you probably would be better off with void. What should a
function like EventGenerate::enrolForEvent( EventHandler& ) return, for
example? Or the callback EventHandler::eek:perator()( Event const& ) ?

Generally speaking, if the purpose of a function is to obtain a value,
then that value should be returned by means of the return of the
function. Otherwise, if the function can fail in an unexceptional way,
the return value should be the error code. Otherwise, in general, the
return value should be void -- there are a few cases where supporting
chaining imposes some other return value, but they aren't that often.
 
K

kanze

Sean Fraley said:
E. Robert Tisdale wrote:
Once again, why?

In that case, one could just as easily ask: why not? The fact that some
forms of std::vector::erase return iterator, and others return void, is
obviously poor design.

But that begs the point. The fact that there are times when some
"procedures" should logically return a value (and thus become functions)
doesn't mean that all should. The initial argument was that using
"procedures" makes reasoning about the program impossible, and results
in spaghetti code. Just returning some random value, which might
eventually permit chaining, won't make the program easier to
understand. In fact, I'd argue just the opposite -- if the statement
contains just one procedure invocation, and nothing else, I know that it
does exactly what that procedure does. Once you start chaining
functions with side effects (i.e. procedures with return values), you're
making things even more complex and difficult to understand. This
argument actually weighs in in favor of what Francis originally stated:
if the function isn't really a function, then don't fool the reader by
making it look like one. (The words are mine, but I think they more or
less correspond with what Francis meant.) I would qualify it somewhat:
there are procedures which can "fail" in expected (non-exceptional)
ways, for which using a return value to indicate error state would be
appropriate.

And in real life, we do need procedures. If I call a procedure to write
something to a file, or to display something on the screen, it had
better have some side effects.
 
J

John Potter

Of course not, but if you head for a clear and concise(?) style than
you might find procedures sometimes the most valuable tool. Just
have a look at the STL - there those procedures are called algorithms
and more often than not having a void return.

You seem to count funny. I get void returns on 30 of 102 algorithms.
Existence: yes, majority: no. Sorting accounts for 18 of the 30.

John
 
F

Francis Glassborow

In message said:
This
argument actually weighs in in favor of what Francis originally stated:
if the function isn't really a function, then don't fool the reader by
making it look like one. (The words are mine, but I think they more or
less correspond with what Francis meant.) I would qualify it somewhat:
there are procedures which can "fail" in expected (non-exceptional)
ways, for which using a return value to indicate error state would be
appropriate.

Yes that is much my view. If a procedure can fail in ways that influence
the rest of the program I normally give it a return type of bool. Note
that that has nothing to do with whatever the procedure was doing, it is
just an effective way of reporting failure.

Indeed only yesterday I wrote some code that went like this:

bool dosomething(mytype & mt){
try {
// do various things that modify mt
// but always leave mt stable
return true;
}
catch(...) {return false;}
}

In the circumstances I did not care what had gone wrong, just that it
had not worked as intended. Of course this function is also terrible
because it uses SEME :)
 
E

Ed Avis

And you should make sure no-one confuses a procedure with
a function. One way to achieve that is to make sure functions never
have side effects and procedures never return results.

I fear this may turn into another SESE-ish discussion. While such a
style is often useful, I wouldn't like to mandate it for all code, all
of the time. Inherently stateful things like an I/O library don't
really need to follow the rule, since it is obvious that
print_string() has a side effect, whether or not it returns void.

It would help if compilers had some way for the programmer to assert
that a function has no side effects, and have this statically
checked. I think gcc has some weird attribute you can set on a
function to say it is pure and so calls to it may be optimized away,
but it's the programmer's responsibility to make sure the annotation
is sound.
 
E

E. Robert Tisdale

Francis said:
And you were responding to Mr. Tisdale's rewriting of what I had written.

Your function

void foo(void){
std::cout << std::clock();
}

modifies a global variable -- cout.
 
R

Rob

Francis Glassborow said:
And if that is done by a system call? What should I then return?

There are only three possibilities.

1) The system call can never fail, so there is no point in returning
anything.

2) The system call can fail, and no recovery is possible in the function
making the call. In this case the error needs to be reported.
That may be done by returning an error code or (if an error should
never be ignored) throwing an exception.

3) If the system call can fail, but recovery is possible by the function
making the call, then the appropriate action needs to be determined
by what the caller needs to be told about. [This is a mix of 1 and
2].

In the end it comes down to what the caller needs to know about and what
it can reasonably be expected to cope with.
 
K

kanze

(e-mail address removed) (Dave Harris) wrote in message
Right. And you should make sure no-one confuses a procedure with a
function. One way to achieve that is to make sure functions never have
side effects and procedures never return results.

So what do you do with rand()? (I like the rule, but there are
exceptions.)

--
James Kanze GABI Software
mailto:[email protected]
Conseils en informatique orientée objet/
http://www.gabi-soft.fr
Beratung in objektorientierter
Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45
16
 
D

Dave Harris

So what do you do with rand()?

Rand ought to be an object anyway:

class {
int state; // or whatever
public:
void srand( int seed );
void advance();
int current() const;
// int next() const { advance(); return current(); }
};

(I like the rule, but there are exceptions.)

I agree there are exceptions. Another possible exception is having a
procedure return information about whether it succeeded.

These can be eliminated, of course, and some people say they always
should be, but I don't take that extreme view. The circumlocutions
sometimes have drawbacks which are worse than the problem they
solve.

-- Dave Harris, Nottingham, UK
 
F

Francis Glassborow

E. Robert Tisdale said:
Your function

void foo(void){
std::cout << std::clock();
}

modifies a global variable -- cout.

So? being a global it is available for anyone to check. Indeed if they
are really paranoid they can switch on exception behaviour for streams.
 
F

Francis Glassborow

Ed Avis said:
I am just thinking of a relatively high-level interface such as

class Screen {
XXX display(Graphic);
};

XXX could be void or it could be Screen&, returning *this. The latter
style would let you chain display() calls, if you are so inclined.

And if you read my original guideline it said something that included
that possibility. Tisdale may have taken us down this path but he was
disagreeing with a guideline that most seem to approve of. I wasn't the
OP but my guidelines were a response to his post. Tisdale claimed that
the guideline was a bad one. I have seen nothing to change my mind.
 
E

E. Robert Tisdale

James Kanze:
So what do you do with rand()?
(I like the rule, but there are exceptions.)

The rand() function was a *bad* idea for a number of different reasons.
It should be replace with a Uniform Random Number Generator

class URNG {
private:
// state representation
public:
// operators
int operator()(void);
// constructors
URNG(unsigned int seed);
};

int main(int argc, char* argv[]) {
URNG rand(0);
// use rand()
return 0;
}
 
L

llewelly

E. Robert Tisdale said:
James Kanze:


The rand() function was a *bad* idea for a number of different reasons.
It should be replace with a Uniform Random Number Generator

class URNG {

Yes, however, let's please not give it a name which looks like a cross
between a macro and punch to the gut. Anyway, boost has some
rather nice random number generators.
private:
// state representation
public:
// operators
int operator()(void);
// constructors
URNG(unsigned int seed);
};

int main(int argc, char* argv[]) {
URNG rand(0);
// use rand()
return 0;
}
[snip]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,102
Messages
2,570,646
Members
47,247
Latest member
GabrieleL2

Latest Threads

Top