Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Dennis Ritchie -- An Appreciation

Reply
Thread Tools

Dennis Ritchie -- An Appreciation

 
 
Nick Keighley
Guest
Posts: n/a
 
      10-31-2011
On Oct 30, 3:33*pm, Malcolm McLean <(E-Mail Removed)>
wrote:
> On Oct 30, 4:56*pm, Nick Keighley <(E-Mail Removed)>
> wrote:> On Oct 30, 8:07*am, Malcolm McLean <(E-Mail Removed)>


> > what? How can your *program* be structured as "arrays of arrays...".
> > My programs are hierarchies of function calls. Nearly a tree but most
> > likely a DAG. Did you mean your data structures are strcts containing
> > arrays? Seems very limited.

>
> The data in the program, not the code.
>
> Most things naturally fall into arrays of arrays. For instance a
> protein consists of an array of atoms,


doesn't sound a natural data type. Surely a protein is an array of
amino acids? The organisation of the atoms is not a linear structure.

> each of which has an element
> type and an x y z position. The atoms are grouped into amino acid
> residues. The residues are grouped into chains. Then you might be
> working on more than one protein.
>
> That's what most data is like.


looks to me more like you've chosen it to be like that.

> Arrays are by far the most commonly
> used data structure in C.


because there isn't much choice

> They're the only one which has explicit
> syntactical support.


structs, strings, unions

> That's not to say you never use other structures, there's a case for
> representing the bonds between atoms as a graph, for instance, you
> might want to do that for some applications.


again wouldn't arrays of structs be more natural than strcuts of
arrays?
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      10-31-2011
On 10/31/2011 04:11 AM, Malcolm McLean wrote:
> On Oct 30, 8:56�pm, Ian Collins <(E-Mail Removed)> wrote:
>>
>> Once again, how? �Is
>>
>> void f( std::vector<int>& );
>>
>> more complex than
>>
>> void f( int*, size_t );
>>
>> ?
>>
>> With a container, the size information is embedded, no need to pass a
>> count (which you would have to manually track). �From where I sit, the
>> container removes at least two bits of complexity: you don't have to
>> track a size and you don't have to worry about a null pointer.
>>

> You have to use std::vectors everywhere with the C++ version, if you
> want to call f. You have to use arrays of ints everywhere with the C
> version if you want to do the same.


