What's the advantage of using for_each loop?

Discussion in 'C++' started by Sarath, May 30, 2007.

  1. Sarath

    Sarath Guest

    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.
     
    Sarath, May 30, 2007
    #1
    1. Advertising

  2. Sarath

    Guest

    > 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 << ' ');
     
    , May 30, 2007
    #2
    1. Advertising

  3. Sarath

    Daniel T. Guest

    Sarath <> wrote:

    > 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.
     
    Daniel T., May 30, 2007
    #3
  4. Sarath

    Sarath Guest

    On May 30, 10:33 am, wrote:
    > > 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 << ' ');


    Yea I used boost::lambda to do the same. But it's not possible to do
    with ISO C++ STL implementation
     
    Sarath, May 30, 2007
    #4
  5. Sarath

    James Kanze Guest

    On May 30, 2:16 am, Sarath <> wrote:
    > 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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 30, 2007
    #5
  6. Sarath

    Jon Harrop Guest

    Sarath wrote:
    > 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.

    --
    Dr Jon D Harrop, Flying Frog Consultancy
    OCaml for Scientists
    http://www.ffconsultancy.com/products/ocaml_for_scientists/?usenet
     
    Jon Harrop, May 30, 2007
    #6
  7. <> wrote:

    > 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.


    --
    Cheers,
    Robbie Hatley
    lonewolf aatt well dott com
    triple-dubya dott tustinfreezone dott org
     
    Robbie Hatley, May 30, 2007
    #7
  8. On Wed, 30 May 2007 15:30:36 +0100, Jon Harrop wrote:
    >
    >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.


    --
    Roland Pibinger
    "I often think that the sole purpose of the STL is to see how many
    lines one can use to obfuscate a simple loop." - John Potter
     
    Roland Pibinger, May 30, 2007
    #8
  9. Sarath

    James Kanze Guest

    On May 30, 5:02 pm, "Robbie Hatley" <> wrote:
    > <> wrote:
    > > 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?


    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.)

    > > 2) you can apply side-effects on the function object


    > ?


    The function object can do just about anything which won't
    invalidate the iterators. Including modifying program state.

    > > 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.


    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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 31, 2007
    #9
  10. Sarath

    Noah Roberts Guest

    Robbie Hatley wrote:
    > <> wrote:
    >
    >> 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.


    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?
     
    Noah Roberts, May 31, 2007
    #10
  11. Sarath

    Jerry Coffin Guest

    In article <f3ms70$ubl$>, says...

    [ ... ]

    > 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.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jun 2, 2007
    #11
  12. 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
     
    Robbie Hatley, Jun 4, 2007
    #12
  13. Sarath

    Jon Harrop Guest

    Robbie Hatley wrote:
    > 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.

    --
    Dr Jon D Harrop, Flying Frog Consultancy
    OCaml for Scientists
    http://www.ffconsultancy.com/products/ocaml_for_scientists/?usenet
     
    Jon Harrop, Jun 5, 2007
    #13
  14. Sarath

    V.R. Marinov Guest

    On May 30, 6:02 pm, "Robbie Hatley" <> wrote:
    > <> wrote:
    > > 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.


    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.
     
    V.R. Marinov, Jun 5, 2007
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ibe

    loop -> for_each

    ibe, Jan 13, 2006, in forum: C++
    Replies:
    1
    Views:
    353
    Thomas Jakob
    Jan 13, 2006
  2. ibe

    loop -> for_each

    ibe, Jan 20, 2006, in forum: C++
    Replies:
    0
    Views:
    341
  3. ibe
    Replies:
    5
    Views:
    388
    Luke Meyers
    Jan 20, 2006
  4. Skirmish
    Replies:
    9
    Views:
    985
    James Kanze
    Jul 24, 2007
  5. Isaac Won
    Replies:
    9
    Views:
    391
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page