Good practice of using void function return type?

K

Keith Thompson

Malcolm McLean said:
A function shuffles bits about in memory, a procedure activates an
external device attached to the computer.
What's wrong, illogical, or extraordinary about that? It's just
using the normal English words to make a distinction that anyone
could see is likely to be meaningful.

What's wrong with it is that the word "function" already has a well
defined meaning in C, and "procedure" has a well defined meaning
in a number of other programming languages.

The vast majority of programmers, if asked about the difference
between a function and a procedure, will say that a function
returns a value and a procedure doesn't, and will likely add that
C's version of a procedure is a void function.

You are, once again, insisting on using established words with
meanings that differ greatly from the way they're used *in the
context of programming*.

And how does your quoted definition of "procedure":

procedure
A process is a set or series of actions directed to some end or a
natural series of changes; a procedure is a series of actions
conducted in a certain manner, an established way of doing
something.

imply that it performs I/O? Surely a subroutine that does nothing
but bit twiddeling would qualify as a "procedure" under that
definition.

Do you also use the English language dictionary definitions of
"pointer", "variable", and "object" when discussing C programming?
(The use of "variable" in your quoted definition of "function"
is entirely inconsistent with the way it's commonly used in
programming.)

Let me rephrase the question I asked earlier: Can you cite an
independent source that uses the words "procedure" and "function"
in the way you do *in the context of computer programming*?
(An English dictionary definition does not qualify.)

If you don't wish to communicate, there are easier ways.
 
K

Keith Thompson

Malcolm McLean said:
When a program's internal state is corrupted it's almost always catastrophic.
But occasionally it won't crash out, agreed.

I don't recall anyone stating an assumption that the program's internal
state is corrupted. I though we were talking about error conditions in
general. (For example, if a program's only job is to write information
to stdout, aborting could be a reasonable reponse to a failure in
printf().)
 
J

Joe Pfeiffer

Malcolm McLean said:
I just did Google searches on "define".

A function is a mapping of a set of values to another set of values. It can be "undefined"
for some sets of inputs (e.g. 0/0), so the definition is hardly rigourous, but it's good
enough for general use.

First, it isn't the definition you gave before, and it isn't citing a
dictionary. Second, it isn't the definition used in C, which is what's
relevant here.
"Procedure" isn't a technical term at all. Every native English speaker knows what a
procedure is. There's no particular reason to use it in a special sense in computer
science, just because a few languages use the term in their jargon.

Well, yes, when discussing programming languages that's a very good
reason to use it in the same special sense they do. I'm still trying to
figure out what that has to do with performing I/O, though.
 
J

Joe Pfeiffer

Malcolm McLean said:
A function shuffles bits about in memory, a procedure activates an
external device attached to the computer.
What's wrong, illogical, or extraordinary about that? It's just
using the normal English words to make a distinction that anyone
could see is likely to be meaningful.

It isn't true of procedures in general strikes me as a perfectly good
reason to call it "wrong".
 
K

Keith Thompson

James Kuyper said:
On 05/15/2014 08:35 AM, BartC wrote: [...]
A lot of the time a return value is meaningless.

I've only rarely seen anything like that. The only example I can think
of was a procedure which was incapable of failing, but was defined as
returning a code to indicate whether or not it had succeeded. I changed
it to be a void function.

Another approach might be to give it a return value that indicates
whether it succeeded, but have it always return 0 to indicate
success. An advantage is that the interface doesn't have to
be changed if it's later modified so it can detect errors; also,
perhaps client code shouldn't have to care which functions can fail
and which can't. A disadvantage is that any error handling code
will never be executed, and so can't be tested.
I have seen functions that return a value that I don't need to know
(such as your printf() case below), but that's different from the value
being meaningless. I can imagine cases where it would be important to
know the value returned by printf(), though the issue has never come up
for me. In most cases, feof(stdout) and ferror(stdout) cover everything
I need to know.

When would ferror(stdout) be true?
A problem that can be dealt with completely internally is not a problem
that needs to be reported to the caller.

Another interesting case is the standard free() function, which can fail
catastrophically if the system's internal data structures have been
corrupted, but it has no way to report an error. Any such failure is a
consequence of undefined behavior, so there's no good way to handle it
anyway.
 
B

BartC

Malcolm McLean said:
A function shuffles bits about in memory, a procedure activates an
external device attached to the computer.
What's wrong, illogical, or extraordinary about that?

What's wrong about it is that a function can also activate an external
device, while a procedure can also shuffle bits in memory. They can both do
exactly the same things.

It's just that one directly returns a value (allowing it to be used in an
expression) and the other doesn't.
 
I

Ian Collins

Malcolm said:
"Procedure" isn't a technical term at all. Every native English speaker knows what a
procedure is. There's no particular reason to use it in a special sense in computer
science, just because a few languages use the term in their jargon.

So if I go in to hospital for a minor repair, is the surgeon performing I/O?
 
I

Ian Collins

BartC said:
C's printf() returns a value (the number of characters written); how many
times do you check that?

It also performs I?O, so in Malcolm's vocabulary, it's a procedure. Oh
wait, it returns a value so it must be a function. Oh wait, it does I/O
so it must be a procedure... Repeat until done.
 
