What's the advantage of using for_each loop?

S

Sarath

What's the advantage of using for_each than the normal iteration using
for loop?

Is there any 'tweak' to use stream objects as 'Function' parameter of
for_each loop. Seems copy function can do the same.
 
V

v.r.marinov

What's the advantage of using for_each than the normal iteration using
for loop?

In general for_each is supposed to be less verbose than for-loop.
The cool thing about for_each is:

1) you can pass the function objects by reference
2) you can apply side-effects on the function object
3) you can use the return value of the for_each() algorithm
Is there any 'tweak' to use stream objects as 'Function' parameter of
for_each loop. Seems copy function can do the same.

How about the boost library?
http://www.boost.org/

With std::copy you can do something like:

copy(a.begin(), a.end(), ostream_iterator<string>(cout, " ");


and with boost::lambda you can do the same thing:

for_each(a.begin(), a.end(), std::cout << _1 << ' ');
 
D

Daniel T.

Sarath said:
What's the advantage of using for_each than the normal iteration using
for loop?

I'm beginning to think this should be an FAQ. :)

A key benefit of the standard library algorithms is that they save
the programmer from writing explicit loops. Loops can be tedious and
error-prone. The for_each() algorithm is the simplest algorithm in
the sense that it does nothing but eliminate an explicit loop... One
common use of for_each() is to extract information from elements of a
sequence. -- Stroustrup
Is there any 'tweak' to use stream objects as 'Function' parameter of
for_each loop. Seems copy function can do the same.

Obviously, if a more specialized algorithm works, then use it instead.
 
S

Sarath

In general for_each is supposed to be less verbose than for-loop.
The cool thing about for_each is:

1) you can pass the function objects by reference
2) you can apply side-effects on the function object
3) you can use the return value of the for_each() algorithm


How about the boost library?http://www.boost.org/

With std::copy you can do something like:

copy(a.begin(), a.end(), ostream_iterator<string>(cout, " ");

and with boost::lambda you can do the same thing:

for_each(a.begin(), a.end(), std::cout << _1 << ' ');

Yea I used boost::lambda to do the same. But it's not possible to do
with ISO C++ STL implementation
 
J

James Kanze

What's the advantage of using for_each than the normal iteration using
for loop?

Obfuscation?

Seriously, the advantage of using for_each is that the reader
knows that the loop doesn't terminate prematurely. This has to
be weighed against the fact the code you execute each pass must
be separate---if the code is more or less general, and has a
good name, this is an advantage; if the code is specialized to
the place making the call, and has no good name, then it is bad.

Note too that any good coding guideline will forbid using break
or return in a loop anyway, which sort of negates the first
advantage.
Is there any 'tweak' to use stream objects as 'Function' parameter of
for_each loop. Seems copy function can do the same.

There is a standard class which converts streams to iterators.
Functions which need iterators can use them. Thus, they work
for the first two arguments of for_each, but not for the third.
 
J

Jon Harrop

Sarath said:
What's the advantage of using for_each than the normal iteration using
for loop?

Brevity. The "for_each" function is a rudimentary form of higher-order
function from functional programming.

For example, the pedagogical C++ example:

copy(a.begin(), a.end(), ostream_iterator<string>(cout, " ");

May be written:

iter print a

in a functional language, where "iter" is a higher-order function equivalent
to "for_each" or "copy". However, functional programming languages like
Haskell, OCaml, F# and Standard ML are all much better at finding and
explaining errors at compile time.
 
R

Robbie Hatley

The cool thing about for_each is:
1) you can pass the function objects by reference

I don't see how that could work. I thought the function
object is always passed by value? I tried passing a function
object to a for_each loop once, where the function object was
collecting data about operations. But that didn't work,
because for_each used a *copy* of the object, rather than the
object itself.

I was writing a spelling-checker, just for programming
practice. The for_each loop looked something like:

Append FuncObj = Append(Dictionary);
for_each(Dicts.begin(), Dicts.end(), FuncObj);

("Dicts" is a list of file paths, and "Dictionary" is a list
of words.)

But the the counts of files and lines went into the unnamed
*copy* of FuncObj, not FuncObj itself.
2) you can apply side-effects on the function object
?

3) you can use the return value of the for_each() algorithm

Hmmm.... Interesting. Perhaps, then, something like the following
would work in my spelling checker (could be used to count files --
or lines -- appended to a list of strings):

Append FuncObjCopy =
for_each(Dicts.begin(), Dicts.end(), Append(Dictionary););
cout << "Files processed = " << FuncObjCopy.files << endl;
cout << "Lines processed = " << FuncObjCopy.lines << endl;

Not quite as nice as getting for_each to use the original function
object, but almost.
 
R

Roland Pibinger

The "for_each" function is a rudimentary form of higher-order
function from functional programming.

