Malcolm McLean said:
No, because if op() is not a bit shuffler, you lose the strong guarantee
from op. behaviour depends on the physical state of hardware attached
to the machine. That might be good enough for many purposes, but not
for all.
By "no", do you mean that I *can't* reason about this code? if so, I
think we'll have to agree to disagree about what that means, and about
it's role in program development.
Callbacks aren't eliminable, of course.
I think they are in pure portable C, but it would certainly be only in
principle. Mind you, I think that's what matters here -- that a call be
eliminable in principle.
Because printf() might be taken away on some future version of
the hardware. Obviously you'll have to deal with this at some level,
but it's best to isolate all the calls to printf() is sections of
the program labelled "procedures".
They are all isolated by the fact that they are calls to a function
called printf. I can deal with this bizarre situation by writing my own
printf. If the specification of the program means that the output is
optional (non-essential logging say), this might be done very easily
indeed.
Now, normal code organisation principles will mean that it's almost
certain that all logging will done through a logging function, so there
will be an alternative method as well.
That IO functions are often segregated is just good design. Other, non
IO functions will be organised and segregated, but both will be
organised at finer grain that bit-shuffling vs. IO and, in my opinion,
the two division won't always coincide (i.e. your two are not just
larger aggregations of the divisions that I might choose).
Because you may want to test and develop most of the program in a
Unix box type environment, and only put in the hardware-specific
calls when the hardware is actually built. You may wish to move
the program to new hardware, making small changes in the logic,
and to start software development before the new hardware becomes
available.
Yes, I do that kind of thing all the time. In fact the same pattern of
work is very useful for pure logic functions too.
What I'm missing is why this distinction of yours helps more than the
usual process by which people develop software. It has downsides --
some things I like are "banned", yet there's no sign that it will help
any more than good software engineering practice has been for decades.
Because we've isolated all the calls to fgetc(). So it's easier to
replace them with calls to internet-enabled functions which deal
with slow connections.
The calls to fgetc are isolated already by the fact that they are calls
to fgetc. Maybe all this comes from your using some really badly
designed software? It's normal to isolate functional components form
each other via well-defined interfaces, and that makes porting to new
environments simpler, but I see no advantage of your particular rules
over what is usually done.
C has no proper module system, so it is easy to make a mess of this
separation, but the solution to that is either to write in another
language, or to structure your code better. You can make a mess of the
pure logic bits as well as of the IO bits. Your division gives one cut
through the software where good design needs many. Since I don't see
that your cut is particularly useful, I would not use it. I'd start
with proper modular design.
strcpy() can be taken away. It's not a disaster, if you know you can
rewrite the function without using strcpy().
I don't see that as an answer. My point was in reply to the need "to
retain the right to ban subroutines" and so I asked how that helps. I
can re-write function to get round broken implementations even if you
have never had the right to ban subroutines. Case in point: you don't
reserve the right to ban subroutines in IO functions, but you happily
talk about re-writing them to work in IO encumbered situations.
Parallel programming is a whole different can of worms.
My point has got lost in snipping. I made it terms of a concurrent
program, but following your objection I re-made it in more general
terms. And now it's lost (and it was not a detail).
We've plenty to talk about just on serial programming.
Actually, no. I have already said more than I really want to, so I
won't be continuing. Feel free to rebut whatever points remain in this
post, but, unless I feel particularly outraged, I won't be replying.
Oh, you mean machine representation issues. Unfortunately that's
a necessary concession. Functions can't be defined in terms of bits,
but in terms of machine representations.
Eh? I just meant that you were wrong to say "this code is the same as
that code". The two pieces of code behave differently for some values
of the arguments. Without a specification, all I can do is conclude
that for one bit of code to be the same as the other, they should behave
the same in all cases.
But the fact that your re-write did no preserve the function's behaviour
is of no significance to your argument. I should just accept that you
are not a fan of details, where I am detail oriented. Pointing this out
has added nothing to the big picture, but, sadly, I obsess about details.
It's a different programming paradigm. Callbacks are difficult for
the bit-shuffling non-bit-shuffling paradigm, because it's difficult
to say if an indirect call should count. So they need to be short
bits of missing functionality. If you build a method on callbacks
you're programming in a different way.
There's no callbacks here. That's why I chose this example. I
understand, but disagree with, what you said about callbacks being
difficult. I was making a fresh point about higher-level functions. Do
they fit into your paradigm at all? If not, fine. But if they do, how
exactly? The talk of bit-states is alien in that sort of code.
When an argument is another function there's a question mark, do we regard
the function as tied (it's one function) or not (it's two functions).
More to the point, do you? The use of "we" is unusual here.
Any tty can fail at any time. So printf() is useless.
Well yes it is, as a "function". That's the whole point.
It's my whole point as well. I don't know how exactly the same facts
can lead the two of us to make such different statements, but I think it
reflects a fundamentally different view of what a program is.
Unravelling that, if it is indeed the case, is beyond me right now.
I've said my bit about IO and re-writing IO functions, but since I don't
know what you are saying about it I am stumped. I agree with every
low-level, factual, statement you've made about it, yet we don't seem to
agree about the most basic higher-level remarks.
<snip>