G

glen herrmannsfeldt

(snip)
What's wrong with it is that the word "function" already has a well
defined meaning in C, and "procedure" has a well defined meaning
in a number of other programming languages.
The vast majority of programmers, if asked about the difference
between a function and a procedure, will say that a function
returns a value and a procedure doesn't, and will likely add that
C's version of a procedure is a void function.

As far as I know, in many cases PROCEDURE is uses as the generic
form, for either subroutine (void function) or function (returning
a value). I believe it is used that way now in the Fortran standard,
for example in the case of procedure pointers.
You are, once again, insisting on using established words with
meanings that differ greatly from the way they're used *in the
context of programming*.

It gets a little complicated, as words sometimes have a generic
computer science meaning that is different from the meaning in
some languages. If the language doesn't define the meaning, then
the generic CS meaning should be considered.

-- glen
 
J

James Kuyper

A lot of the time a function will just contain a sequence of statements.
Perhaps to break up a larger one or just to give some structure.

Would you do a status check every half-dozen statements? No, so why is it
necessary when you wrap a function body around the same statements?

A status check is necessary whenever something can go wrong. Lots of
statements have no possible failure mode, so there's no need to check
anything. The only significance of the function body is that a single
logical line of code in the caller results in the execution of many
lines in the called routine, increasing the likelihood that there's at
least one thing that could go wrong, and must therefore be reported. The
actual behavior should be the same, whether or not the code is wrapped
in a separate function body.

That's not quite true: I trust data values passed between different
parts of the same translation unit (TU), because it's generally easy to
confirm that they have been validated at least once before use. However,
whenever data is passed into one TU from some other part of the program,
I don't trust it, and insist on validating it. For instance, I check
pointers to make sure they're not null, and I take numbers that
determine what parts of an array will be used, and make sure they don't
have values that would result in out-of-range array accesses.

Therefore, if a bunch of lines in one function is pulled out, and put
into a separate function, *and the separate function is put in a
different TU*, then that separate function needs to validate all of the
values passed to it, and the calling function needs to validate any
information returned to it by that function. But this isn't because it's
a function, it's because it's in a separate TU.

If you are willing to trust across TU boundaries, then you would have a
correspondingly smaller need to validate data values.
(And what on earth would you check anyway, that the right-hand-side of an
assignment was successfully copied to the left side? Would you then also
have to check that the check was done properly? Etc.)

Why are you talking about assignment statements? I'm talking about
checking function calls; in particular, function calls that can fail,
for whatever reason - the reason depends upon the function. What I'm
checking for is, as indicated above, is whether or not the function
actually did fail. If the function can't fail, there's no need to check.
If it can fail, what seems odd to you about the fact that I want to
check whether it did?

....
So that's another example where no value need be returned.

Yes, exactly.
 
J

James Kuyper

James Kuyper said:
On 05/15/2014 08:35 AM, BartC wrote: [...]
A lot of the time a return value is meaningless.

I've only rarely seen anything like that. The only example I can think
of was a procedure which was incapable of failing, but was defined as
returning a code to indicate whether or not it had succeeded. I changed
it to be a void function.

Another approach might be to give it a return value that indicates
whether it succeeded, but have it always return 0 to indicate
success.

Yes, that's how it was originally written. It was actually a macro named
PGS_S_SUCCESS, but that macro happens to be #defined to 0.
An advantage is that the interface doesn't have to
be changed if it's later modified so it can detect errors; ...

In principle, that's always a possibility, but it seemed exceedingly
unlikely in this case. Unfortunately, I don't remember the details - but
the function body was no more than about three lines long; there just
wasn't much room for any detectable problem to occur, nor any plausible
reason why the function might someday be given larger responsibilities.
... also,
perhaps client code shouldn't have to care which functions can fail
and which can't. A disadvantage is that any error handling code
will never be executed, and so can't be tested.

It's because of that disadvantage that I choose to modify the routine.

....
When would ferror(stdout) be true?

When there's an I/O error while writing to stdout. That seems obvious,
so I suspect I've missed some aspect of your question.
 
J

James Kuyper

Oops! What I meant to write was:

When would feof(stdout) be true?

That makes more sense!

I had a vague idea that feof(stdout) should be true if stdout is
redirected to a file, and the file system that it's writing to runs out
of space, but a quick review of what the standard says about
"end-of-file" provides no support for that idea. I guess that should be
counted as an I/O error?

For 18 years now, most of the programs I've written do I/O mainly
through third-party libraries (HDF, HDF-EOS, and the SDP Toolkit),
rather than <stdio.h>. I don't use feof() or ferror() anywhere near as
often as I used to before I started work on this project. I don't think
I've got any code that passes an input file to feof(), but I suppose I
should check to make sure.
 
M

Malcolm McLean

Malcolm McLean wrote:

So if I go in to hospital for a minor repair, is the surgeon performing I/O?
He's performing what's normally called an "operation", from the Latin word
for "work", or a manipulation of the external environment.