The amazing thing is that in the course of its evolution C++ changed
the underlying paradigm from object-oriented to value-oriented,
functional. This 'paradigm shift' happened approximately in 1995 with
the inauguration of STL and caused a lot of confusion ever since.
 
J

James Kanze

I don't see how that could work. I thought the function
object is always passed by value?

They are.
I tried passing a function object to a for_each loop once,
where the function object was collecting data about
operations. But that didn't work, because for_each used a
*copy* of the object, rather than the object itself.
I was writing a spelling-checker, just for programming
practice. The for_each loop looked something like:
Append FuncObj = Append(Dictionary);
for_each(Dicts.begin(), Dicts.end(), FuncObj);
("Dicts" is a list of file paths, and "Dictionary" is a list
of words.)
But the the counts of files and lines went into the unnamed
*copy* of FuncObj, not FuncObj itself.

The STL requires functional objects to have value semantics, so
you would (generally) write something like:

Append FuncObj( for_each( Dicts.begin(),
Dicts.end(),
Append( Dictionary ) ) ) ;

The problem becomes more difficult if you are trying to use a
polymorphic object; you have to give it value semantics which do
not loose the polymorphic behavior, by means of the
letter/envelope idiom, or something similar. (Often, just a
small wrapper around a pointer will do the trick.)

The function object can do just about anything which won't
invalidate the iterators. Including modifying program state.
Hmmm.... Interesting. Perhaps, then, something like the following
would work in my spelling checker (could be used to count files --
or lines -- appended to a list of strings):
Append FuncObjCopy =
for_each(Dicts.begin(), Dicts.end(), Append(Dictionary););
cout << "Files processed = " << FuncObjCopy.files << endl;
cout << "Lines processed = " << FuncObjCopy.lines << endl;
Not quite as nice as getting for_each to use the original function
object, but almost.

In some contexts (including this one, IMHO), it's even nicer.
In others (i.e. polymorphic agents), it's a real pain you know
where.
 
N

Noah Roberts

Robbie said:
I don't see how that could work. I thought the function
object is always passed by value? I tried passing a function
object to a for_each loop once, where the function object was
collecting data about operations. But that didn't work,
because for_each used a *copy* of the object, rather than the
object itself.

There are things coming in the new C++ that will make this easier I
think. Would be something like so maybe:

std::for_each(itera, iterb, ref(f));

I think the committee is *trying* to get the std locked some time this year?
 
J

Jerry Coffin

[email protected] says... said:
I think the committee is *trying* to get the std locked some time this year?

Sort of. The deadline for addition of new features is in October, IIRC.
I don't know the exact schedule after that, but my guess would be that
for roughly a year after that the standard will still be open to
modification, but only to fix the definition(s) of existing features,
not to add new ones.
 
R

Robbie Hatley

James Kanze wrote:


Append FuncObj( for_each( Dicts.begin(),
Dicts.end(),
Append( Dictionary ) ) ) ;


Coool! That looks like a work of art. I like it. No assignment,
minimum copying; just uses constructors. Thanks for the tip.
I re-wrote my "build dictionary" function along those lines:



// Build "Dictionary" from dictionary files:
void
ns_Spell::
BuildDictionary
(
std::list<std::string> & Dictionary
)
{
std::list<std::string> Dicts;
rhdir::LoadFileList
(
Dicts, // List of dictionary paths.
"C:/bin/*.dic", // Wildcard.
1, // Files only (no dirs).
2 // Append to list without clearing.
);

// Define "Append" to mean "class rhdir::AppendFileToListFunctor",
// for purposes of brevity:
typedef class rhdir::AppendFileToListFunctor Append;

// For each dictionary file, append its contents to Dictionary:
Append
FuncObj
(
for_each
(
Dicts.begin(),
Dicts.end(),
Append(Dictionary)
)
);

BLAT("In ns_Spell::BuildDictionary().")
BLAT(" Number of files processed = " << FuncObj.applications)

rhutil::SortDup(Dictionary);

return;
} // end BuildDictionary()



--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lonewolf aatt well dott com
triple-dubya dott tustinfreezone dott org
 
J

Jon Harrop

Robbie said:
James Kanze wrote:

Append FuncObj( for_each( Dicts.begin(),
Dicts.end(),
Append( Dictionary ) ) ) ;


Coool! That looks like a work of art.

Indeed, this is an idiom from functional programming where the above would
typically be written:

iter add dicts

and "iter" is referred to as a higher-order function because it accepts the
function "add" as an argument.
 
V

V.R. Marinov

I don't see how that could work. I thought the function
object is always passed by value? I tried passing a function
object to a for_each loop once, where the function object was
collecting data about operations. But that didn't work,
because for_each used a *copy* of the object, rather than the
object itself.

My fault. It should be:

1) you can pass the argument to the function object by reference.


BTW it looks like i cant change my username, now that's cool.
 

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,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top