Good practice of using void function return type?

Discussion in 'C Programming' started by dspfun, May 15, 2014.

  1. Sure, I'm not the person trying to stop people using the term "function"
    in the C standard context.
    I would like to grab the term "pure function", but unfortunately it already
    has a very specific meaning, which is

    double square_root(double x)
    {
    double answer;
    /* run a root finder of some sort */
    return answer;
    }

    is a pure function.

    extern in errno;

    double square_root(double x)
    {
    double answer;
    if(x < 0)
    {
    errno = -1;
    return nan();
    }
    /* run root finder */
    return answer;
    }

    is not, because it has an external effect.

    So why not use "pure function" in a different context? You could do
    that, but that's inventing or imposing a new meaning, as opposed to
    picking one of the existing, generally accepted meanings of "function"
    and making it clear that you're using the word with that meaning.
     
    Malcolm McLean, May 16, 2014
    #41
    1. Advertisements

  2. dspfun

    David Brown Guest

    That is correct.

    But in programming (C or otherwise), it is useful to distinguish between
    "pure functions" and "non-pure functions", because "pure functions" can
    be optimised and analysed in ways that you cannot do with non-pure
    functions. (This is a major reason why functional programming
    languages, which put great emphasis on pure functions, are much more
    amenable to formal correctness analysis.) There is /no/ useful
    distinction in programming between "functions/procedures that do I/O"
    and "functions/procedures that don't do I/O" - because there is no
    distinct definition of I/O.
    Well, you already seem perfectly happy to pick your own meanings for
    existing terms.

    But I am not advocating using "pure function" to mean anything but its
    standard computer science meaning (except perhaps in the context of gcc
    function attributes, where the attribute "pure" declares an almost-pure
    function, and the attribute "const" declares a /really/ pure function).
     
    David Brown, May 16, 2014
    #42
    1. Advertisements

  3. dspfun

    BartC Guest

    I thought you were in favour of leaving a compiler to get on with it instead
    of giving it optimisation hints?

    (Because, apart from introducing portability issues, it can cause a problem
    when editing changes the function's pureness but the attribute is not
    updated.)
     
    BartC, May 16, 2014
    #43
  4. dspfun

    David Brown Guest

    I like Zen here - not too much, and not too little. So sometimes my
    arguments will vary, depending on the other posters. Maybe I'm just
    feeling argumentative. (Write a post entitled "the sky is blue", and
    see if I take the bait...)

    In this particular case, I will sometimes mark functions with the gcc
    "pure" or "const" attribute. It gives the compiler more information -
    it is not directing its optimisations, but merely allowing them. And it
    also gives the compiler extra information for compile-time checks to
    enforce the pureness or constness. (I don't know if gcc actually
    implements such checks, but it could do.)
    True enough. It is not something I would use on a long or complex
    function - it should be pretty clear that the implementation is "pure"
    or "const". And it is mostly used on functions where it is obvious that
    the implementation should be "pure" or "const", such as mathematical
    functions.
     
    David Brown, May 16, 2014
    #44
  5. dspfun

    David Brown Guest

    But those are not "crisp" or "unambiguous" - at best, they are rough
    statements of intent for your "Malcolm-functions" and "Malcolm-procedures".

    What happens when your Malcolm-function "shuffles a bit" that triggers
    an I/O operation? "int foo(int *p) { int x = *p; *p = 1; return x;}"
    looks like it is just "shuffling bits". But if called with "p" equal to
    0 it might cause a fault leading to a screen output of an error message,
    or a core dump causing disk activity, or nasal daemons which are
    certainly input/output. What happens if it triggers a swap file
    movement - that's I/O ? There are endless ways for Malcolm-functions to
    cause I/O.

    And of course the opposite is also true - a "Malcolm-procedure" might
    not cause I/O depending on its inputs, or on the system as a whole. The
    "Malcolm-procedure" might contain a printf, but if the program is called
    with the output redirected to /dev/null then there is no output.


    There are good reasons why Malcolm-functions and Malcolm-procedures are
    not standard terms.
     
    David Brown, May 16, 2014
    #45
  6. That has to be disallowed.
    Passing volatile memory, where reading and writing has side effects that
    might affect program state in ways defined by the external environment
    mean that it's not a function. There's not a one to one mapping of bit
    state on function entry to bit state on function exit.

    You can make Malcolm-functions into "pure functions" by disallowing
    pointers and globals. But there's no easy way of enforcing that in C that
    doesn't radically change the language.
     
    Malcolm McLean, May 16, 2014
    #46
  7. No, it means it's not a "Malcolm-function".
     
    Keith Thompson, May 16, 2014
    #47
  8. Let me see if I can do this one...

    "Global" must mean something that more detail-oriented, drone
    thinkers might call "static storage duration", otherwise

    int f(void) { static int i; return i++; }

    would be a pure function. And, presumably, "disallowing pointers and
    globals" is to be interpreted as applying, recursively, to any called
    functions. Calling non-functions (Malcolm-procedures) is covered
    because all IO implicitly uses pointers or globals, yes?.

    (More muddled thinkers might have tacked on "and only calls other pure
    functions".)

    Also there can't be any volatile-qualified objects with peculiar
    semantics either, but these functions are either "marginal" cases or
    such accesses count as IO.

    <snip>
     
    Ben Bacarisse, May 16, 2014
    #48
  9. Yes, often IO is implemented by reading a global whose state is
    influenced by an external device. So it's in the normal address space
    of the machine and C will allow you to read it via a pointer or even
    a direct hardcoded variable name.
    But if you try to pass such memory to a function (a Malcolm-function
    if you insist), without locking it somehow, then the function is no
    longer a Malcolm-function.

    int foo()
    {
    static int x =0;
    return x++;
    }

    is a good example of a Malcolm-function which isn't a "pure function". The
    bit state of the computer on function exit is completely determined by the
    bit state on function entry, so it's a bit-shuffling function.
     
    Malcolm McLean, May 16, 2014
    #49
  10. This should be:

    ccount += printf( "%u, ", index );

    (Presumably you've initialized ccount to 0.)
     
    Keith Thompson, May 17, 2014
    #50
  11. Yes, you're in a muddle if you tack this on. Probably my fault, but
    still a muddle.

    A Malcolm-function can't call a Malcolm-procedure. But it can access
    a global, it can write to and from memory address passed to it from
    pointers. So whilst pure functions are always Malcolm-functions,
    Malcolm-functions aren't always pure functions. If we say what extra
    restrictions we need to apply to Malcolm-functions to make them into
    pure functions, we don't need to specify, "don't call Malcolm-procedures",
    because a Malcolm-function already never calls a Malcolm-procedure.

    It's true that we have to disallow pointers and globals for all
    Malcolm-functions in the call tree to make a Malcolm-function into
    a pure function.
     
    Malcolm McLean, May 17, 2014
    #51
  12. Kiki *has* a brain? I thought it had been established that all he was was
    a walking compiler and/or walking incarnation of the C standards.
     
    Kenny McCormack, May 17, 2014
    #52
  13. If you say that a function can only return information via a "return"
    statement, then functions that dont return values (procedures) must do IO,
    in fact output, or else what are they doing?
    But very few languages actually enforce that. Most allow writing to
    globals, or to pointers.
    So we have the distinction between pure and impure functions, I'm
    making a slightly different one. Hence I can't use the term "pure
    function" without being highly confusing.
    Exactly. Also a mathematical function, which is a mapping of an input
    set to an output set.
    You have to assume that the abstract machine is functioning correctly.
    If occasionally the act of writing a byte will raise an error which
    needs to be handled, the system breaks down.
    You need the abstract model of the machine which can write to
    memory, which can;t be changed by any external factor. Obviously
    for any physical machine, it will be physically possible to
    manipulate the bits during function execution. Then the analysis
    breaks down.
    No, because writing to bytes with the intention of creating a
    side-effect is doing IO. If we refactor the function so that
    program bit state on exit is the same given bit state on entry,
    but don't write to the memory-mapped bits, then that doesn't change
    a Malcolm-function. It does potentially change a Malcolm-procedure.
    A procedure is hardware-dependent, we only know its working
    correctly if we have something connected to the memory-mapped
    bytes.
    Everything is a procedure if the abstract machine model of reliable,
    addressable memory doesn't hold, yes.
    A pure function is a Malcolm function, assuming it doesn't do any
    output. But not all Malcolm functions are pure functions.
    A computer can't express concepts like "every number from +/-
    infinity". It can only shuffle discrete bits. So not every mathematical
    function can be coded as a Malcolm-function, though most
    mathematics that people want practically can.
    Yes, we're making a slightly different distinction than the pure/impure
    function distinction.
     
    Malcolm McLean, May 27, 2014
    #53
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.