Nodes with unlimited children.

T

The Ghost In The Machine

In comp.os.linux.advocacy, Jeff Relf
<Jeff_Relf_@_NCPlus.NET.Invalid>
wrote
Hi The Ghost In The Machine,

You showed something like this:

for ( list_of_things_type::const_iterator
i = list_of_things.begin();
i != list_of_things.end();
i ++ )
{ const C & obj = *i;
/* ... obj ... */
}

And then you commented: <<
Compared to this level of elegance, Jeff's code is,
in the considered opinion of this particular C++ programmer,
swamp muck. :p~~~ >>

Are you really a C++ programmer ? I don't think so.

At least I know about C++/STL.
Java maybe, server side perhaps,
but you're not a serious Win XP C++ programmer.

You want to make comparisons ?

This is how I loop through a list of unthread Usenet messages:
( From )

LoopC ( & Flat )
if ( Eq ( Par, ( * Arr )->Ln [ _MID ] ) ) break ;

If one assumes the declarations

typedef std::string itemtype; // or whatever you want
typedef std::xxx<itemtype> collectiontype;
// xxx = set, vector, or list
collectiontype collection;
collectiontype::const_iterator it;

then one can do the following.

it = std::find(collection.begin(), collection.end(), "constant");
or
it = std::binary_search(collection.begin(), collection.end(), "constant");
or
inline bool myfunc(itemtype conts & val) { return val == "constant"; }
it = std::find_if(collection.begin(), collection.end(), myfunc);
or [*]
it = std::find_if(collection.begin(), collection.end(),
std::bind2nd(std::equal_to<itemtype>, "constant"));

depending on whether one has a value or a function, and whether
the collection's sorted or not. While the declarations take some
time to use properly, it should be fairly clear what I'm doing.

If the collection is a std::set<> with itemtype as the key, one can
also ask

it = collection.find(val);

which is probably simpler.

To save some typing, one can also prefix the source file with

'using namespace std;'

but I for one am not overly fond of that approach;
I prefer using 'std::' so that I can find STL usages the code.

Now, after one's assigned a value to 'it', one can then test 'it':

if(it != collection.end())
/* found it */
else
/* not in there */

or one can do inline tests such as:

if((it = collection.find("constant")) != collection.end())
/* do something with '*it' */
else
/* collection doesn't contain "constant" */

The inline assignment should be familiar to most C programmers.

One can consider 'it' a 'super-pointer', generalizing the concept
of a pointer and allowing for some nice operations. For instance,
one can remove the pointer:

collection.erase(it);

and the collection will no longer contain that item.

Dereferencing a non-end pointer ('*it') will get the item back.
This is how I delete a forest of threaded messages:

DeC ( Lnk_T Lnk ) { if ( ! Lnk->B ) return ;
LoopC ( Lnk ) { Lnk_T P = * Arr ;

// Recursively deletes... how fun.

DeC ( P );

// Deletes the array of lines that contain
// the abbreviated headers.

LineArr Ln = P->Ln - 1 ;
Loop( _Lns ) free ( * ++ Ln ); free ( P ); }

free ( Lnk->B ); }

collection.erase(collection.begin(), collection.end());

or just let collection go out of scope. If one wants an
explicit forest of items some work will be required to
encapsulate them properly. I have a "smartpointer" class
that contains an explicit refcount, but that does take
more space.
I'm looking at your way... and my way...

I'm comparing the two, and I'm very much preferring my way.

Your perogative. I'll say this for your way of coding:
you're close to the hot metal. However, you're also
making it ugly on yourself as you're touching the oil,
trying not to get burned by various syntactic issues,
dancing all around because of the heat, etc.
By the way...

People are Still inventing wheels... as they well should.

It's called: A better tire.

Enjoy your swamp muck, and watch out for the road tacks. :)

[*] This is where C++/STL starts to get a bit messy, but
std::equal_to is far more general than testfunc() -- presumably
this is documented somewhere, if only in bits/stl_algo.h
or bits/stl_function.h; note that those are included
indirectly and the user should #include <algorithm>
or #include <functional> instead.

There's a method to take a collection type and get the
type of its argument -- collectiontype::value_type
is suggested in the #include files -- if one doesn't
explicitly declare itemtype. For std::map and std::hashmap,
one can also use collectiontype::key_type.
 
T

The Ghost In The Machine

