October 30, 2001
Russell Borogove wrote:
> Hm, this is getting towards matters of personal style, but I disagree with this for a number of reasons.

I'll agree with the personal style part.

> - Saving yourself typing frequently means reduced readability for the other programmers who have to deal with your code. Rather than "ms" or "i" I'd prefer to see "element" or (if it's, say, a vector of wombats) "wombat" as the name of the iterator. If you have carpal tunnel syndrome, I could cut you some slack, I guess, but on the whole, I find long identifiers to be more readable in the long run.

I agree in cases where the identifier is really of meaning.  I consider
index 'i' to be a safe and well know convention for some cases.  Kind of
like x, y and z for coordinates.  I've also seen cases where overly
verbose code subverted readability by turning a statement that could
have been expressed clearly in one line into a five line paragraph that
was a riddle to even the most experienced eyes.
	In any case, I don't have carpal and I hope to avoid it for a very long
time.

> - In your example, you've traded away "i->foo" to get "ms.foo", which is no savings to length or readability no matter how many times you make the substitution :)

I suspect it was a toy example.  I personally would use such a thing in
cases such as

	physicalObject& current = (Engine->PhysicsModel->currentArea()->
					objects.next());
	// do we hit
	if(Engine->PhysicsModel->collide(player, current)){
		// important stuff
	}

	// do we see it
	if(Engine->PhysicsModel->observe(player, current)){
		// cool stuff
	}

	// does it see us
	if(Engine->PhysicsModel->observe(current, player)){
		// bad things
	}

	// etc etc etc


> - If you're intending to do a lot more to ms in the loop, then it may be that you should factor that series of operations into a member function of mystruct, so the loop body becomes:
> 
>   i->DoWhatWombatsDo();  // or ms.DoWhatWombatsDo();

There are cases where that defies Modularity.

> - Last but not least, STL provides the "for_each()" mechanism to clean up exactly this idiom. I myself am guilty of not having learned to use it yet.

I personality detest for_each() and the idiom in general.  It a kludge. If C++ supported some form of closure than I might not mind.  Far too often I found myself creating a named function and polluting my namespaces with like functions who implementation were truly too simplistic to deserve a name.  Functors are a poor excuse for a closure.
November 04, 2001
"Russell Borogove" <kaleja@estarcion.com> wrote in message news:3BDDAE52.301C7D72@estarcion.com...
> "Sean L. Palmer" wrote:
> >
> > I use references all the time to save typing.  For instance:  (C++ code)
> >
> > [...]
> >
> >   for (std::vector<mystruct>::iterator i = myvector.begin(); i !=
> > myvector.end(); ++i)
> >   {
> >      mystruct& ms = (*i);
> >      std::cout << ms.foo;
> >   }
> > }
> >
> > Now just imagine a more complex function that uses ms many times... the savings in typing and increased readability quickly add up.
>
> Hm, this is getting towards matters of personal style, but I disagree with this for a number of reasons.
>
> - Saving yourself typing frequently means reduced readability for the other programmers who have to deal with your code. Rather than "ms" or "i" I'd prefer to see "element" or (if it's, say, a vector of wombats) "wombat" as the name of the iterator. If you have carpal tunnel syndrome, I could cut you some slack, I guess, but on the whole, I find long identifiers to be more readable in the long run.

It is a matter of personal style.  I do this because it makes it easier to change the container type later without having to change all references inside the block using an item in the container.  I prefer locals with short names... it's easy enough to glance up a few lines to find the declaration of ms.  I do prefer descriptive names on members and functions.  Readability of code does not increase proportionally to the length of the identifiers used... It's good up to a point, then starts to get worse because simple operations need code that goes off the edge of the screen.  Brevity can be good too, to a point.  My identifiers tend to be between 6 and 20 characters.  I can tolerate long function names better than long variable names.  I think this all ends up being a matter personal taste and has nothing to do with the design of the D language.

> - In your example, you've traded away "i->foo" to get "ms.foo", which is no savings to length or readability no matter how many times you make the substitution :)

ms.foo is much better than (*i).foo, which I end up having to use because
some compilers' STL still don't support the operator -> on iterators.  ;)

It's easy to extrapolate to a situation where to get ms, you have to do some serious work, such as

mystruct& ms = (*i)->member.grabentries(index1)[index2].second;

I'm sure you'd agree that having twenty instances of
(*i)->member.grabentries(index1)[index2].second in your function would
decrease readability and maintainability.

> - If you're intending to do a lot more to ms in the loop, then it may be that you should factor that series of operations into a member function of mystruct, so the loop body becomes:
>
>   i->DoWhatWombatsDo();  // or ms.DoWhatWombatsDo();
>
> - Last but not least, STL provides the "for_each()" mechanism to clean up exactly this idiom. I myself am guilty of not having learned to use it yet.

Without being able to declare classes inside a function, for_each clutters the code by requiring that the code that operates on each item be separated lexically from the code doing the for_each.  Not that I'm against for_each, I like it... I guess I'm just as guilty as you, maybe more so because I know how to use it and yet still find myself typing iterating loops alot.  ;)

I suppose the with clause will help alot with this sort of thing.  What I don't like about Pascal's with clause is that it basically injects the object's contents directly into the current scope... I'd rather be able to give the result a new name of my choosing, to avoid ambiguity, like so:

with ((*i)->member.grabentries(index1)[index2].second) as ms
{
  ms.DoSomething();
  ms.DoSomethingElse();
  ++ms.foo;
  cout << ms.foo;
}

Sean


1 2
Next ›   Last »