Idiomatic for ... in

P

Pedro Pinheiro

Hey folks,

One thing I've been wondering about lately is how to write a for (key in object) loop in a nice, idiomatic manner.

What to me seems the obvious shape for it is

for (key in object) {
if (object.hasOwnProperty(key)) {
doStuff();
}
}

but that is a wee bit too verbose, and eats up an indent level unnecessarily. I've also seen the form

for (key in object) {
if (!object.hasOwnProperty(key)) {
continue;
}
doStuff();
}

which doesn't eat up the extra indent level, but is longer, and suffers from not making it quite as obvious that the if is filtering the keys. I've personally come to favour

for (key in object) if (object.hasOwnProperty(key)) {
doStuff();
}

Which, to my eyes, is nice and compact, but I really haven't seen it anywhere else, so fails a bit on the
surprise factor for anyone else reading my code.

So, what do you guys like, and why?
 
T

Thomas Mlynarczyk

Pedro said:
for (key in object) {
if (object.hasOwnProperty(key)) {
doStuff();
}
}

Why not wrap this in a function? (Untested:)

function iterate( object, callback )
{
for ( key in object ) {
if ( object.hasOwnProperty( key ) ) {
callback( object, key );
}
}
}

// Usage
iterate( someObject, doStuff );

Greetings,
Thomas
 
J

J.R.

Hey folks,

One thing I've been wondering about lately is how to write a
for (key in object) loop in a nice, idiomatic manner.

What to me seems the obvious shape for it is

for (key in object) {
if (object.hasOwnProperty(key)) {
doStuff();
}
}


but that is a wee bit too verbose, and eats up an indent
level unnecessarily. I've also seen the form

for (key in object) {
if (!object.hasOwnProperty(key)) {
continue;
}
doStuff();
}

which doesn't eat up the extra indent level, but is longer,
and suffers from not making it quite as obvious that the if
is filtering the keys. I've personally come to favour

for (key in object) if (object.hasOwnProperty(key)) {
doStuff();
}

Which, to my eyes, is nice and compact, but I really haven't seen it anywhere else, so fails a bit on the
surprise factor for anyone else reading my code.

So, what do you guys like, and why?


I'd suggest that you stick to the code conventions:
<http://javascript.crockford.com/code.html>

The following code snippet should be the preferred form in JavaScript:

for (variable in object) {
if (object.hasOwnProperty(variable)) {
// statements
}
}
 
T

Thomas 'PointedEars' Lahn

J.R. said:

The code above complies with the conventions set forth in this document.
[…]
So, what do you guys like, and why?

I'd suggest that you stick to the code conventions:
<http://javascript.crockford.com/code.html>

The following code snippet should be the preferred form in JavaScript:

for (variable in object) {
if (object.hasOwnProperty(variable)) {
// statements
}
}

I do suggest that you start thinking independently. Syntactically, the name
of the value which holds the current property name in for-in iteration may
be anything that can be produced by /LeftHandSideExpression/. In a strict
semantic sense, obviously neither of the terms "key" nor "variable" is
correct for it; only "property name" is. In a more loose semantic sense, a
property name can certainly be considered a key (of a hash table) by which a
certain property value is accessed.

IOW, there was nothing wrong with this code in the first place. Besides,
despite his contributions on the topic it is certainly not Douglas Crockford
who sets the standards against which ECMAScript-based code should be
measured; see for example (the complaints about) jslint. It is incorrect to
present his ideas of code conventions as "/the/ code conventions". Contrary
to that of Java, there are no official code conventions for the JavaScript
language or all ECMAScript implementations. Instead, there are some best
practices which several developers agree on.


PointedEars
 
R

RobG

Hey folks,

One thing I've been wondering about lately is how to write a for (key in object) loop in a nice, idiomatic manner.

What to me seems the obvious shape for it is

for (key in object) {
if (object.hasOwnProperty(key)) {
doStuff();
}

}

but that is a wee bit too verbose, and eats up an indent
level unnecessarily. I've also seen the form

That is the only way to do it safely in general, though if you want
less code:

for (var p in o) {
o.hasOwnProperty(p) && doStuff();
}

may suit - but if the only reason to do it is to save a few characters
I'm not convinced it's a good idea. It might keep Crockford happy
though. :)

ES5 introduces Object.keys[1] that returns an array of an object's
enumerable, own property names, but it doesn't save any typing:

// Substitute if Object.keys isn't a function
if (Object.keys != 'function') {
Object.keys = function(o) {
var a = [];
for (var p in o) {
if (o.hasOwnProperty(p)) {
a.push(p);
}
}
return a;
}
}

// Use Object.keys
if (typeof Object.keys == 'function') {
var keys = Object.keys(o);
for (var i=0, iLen=keys.length; i<iLen; i++) {
// do stuff with keys
}
}

Note that there is also Object.getOwnPropertyNames, but it returns
both enumerable and non-enumerable own properties.

1. Object.keys also has:

"If an implementation defines a specific order of enumeration for
the for-in statement, that same enumeration order must be
used in step 5 of this algorithm."
 
J

John G Harris

for (key in object) if (object.hasOwnProperty(key)) {
doStuff();
}
^
<snip>

That close bracket looks as though it was opened a long way off the top
of the screen. Saving a couple of space chars isn't worth it.