That's why most C++ algorithms take iterator arguments rather than
container arguments. An algorithm, once it's correctly expressed in
terms of iterators, can work equally well on the elements of an array of
double as on a std::vector<int> or a std::list<unsigned long>. You only
have to write the template once, no matter how the data's actually
stored (as long as the algorithm's iterator requirements are met).
--
James Kuyper
 
Reply With Quote
 
 
 
 
Malcolm McLean
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 12:55*pm, James Kuyper <(E-Mail Removed)> wrote:
>
> That's why most C++ algorithms take iterator arguments rather than
> container arguments. An algorithm, once it's correctly expressed in
> terms of iterators, can work equally well on the elements of an array of
> double as on a std::vector<int> or a std::list<unsigned long>. You only
> have to write the template once, no matter how the data's actually
> stored (as long as the algorithm's iterator requirements are met).
>

But not everyone uses the iterator system consistently.

You need two requirements. You need the iterators to be set up
correctly. But you also need functions like add and divide to be
defined correctly. The mean of a list of integers is not usually an
integer.

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      10-31-2011
On 10/31/2011 09:08 AM, Malcolm McLean wrote:
> On Oct 31, 12:55 pm, James Kuyper <(E-Mail Removed)> wrote:
>>
>> That's why most C++ algorithms take iterator arguments rather than
>> container arguments. An algorithm, once it's correctly expressed in
>> terms of iterators, can work equally well on the elements of an array of
>> double as on a std::vector<int> or a std::list<unsigned long>. You only
>> have to write the template once, no matter how the data's actually
>> stored (as long as the algorithm's iterator requirements are met).
>>

> But not everyone uses the iterator system consistently.


"Not everyone uses X consistently" is a fairly accurate statement for
just about any X. It's a problem with everything, and is not specific
to C++ iterators.

> You need two requirements. You need the iterators to be set up
> correctly. But you also need functions like add and divide to be
> defined correctly. The mean of a list of integers is not usually an
> integer.


That's true; which is why a C++ algorithm that performed a generic mean
calculation would have to templated by the type to be used for
calculating the mean. It would have to be the user's responsibility to
choose that type in a way that allows the expressions "sum += *iterator"
and "sum /= count" to do what he wants done.
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 4:42*pm, James Kuyper <(E-Mail Removed)> wrote:
> On 10/31/2011 09:08 AM, Malcolm McLean wrote:
>
> "Not everyone uses X consistently" is a fairly accurate statement for
> just about any X. *It's a problem with everything, and is not specific
> to C++ iterators.
>

No, but it's particularly bad in this case, because the whole point of
the template system is to avoid having to rewrite code or "adapter"
routines (e.g. to convert an array of size_ts to an array of DWORDs).

 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      10-31-2011
Malcolm McLean <(E-Mail Removed)> writes:

> On Oct 30, 9:46*pm, Ben Bacarisse <(E-Mail Removed)> wrote:
>> Malcolm McLean <(E-Mail Removed)> writes:
>>
>> Some code might clarify things. *You might want to sketch a situation
>> with lots of "plugs and sockets" which gets more complex hen written in
>> C++.
>>

>
> I'm not sure I've even got the syntax right, it's so long since I did
> this, but the root of the problem goes something like this
>
> template <class Iterator, class numeric>
> <numeric> standard_deviation( Iterator begin, Iterator end)
> {
> while(begin !- end)
> {
> /* code here */
> ++begin;
> }
> /* There's something wrong with out standard deviation, so I want
> to call a tried and tested function to get the mean, which is foo ()
> */
> foo();
> /* The problem is that, even though under the bonnet I've just been
> passed a double *, the only way of calling foo() is to construct a
> temporary vector */
> }
>
> temple <class numeric>
> <numeric> foo( std:vector<numeric> &list )
> {
> }
>
> In C, you can have the problem that we might have floats or doubles or
> long doubles. The whole point of the template idea is that you only
> have to write the routines once. But you need iron tight discipline to
> achieve this.


No, I meant some C code which gets more complex in C++. That was your
claim -- that some kinds of code get more complex in C++. This snippet
demonstrates that you can't hack a call to a function with one type from
a template that uses another. That's true, but not what you were
talking about. For one thing, it's very hard to write this sort of the
generic code in C, so it's unfair to complain that it's "unhackable" and
"complex" in C++. The C for a type-generic loop would be horrendous.

--
Ben.
 
Reply With Quote
 
nroberts
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 1:34*am, Ian Collins <(E-Mail Removed)> wrote:

> You'll see kludges an any language! *Null objects are an abomination and
> anyone using them should be tarred and feathered by their peers.


Nonsense. They are quite preferable to littering 'if (xx != 0)' all
over the place in a great number of situations. Any time it is quite
common for an object to be non-existent and the behavior is always the
same, a null object encapsulates the situation quite nicely. Client
code doesn't need to care, nor should it.
 
Reply With Quote
 
nroberts
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 2:26*am, Nick Keighley <(E-Mail Removed)>
wrote:
> On Oct 30, 5:43*pm, nroberts <(E-Mail Removed)> wrote:


> > but it is a good argument for variable

>
> noooooo! This way lies the Hungarian Lunacy. If your functions are
> small and localised then the variable will be defined close by and we
> can see what type it is.


Nobody said anything about Hungarian notation. That's a straw man.

>
> void refrog (MyType x, MyType y)
> {
> * * x = y++;
>
> }


OK, well I'm looking at that function and I have no idea what you are
intending with it. I really doubt that knowing the definitions of
MyType would help me either.

>
> >*When that is done well you generally know what can be done with
> > the variable, which is more important than what type it is (which is
> > something I can let the compiler worry about).

>
> a well chosen type tells you the semantics of the type


int q;

Tell me, what is the intended use of q?

void (*f)(int,int,double);

Tell me, what does f do?

You should be able to tell me since the types tell you enough, right?
 
Reply With Quote
 
nroberts
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 8:15*am, Ben Bacarisse <(E-Mail Removed)> wrote:

> No, I meant some C code which gets more complex in C++. *That was your
> claim -- that some kinds of code get more complex in C++. *This snippet
> demonstrates that you can't hack a call to a function with one type from
> a template that uses another. *That's true, but not what you were
> talking about. *For one thing, it's very hard to write this sort of the
> generic code in C, so it's unfair to complain that it's "unhackable" and
> "complex" in C++. *The C for a type-generic loop would be horrendous.


Let's compare them. The basic for_each implementation in C++:

template < typename ForwardIterator, typename Fun >
void for_each(ForwardIterator start, ForwardIterator end, Fun fun)
{
for (; start != end; ++start) fun(*start);
}

Use:

void print_int(int i) { std::cout << i; }

std::vector<int> vect;
....
std::for_each(vect.begin(), vect.end(), print_int);

Or now:

std::for_each(vect.begin(), vect.end(), [](int i) { std::cout <<
i; });

I, personally, don't find that very complicated.

Now the C version. I'm sure a C expert can do better than me, but
here's my untested attempt:

void for_each(char const* start, size_t size, size_t count, void(*fun)
(char*))
{
while (count--)
{
fun(start);
start += size;
}
}

Use:

void print_int(char const* ptr) { printf("%d", *((int const*)ptr)); }

int array[COUNT];
....
for_each((char const*)array, sizeof(int), COUNT, print_int);

I don't find that particularly difficult to get, but as a C++
developer I am annoyed by all the casting (especially upon review
before posting when I noticed I forgot the const on the int cast).
There's also room for user error if the wrong size is passed in, which
the compiler does for you with the C++ version. Neither of these is
insurmountable though.

Of course, generally you don't write your functions to work on char*
when they don't, so you'd probably be creating a wrapper for
print_int. In that way it would be reminiscent of having to create
functor objects for binding more than 2 parameters. The new C++
solves this issue, but most here probably are not familiar with bind
and lambdas.
 
Reply With Quote
 
nroberts
Guest
Posts: n/a
 
      10-31-2011
On Oct 31, 1:49*am, Malcolm McLean <(E-Mail Removed)>
wrote:
> On Oct 30, 9:46*pm, Ben Bacarisse <(E-Mail Removed)> wrote:
>
> > Malcolm McLean <(E-Mail Removed)> writes:

>
> > Some code might clarify things. *You might want to sketch a situation
> > with lots of "plugs and sockets" which gets more complex hen written in
> > C++.

>
> I'm not sure I've even got the syntax right, it's so long since I did
> this, but the root of the problem goes something like this
>
> template <class Iterator, class numeric>
> <numeric> standard_deviation( Iterator begin, Iterator end)
> {
> * while(begin !- end)
> * {
> * * /* code here */
> * * ++begin;
> * }
> * /* There's something *wrong with out standard deviation, so I want
> to call a tried and tested function to get the mean, which is foo ()
> */
> * foo();
> * /* The problem is that, even though under the bonnet I've just been
> passed a double *, the only way of calling foo() is to construct a
> temporary vector */
>
> }
>
> temple <class numeric>
> <numeric> foo( std:vector<numeric> &list )
> {
>
> }
>
> In C, you can have the problem that we might have floats or doubles or
> long doubles. The whole point of the template idea is that you only
> have to write the routines once. But you need iron tight discipline to
> achieve this.


So, let me see if I understand you correctly...you find C++ more
complicated because you're not allowed to call functions that expect
one type with a different one and that if you need to you have to do
some conversions?

I think I can live with that. I wonder, what would happen if I
created a function expecting to be passed a handle to a managed buffer
structure and tried to pass it a double*...
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: RIP Dennis Ritchie Lynn McGuire C++ 12 10-18-2011 08:35 AM
Dennis Ritchie Has Died Bradley K. Sherman C Programming 28 10-18-2011 04:44 AM
Query from Dennis Ritchie C learner C Programming 6 04-04-2011 05:44 PM
Errata for The C Programming Language, Second Edition, by Brian Kernighanand Dennis Ritchie Ioannis Vranos C Programming 4 05-16-2009 03:48 PM
What is this noalias thing Dennis Ritchie is railing about ? Spiros Bousbouras C Programming 22 09-13-2007 09:28 AM



Advertisments