A procedure is a sort of format or instruction set for an "operation",
or a "work". Now is an internal action an action? It's another case of
marginal set membership. Sometime we say that if a device is performing
internal actions but nothing externally, then it's "idling" or "doing
nothing". Other times we say "it's doing something to itself". It depends
on context. Sometimes an "action" must be external. If we say to the
putative surgeon, "how many people did you repair today?", and he had
three patients in theatre, but he also has a scratch on his leg which
slowly healing, normally you'd expect him to say "three", the marginal
case is excluded. But if you then point to the scratch on his leg
and say "why is that scabbing over?", he might say "it's repairing
itself". If you say "so actually you repaired four people today",
he might admit that you are in a sense correct.

Now if a computing device performs IO, that's another way of saying
that it manipulates something in the external environment. So
that's a core member of the set of "actions". If the computer
is moving space invaders about the screen in response to player
input, no one would say it's "idling". What if it's turned on
and in fact running the processor? It's a marginal case. Often
we'd say "it's not doing anything".

Now my use f the term "procedure" excludes the marginal case of
internal actions. That's normal and natural. You can sometimes
use the word in another context, e.g. "this procedure will remove
all the invalid pointers from the list". Now we're treating an
internal action as qualifying. Again, that's perfectly normal,
natural and unproblematic. By definition, marginal members of
a set are sometime included, sometimes included.

It's all perfectly simple, intuitive, and obvious, unless you
try to apply a mathematical mindset to English speech.
 
I

Ike Naar

There are two sorts of functions, function that do IO, and functions
that shuffle bits about in the computer memory.

That distinction seems a bit artificial.

There are functions that do both: many functions that do I/O also
shuffle bits about in the computer memory. If the I/O device is
mapped in memory (like, say, a file in a tmpfs filesystem under
linux, or an unnamed pipe) then a function that "does I/O" does in
fact nothing more than shuffle bits about in memory.

And then there are functions that do neither, e.g. sleep().
 
J

Joe Pfeiffer

Malcolm McLean said:
It's all perfectly simple, intuitive, and obvious, unless you
try to apply a mathematical mindset to English speech.

In this case, of course, everyone else in the discussion is applying a
mathematical mindset to a mathematical object (a program).
 
M

Malcolm McLean

In this case, of course, everyone else in the discussion is applying a
mathematical mindset to a mathematical object (a program).
A compiler can't use natural language. So I've given a crisp,
unambiguous definition of "function" and "procedure" which can
coded and enforced automatically. A function can only shuffle bits
about in the computer's memory, it can't do IO. (So it can't read
any bits, for example, which might be affected by an external
device in the course of execution, the state of the program on
function exit is always completely defined by the state on function
entry). A procedure can do IO. So a procedure may call a function
or another procedure, but a function may not call a procedure.

But you can't apply the crisp, programming definition to the English
word "procedure" itself and say "That's what it means. It means what
Malcolm has said and may never be used in any other context." Or
alternatively, "Malcolm has no right to use that word. He must invent
a special one". That's the inappropriate mathematical thinking.
 
L

luser droog

Now you have. Progress.


Uh oh. Another failing grade from Headmaster Kiki.

Hmmmm. What if Kenny and Keith are the same person,
playing a long-con smeagol/Gollum soliloquy for us.
 
K

Keith Thompson

Malcolm McLean said:
A compiler can't use natural language. So I've given a crisp,
unambiguous definition of "function" and "procedure" which can
coded and enforced automatically.

And these "crisp, unambiguous" definitions of yours blatantly
conflict with the way those words are routinely used *in the context
in which you're using them*.

[...]
But you can't apply the crisp, programming definition to the English
word "procedure" itself and say "That's what it means. It means what
Malcolm has said and may never be used in any other context." Or
alternatively, "Malcolm has no right to use that word. He must invent
a special one". That's the inappropriate mathematical thinking.

The relevant context is programming, not mathematics. Mathematical
functions and software functions are, or at least can be, quite
different.

If this many people were unanimously telling me that I was using words
in a confusing manner, I'd seriously consider the possibility that they
were right and I was wrong.
 
D

David Brown

A function shuffles bits about in memory, a procedure activates an
external device attached to the computer.
What's wrong, illogical, or extraordinary about that? It's just
using the normal English words to make a distinction that anyone
could see is likely to be meaningful.

You really like these personal Malcolm McLean specific definitions that
are "obvious" to "normal" English speakers, don't you?

In normal English, the word "function" has multiple meanings. It also
has a particular meaning in mathematics, multiple meanings in computer
science, and a specific definition in C. You don't get to pick one of
these and call it /the/ definition, and then blame C for disagreeing
with you.

This is a C newsgroup - we talk mostly about C, or related topics. So
when you use the word "function", everyone here understands it to mean
"C function", unless the context makes it clear (such as "the function
of this software is to annoy the user as efficiently as possible"). If
you want to talk specifically about functions that produce results
dependent solely on their inputs, and have no side-effects, then these
are commonly referred to as "pure functions".

There are no commonly used terms to make the distinctions you describe
between "functions that shuffle bits around" and "procedures that do
IO". So if you want to talk about these, you have to say what you mean,
such as "functions with externally visible effects".
 

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

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top