Why not have the courage to prove you understand the syntax :

for (key in object)
if (object.hasOwnProperty(key))
doStuff();

or even

for (key in object) if (object.hasOwnProperty(key)) doStuff();


John
 
T

Thomas 'PointedEars' Lahn

John said:
^
<snip>

That close bracket looks as though it was opened a long way off the top
of the screen. Saving a couple of space chars isn't worth it.
ACK

Why not have the courage to prove you understand the syntax :

for (key in object)
if (object.hasOwnProperty(key))
doStuff();

Because this isn't Python.
or even

for (key in object) if (object.hasOwnProperty(key)) doStuff();

Because that's a debugging and refactoring nightmare.


PointedEars
 
V

VK

for (key in object) if (object.hasOwnProperty(key)) {
    doStuff();

}

Which, to my eyes, is nice and compact, but I really haven't seen it anywhere else, so fails a bit on the
surprise factor for anyone else reading my code.

The code is valid and from the human language semantic point of view
looks pleasurable. Yet I personally object skipping block brackets
even if allowed. Even more disturbing here that the same line
demonstrate two different choices for block brackets: omitted for for-
in and used for if-else. I would prefer the coding consistency over
any belletristic achievements. If it is possible to write a working
program in say Perl as a piece of a poetry, it doesn't mean that we
have to :)

So my personal opinion: definitely fine for personal projects, should
be avoided for an open code project with many participant. In the
latter case: i) consistency, ii) strict syntax rules (no skipped
brackets or ;'s), iii) detailed comments. With this in place (iii) can
be as idiomatic or belletristic as particular participant feels to.
IMHO.
 
T

Tim Streater

I'd suggest that you stick to the code conventions:
<http://javascript.crockford.com/code.html>

The following code snippet should be the preferred form in JavaScript:

for (variable in object) {
if (object.hasOwnProperty(variable)) {
// statements
}
}

And so all your "// statements" are indented one more level than is
necessary. I subscribe to the view that says get rid of the
uninteresting cases as soon as possible, and then concentrate on the
rest (so I'm bored with any argument in favour of SESE). In this case,
that becomes:

for (variable in object)
{
if (object.hasOwnProperty(variable)==false) continue;
// statements
}

Only one pair of braces needed, and because they are aligned, I can find
the matching pair easily.
 
J

J.R.

And so all your "// statements" are indented one more level than is
necessary. I subscribe to the view that says get rid of the
uninteresting cases as soon as possible, and then concentrate on the
rest (so I'm bored with any argument in favour of SESE). In this case,
that becomes:

for (variable in object)
{
if (object.hasOwnProperty(variable)==false) continue;
// statements
}

Only one pair of braces needed, and because they are aligned, I can find
the matching pair easily.

Okay, there's no accounting for taste. However, there are some code
editors, such as Notepad++ and Aptana Studio, which help me a lot in
terms of finding the matching pair of curly brackets, particularly with
many code lines.
 
T

Tim Streater

J.R. said:
Okay, there's no accounting for taste. However, there are some code
editors, such as Notepad++ and Aptana Studio, which help me a lot in
terms of finding the matching pair of curly brackets, particularly with
many code lines.

Sure and TextWrangler has a similar feature. But I don't use it often
because I don't need to.
 
J

John G Harris

Because scarce few real world loops would actually have a single
function call inside, and doStuff() is meant to be read as a
placeholder for whatever the loop contents would be.

You need exactly one statement there. Obviously, when you want to do
several statements you package them up in a compound statement to give
you exactly one statement there.

However, if the code to be executed is being passed as a function
parameter or is event processing code, then it needs to be packaged
inside a function. Then adding { } is not only redundant but also
misleading to anyone maintaining the code.

Didn't get what you meant with "That close bracket looks as though it
was opened a long way off the top of the screen".

In your last example ...
for (key in object) if (object.hasOwnProperty(key)) {
doStuff();
}

.... if you follow from that } upwards you find the 'for', but that
doesn't have an opening { so you look for the opening earlier in the
code. It needs to be obvious that the } belongs to the 'if', and it
isn't.


John
 
J

John G Harris

John G Harris wrote:


Because this isn't Python.

No, it's more like C, C++, Java, and C#, but it's where Python got its
peculiar ideas from.

Because that's a debugging and refactoring nightmare.

Tell that to John Stockton :)

John
 
T

Thomas 'PointedEars' Lahn

John said:
No, it's more like C, C++, Java, and C#, but it's where Python got its
peculiar ideas from.

I do not know about C(\+\+|#)? code conventions, but the official Java Code
Conventions require braces there. And that is good so.

Tell that to John Stockton :)

No, I won't. Code-style-wise at least, he cannot be reasoned with.


PointedEars
 
T

Tim Streater

Thomas 'PointedEars' Lahn said:
Tim said:
Thomas 'PointedEars' Lahn wrote:
[snip]
For "if" and "for", at least (I didn't look any further), these have to
be the shittiest layout conventions I've ever seen.

Oracle screwed up the formatting when taking over Sun; compare with the
original here:

<http://replay.waybackmachine.org/20090228064950/http://java.sun.com/docs/code
conv/html/CodeConventions.doc6.html#449>

Thanks for the link.

Fortunately I don't have to bother with conventions I don't like.
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top