In comp.os.linux.advocacy, Jeff Relf
<Jeff_Relf_@_NCPlus.NET.Invalid>
wrote
Hi Karl Heinz Buchegger,

Re: The Ghost In The Machine and me,

You wrote: <<
_____________________
/| /| | |
||__|| | Please do not |
/ O O\__ | feed the |
/ \ | Trolls |
/ \ \|_____________________|
/ _ \ \ ||
/ |\____\ \ ||
/ | | | |\____/ ||
/ \|_|_|/ | _||
/ / \ |____| ||
/ | | | --|
| | | |____ --|
* _ | |_|_|_| | \-/
*-- _--\ _ \ | ||
/ _ \\ | / `
* / \_ /- | | |
* ___ c_c_c_C/ \C_c_c_c____________


At least we're talking abut C++, doesn't that count ?

I don't think the Ghost is a troll,
I just think he has a different point of view from me.

Very different. :)
A lot of people have scored me down too,
but that's fine with me...

I'm not entering anyone's popularity contest.

It's even possible that
The Ghost and I could come to a understanding.

I understand you well enough. Admittedly, there are
those out there who think nothing of putting
no comments at all into swamp muck, codeswill, or
execrable crap, then using it as the documentation
basis for whatever the tool is supposed to do.

(The computer has no problem understanding Obfuscated C.
But mere mortals have to take it apart. Code should
be understandable to both man and machine -- ideally.)

Of course part of my position is self-defense. I write
something, come back to it later, and wonder why the
hell I wrote it that particular way. It behooves me
to be able to read my own code -- and presumably that
means others can at least have a chance of decoding
what I scribbled into the computer at some point.

ObLinux: I can get the source code. That is a plus in itself.
 
J

Jeff Relf

Hi The Ghost In The Machine,

Oops, I showed: <<
FuBar () { int X = -1, Y = -1 ;

Loop ( 6 ) { ++ X ; Loop ( 7 ) ++ Y ; }

// Prints: 5 and 6

printf ( " %d and %d ", X, Y ); }
And you correctly corrected me: <<
The results I get are 5 and 41, before and after conversion.
This is regardless of whether I use 'i' or 'j'
as the inner variable, which shadows the outer one. >>

I meant to write this:

FuBar () { int X = -1, Y = -1 ;

{ Loop ( 6 ) ++ X ; } Loop ( 7 ) ++ Y ;

// Prints: 5 and 6

printf ( " %d and %d ", X, Y ); }


I say that this: { Loop ( 6 ) ++ X ; } Loop ( 7 ) ++ Y ;
is more readable than this:

for(int i = 0; i < 6; i++)
{
x++;
for(int j = 0; j < 7; j++)
y++;
}

You commented: " I'm surprised you can read that gunk. "

That only goes to show that
one man's meat is another man's poison.

I'm into targeting Win XP for personal use,
( I put the personal in personal computer )...

and you're into targeting servers in a large corporation...

As the saying goes:

I'm ok, you're ok,
and Microsoft should give us a 75 billion dollar rebate.
 
J

Jeff Relf

Hi The Ghost In The Machine,

You showed: <<
it = std::binary_search(
collection.begin(), collection.end(), "constant");
Yea, my original plan was to :

A. qsort() the unthread list of Usenet messages ( Flat ).
( Flat contains one huge array of pointers to nodes,
as described here
)

B. Then do a binary search on it.

But then I ran the code... No need for the binary search.

It's already instant,

even with a list of two thousand messages.
( Even more so when compared to how long it takes me
to download those messages using a spotty dial-up service )

In fact, it's much much Much faster than 40Tude Dialog,
the newsreader that I was using before I wrote X.
( Actually, I'm still using Dialog for some things,
because X is still so primitive )

Re: Your code:
typedef std::string itemtype; // or whatever you want
typedef std::xxx<itemtype> collectiontype;
// xxx = set, vector, or list
collectiontype collection;
collectiontype::const_iterator it;

You said: " ...it should be fairly clear what I'm doing. "

Yes, it is quite clear ( and quite interesting too ).

You showed: <<
Now, after one's assigned a value to 'it',
one can then test 'it':

if ( it != collection.end() ) /* found it */
Of course, I do that all the time...

Only I say this: if ( J < LLL ) // found, i.e. broke out.

after: Loop( 5 ) if ( Eq( "Hello", Line_Array[ J ] ) ) break;

where: #define Eq ! strcmp

#define Loop( N ) int J = -1, LLL = N ; while ( ++ J < LLL )

The main difference is that I'm using J, not " it ",
and LLL, not collection.end() .

Re: collection.erase( it );

With my dynamic arrays of pointers to children and/or lines,
( Using B, P, E, and Inc() described recently:
(e-mail address removed) )...

...I just free one or more pointers and then
use memmove to overwrite them, the I adjust P,
e.g. -- Ln.P, or -- Forest.P .
( I would show you exactly how I do that,
but it's past 6 am now,
and I usually go to bed at 3 am,
and I have to be on campus by 10 am... uuugh ! )

You wrote: <<
Dereferencing a non-end pointer ( '*it' )
will get the item back. >>

Yea, that's similar to my code here:
LoopC ( & Flat )
if ( Eq ( Par, ( * Arr )->Ln [ _MID ] ) ) break ;


You showed:
collection.erase( collection.begin(), collection.end() );
saying: << If one wants an explicit forest of items
some work will be required to encapsulate them properly. >>

Right, the STL has no " Forest " type,
especially not one with unlimited children...

So your code above wouldn't work...
forests have to be recursively deleted/printed.

You said: " Enjoy your swamp muck... ".

Oh, of that you can be Quite sure...

I'm loving every minute of it.

But I've got to go now...
 
R

Richard Herring

Phlip said:
Real programmers don't piss their colleagues off. They write clear, simple,
robust, and easily-changed code. This helps keep their colleagues in the ...
loop.

They don't change the subject line with every reply, either.
 
T

The Ghost In The Machine

In comp.os.linux.advocacy, Jeff Relf
<Jeff_Relf_@_NCPlus.NET.Invalid>
wrote
Hi The Ghost In The Machine,

You showed: <<
it = std::binary_search(
collection.begin(), collection.end(), "constant");
Yea, my original plan was to :

A. qsort() the unthread list of Usenet messages ( Flat ).
( Flat contains one huge array of pointers to nodes,
as described here
)

B. Then do a binary search on it.

But then I ran the code... No need for the binary search.

It's already instant,

even with a list of two thousand messages.
( Even more so when compared to how long it takes me
to download those messages using a spotty dial-up service )

In fact, it's much much Much faster than 40Tude Dialog,
the newsreader that I was using before I wrote X.
( Actually, I'm still using Dialog for some things,
because X is still so primitive )

Re: Your code:
typedef std::string itemtype; // or whatever you want
typedef std::xxx<itemtype> collectiontype;
// xxx = set, vector, or list
collectiontype collection;
collectiontype::const_iterator it;

You said: " ...it should be fairly clear what I'm doing. "

Yes, it is quite clear ( and quite interesting too ).

You showed: <<
Now, after one's assigned a value to 'it',
one can then test 'it':

if ( it != collection.end() ) /* found it */
Of course, I do that all the time...

Only I say this: if ( J < LLL ) // found, i.e. broke out.

after: Loop( 5 ) if ( Eq( "Hello", Line_Array[ J ] ) ) break;

where: #define Eq ! strcmp

*hack* *cough*

Try

if(Eq(1, 2))

and see how far you get. I'll be standing way over here...
#define Loop( N ) int J = -1, LLL = N ; while ( ++ J < LLL )

The main difference is that I'm using J, not " it ",
and LLL, not collection.end() .

Right. Now replace your list with a red-black tree.
Re: collection.erase( it );

With my dynamic arrays of pointers to children and/or lines,
( Using B, P, E, and Inc() described recently:
(e-mail address removed) )...

...I just free one or more pointers and then
use memmove to overwrite them, the I adjust P,
e.g. -- Ln.P, or -- Forest.P .
( I would show you exactly how I do that,
but it's past 6 am now,
and I usually go to bed at 3 am,
and I have to be on campus by 10 am... uuugh ! )

You wrote: <<
Dereferencing a non-end pointer ( '*it' )
will get the item back. >>

Yea, that's similar to my code here:
LoopC ( & Flat )
if ( Eq ( Par, ( * Arr )->Ln [ _MID ] ) ) break ;


You showed:
collection.erase( collection.begin(), collection.end() );
saying: << If one wants an explicit forest of items
some work will be required to encapsulate them properly. >>

Right, the STL has no " Forest " type,
especially not one with unlimited children...

Don't be so sure. In fact, std::set<> and std::map<>
use a red-black tree.

You're right in that STL has no "Forest" type. I'm not sure
how much of a limitation that is.
 
J

Jeff Relf

Hi Kelsey Bjarnason,

In ,
I said to The Ghost: <<
...you and Kelsey Bjarnason were talking about
how much you dislike my AllocN() macro... >>

And you, not remembering what you last wrote, said: <<
Never mentioned it, AFAIK;
although I did make a mention or two about your
Loop and loop macros and your Zero macro. >>

To refresh your memory, see:
( Shit, what a verbose Message-ID )

You quoted AllocN() and then commented: <<
Good god. If you're going to do that much work,
use a frippin' function, not a macro. >>

And I said that it was so I could do: { ... continue; }
thus creating fewer ( ugly ) braces in my code.

At any rate, I'm very glad you quoted AllocN(),
as that gave me an excuse to update it...
and to explain to you and the Ghost
how it creates a forest of bushy trees
( i.e. where the number of direct-children per node
is not limited ).

Re: memmove( Dest = malloc( Sz ), Source, Size )

You commented: << If malloc fails, you're hooped. >>

That wasn't my concern ( of course ),
I noticed that that code didn't work in certain places...

So I had to separate out the two calls, like this:
Dest = malloc( Sz ); memmove( Dest , Source, Size )

As I said... I have no idea why.

You quoted: P = ( Lnk_T ) malloc( sizeof NodeT );

And commented: << Okay, look, if you're coding in C,
lose the cast; it is extremely bad practice and hides bugs.
If you're coding in C++,
why are you using malloc at all, when there's new ? >>

I'm obviously coding in C++ ( only without the STL ),

You should've known that by all the binding I was doing,
eg: Line & Inc ( Ln_T & Ln );

So either you don't know C or you aren't reading my code...
Probably both. ( No big deal )

You asked why I use realloc() when there's new...

Compare new and realloc()... ( I'll wait )

Which is better ? ( No cheating )
 
J

Jeff Relf

Richard Herring,

Re: How I use appropriate titles, in compliance with RFC 1036.

RFC documents employ exact definitions of
these two all-uppercase words: SHOULD and MUST.

Because the title of a message SHOULD describe the message,
RFC 1036 says that when the topic changes:

A. One SHOULD Not use "Re: " at the start of a title.

B. One SHOULD Not delete the References line.

From http://www.usenet-fr.net/fr-chartes/son-of-rfc1036.2.html
<< If the poster determines that
the topic of the followup differs significantly
from what is described in the subject,
a new, more descriptive, subject SHOULD be substituted
( With No Back Reference ). >>
^^^^ ^^ ^^^^ ^^^^^^^^^

The term, " back reference " here is defined as
the " Re: " tag at the start of a title,
( Not the References: line in the headers ).

Google violates RFC 1036 by mandating something more like this:

Because the title of a message MUST define the thread,
One MUST use "Re: " at the start of a title...
Otherwise we MUST delete the References line.

If you were to not side with Google's violation of RFC 1036...

You could " Sort by Thread " ( i.e. the references line ),
( rather than by titles ).

You also might consider unchecking the box that says:
" Start a new thread when the title changes ".

If you simply don't like RFC 1036,
and you choose to violate it...

Please don't complain to me
about the problems it is causing _ You _ .
 
J

JustBoo

You will never ever catch me telling someone that
his code is hard to maintain ( at least if I'm honest ).

You haven't been around much, have you.
I might well refuse to maintain someone's old code,
as I always prefer total rewrites.

You obviously have never spent a single minute in a commercial
software company, have you. Total rewrites... bwhaahaaaa.
I actually own a 450 dollar copy of MS Fortran for Win98.
( From when I converted some Fortran code to C )
But I never used it, thank God... I refused to.

So you converted from a language you never read about... okay, there's
a clue.
So I know what Fortran code ( and Fortran programmers )
look like ( with their big iron, IBM, and all that ).

But you said you never looked at the book?
I've seen those huge hard disk platters.

Did this excite you in some way?
Hmm... Where they the forerunner to floppies ?
( Not counting tape, of course )

"Never try to teach a pig to sing, it wastes time and annoys the pig."
 

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
473,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top