BOOST_FOREACH with Index

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

BOOST_FOREACH with Index

The Dude
  Hello,

  Boost::foreach is very useful for iterating over a sequence and doing something that depends only on the iterated element, e.g.,
<code>
BOOST_FOREACH(const Foo &f, foos)
  cout << f.bar() << endl;
</code>

  However, I often need to iterate over a sequence and do some operation that depends on both the iterated element and the iteration index. E.g., I would like something like
<code>
BOOST_FOREACH(size_t i, const Foo &f, foos)
  cout << "The bar of element " << i << " is " << f.bar() << endl;
</code>

  Is there an easy way to do so?

  Thanks & Bye,

  TD

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Eric Niebler-3
The Dude wrote:

>   Hello,
>
>   Boost::foreach is very useful for iterating over a sequence and doing
> something that depends only on the iterated element, e.g.,
> <code>
> BOOST_FOREACH(const Foo &f, foos)
>   cout << f.bar() << endl;
> </code>
>
>   However, I often need to iterate over a sequence and do some operation
> that depends on both the iterated element and the iteration index. E.g.,
> I would like something like
> <code>
> BOOST_FOREACH(size_t i, const Foo &f, foos)
>   cout << "The bar of element " << i << " is " << f.bar() << endl;
> </code>
>
>   Is there an easy way to do so?


Why not:

   int index = 0;
   BOOST_FOREACH(const Foo &f, foos)
   {
     // ... stuff ...
     ++index;
   }

?

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

The Dude


On Sun, Dec 13, 2009 at 11:51 PM, Eric Niebler <[hidden email]> wrote:
The Dude wrote:
 Hello,

 Boost::foreach is very useful for iterating over a sequence and doing something that depends only on the iterated element, e.g.,
<code>
BOOST_FOREACH(const Foo &f, foos)
 cout << f.bar() << endl;
</code>

 However, I often need to iterate over a sequence and do some operation that depends on both the iterated element and the iteration index. E.g., I would like something like
<code>
BOOST_FOREACH(size_t i, const Foo &f, foos)
 cout << "The bar of element " << i << " is " << f.bar() << endl;
</code>

 Is there an easy way to do so?


Why not:

 int index = 0;

 BOOST_FOREACH(const Foo &f, foos)
 {
   // ... stuff ...
   ++index;
 }

?

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users


  Hello,

  Thanks for you answer. I'm not sure how to answer the "why not"? The code you write certainly will work, but so would the predecessor to BOOST_FOREACH in the first place, no? So here's my attempt:
1. For shorter loops, this changes 2 LOCs to 5.
2. For longer loops, the iteration code changes its meaning if it appears before the ++index or after.
3. The variable index has scope outside the loop.
4. Other people think so, e.g., the author's of D language http://en.wikipedia.org/wiki/D_(programming_language)#Example_1
  It's true that none of these points is really a proof. Still, I'd be really happy to hack my own INDEX_FOREACH, but the 500+ LOCs of BOOST_FOREACH left me daunted.

  Thanks & Bye,

  TD
 

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Eric Niebler-3
The Dude wrote:

> Eric Niebler wrote:
>>     Why not:
>>
>>      int index = 0;
>>
>>      BOOST_FOREACH(const Foo &f, foos)
>>      {
>>        // ... stuff ...
>>        ++index;
>>      }
>>
>>     ?
>
>   Thanks for you answer. I'm not sure how to answer the "why not"? The
> code you write certainly will work, but so would the predecessor to
> BOOST_FOREACH in the first place, no? So here's my attempt:
> 1. For shorter loops, this changes 2 LOCs to 5.

So put it all on one line! Kidding. ;-)

> 2. For longer loops, the iteration code changes its meaning if it
> appears before the ++index or after.
> 3. The variable index has scope outside the loop.
> 4. Other people think so, e.g., the author's of D language
> http://en.wikipedia.org/wiki/D_(programming_language)#Example_1
>   It's true that none of these points is really a proof. Still, I'd be
> really happy to hack my own INDEX_FOREACH, but the 500+ LOCs of
> BOOST_FOREACH left me daunted.

This is true, but I'm not convinced. What value BOOST_FOREACH has comes
primarily from its ability to simplify something that's already pretty
darn simple -- a plain for(;;) loop. I strongly resist any effort to
make BOOST_FOREACH more complicated, unless the wins are truly
significant. In this case, I don't think they are.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Nat Goodspeed-2
Eric Niebler wrote:

>>>     Why not:
>>>
>>>      int index = 0;
>>>
>>>      BOOST_FOREACH(const Foo &f, foos)
>>>      {
>>>        // ... stuff ...
>>>        ++index;
>>>      }

> What value BOOST_FOREACH has comes
> primarily from its ability to simplify something that's already pretty
> darn simple -- a plain for(;;) loop. I strongly resist any effort to
> make BOOST_FOREACH more complicated, unless the wins are truly
> significant. In this case, I don't think they are.

Maybe this shouldn't be a BOOST_FOREACH feature at all. As with Python's
builtin enumerate() function, maybe what we want here is an iterator
adapter that dereferences to a std::pair<index_type,
original_iterator_value_type>?
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

OvermindDL1
On Sun, Dec 13, 2009 at 6:41 PM, Nat Goodspeed <[hidden email]> wrote:

> Eric Niebler wrote:
>
>>>>    Why not:
>>>>
>>>>     int index = 0;
>>>>
>>>>     BOOST_FOREACH(const Foo &f, foos)
>>>>     {
>>>>       // ... stuff ...
>>>>       ++index;
>>>>     }
>
>> What value BOOST_FOREACH has comes primarily from its ability to simplify
>> something that's already pretty darn simple -- a plain for(;;) loop. I
>> strongly resist any effort to make BOOST_FOREACH more complicated, unless
>> the wins are truly significant. In this case, I don't think they are.
>
> Maybe this shouldn't be a BOOST_FOREACH feature at all. As with Python's
> builtin enumerate() function, maybe what we want here is an iterator adapter
> that dereferences to a std::pair<index_type, original_iterator_value_type>?

Ooo, that makes sense, as long as it can still be done quickly (ala
the in index = 0; example above):
BOOST_FOREACH(size_t i, const Foo &f, ENUMERATE(foos))

Or maybe:
BOOST_FOREACH_ENUMERATE(size_t i, const Foo &f, foos)
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

OvermindDL1
On Sun, Dec 13, 2009 at 7:11 PM, OvermindDL1 <[hidden email]> wrote:

> On Sun, Dec 13, 2009 at 6:41 PM, Nat Goodspeed <[hidden email]> wrote:
>> Eric Niebler wrote:
>>
>>>>>    Why not:
>>>>>
>>>>>     int index = 0;
>>>>>
>>>>>     BOOST_FOREACH(const Foo &f, foos)
>>>>>     {
>>>>>       // ... stuff ...
>>>>>       ++index;
>>>>>     }
>>
>>> What value BOOST_FOREACH has comes primarily from its ability to simplify
>>> something that's already pretty darn simple -- a plain for(;;) loop. I
>>> strongly resist any effort to make BOOST_FOREACH more complicated, unless
>>> the wins are truly significant. In this case, I don't think they are.
>>
>> Maybe this shouldn't be a BOOST_FOREACH feature at all. As with Python's
>> builtin enumerate() function, maybe what we want here is an iterator adapter
>> that dereferences to a std::pair<index_type, original_iterator_value_type>?
>
> Ooo, that makes sense, as long as it can still be done quickly (ala
> the in index = 0; example above):
> BOOST_FOREACH(size_t i, const Foo &f, ENUMERATE(foos))
>
> Or maybe:
> BOOST_FOREACH_ENUMERATE(size_t i, const Foo &f, foos)
>

Er, meant my first example to be:
BOOST_FOREACH(tuple<size_t, const Foo&> t, ENUMERATE(foos))
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Eric Niebler-3
In reply to this post by Nat Goodspeed-2
Nat Goodspeed wrote:

> Eric Niebler wrote:
>
>>>>     Why not:
>>>>
>>>>      int index = 0;
>>>>
>>>>      BOOST_FOREACH(const Foo &f, foos)
>>>>      {
>>>>        // ... stuff ...
>>>>        ++index;
>>>>      }
>
>> What value BOOST_FOREACH has comes primarily from its ability to
>> simplify something that's already pretty darn simple -- a plain
>> for(;;) loop. I strongly resist any effort to make BOOST_FOREACH more
>> complicated, unless the wins are truly significant. In this case, I
>> don't think they are.
>
> Maybe this shouldn't be a BOOST_FOREACH feature at all. As with Python's
> builtin enumerate() function, maybe what we want here is an iterator
> adapter that dereferences to a std::pair<index_type,
> original_iterator_value_type>?

This would fit in well with the proposed resolution of
https://svn.boost.org/trac/boost/ticket/3469. I'll reference this
discussion from that ticket. Thanks for the suggestion.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Daniel James
In reply to this post by The Dude
2009/12/13 The Dude <[hidden email]>:
>
>   It's true that none of these points is really a proof. Still, I'd be
> really happy to hack my own INDEX_FOREACH, but the 500+ LOCs of
> BOOST_FOREACH left me daunted.

It's not that hard:

#define INDEX_FOREACH(index,a,b)                            \
    for(unsigned int index = static_cast<unsigned int>(-1); \
        index == static_cast<unsigned int>(-1);)            \
            BOOST_FOREACH(a,b) if(++index,true)

INDEX_FOREACH(i, const Foo &f, foos)
  cout << "The bar of element " << i << " is " << f.bar() << endl;
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Mathias Gaunard-2
In reply to this post by The Dude
The Dude a écrit :

>   However, I often need to iterate over a sequence and do some operation
> that depends on both the iterated element and the iteration index. E.g.,
> I would like something like
> <code>
> BOOST_FOREACH(size_t i, const Foo &f, foos)
>   cout << "The bar of element " << i << " is " << f.bar() << endl;
> </code>
>
>   Is there an easy way to do so?

The index is not something generic enough.
What you would want in the general case is the iterator. But then, you
might as well use the real for loop, since BOOST_FOREACH_IT couldn't be
really less complicated.

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Mathias Gaunard-2
In reply to this post by Nat Goodspeed-2
Nat Goodspeed wrote:

> Maybe this shouldn't be a BOOST_FOREACH feature at all. As with Python's
> builtin enumerate() function, maybe what we want here is an iterator
> adapter that dereferences to a std::pair<index_type,
> original_iterator_value_type>?

Couldn't you just do a BOOST_FOREACH over combine(count_range(), foos)
  for that?

(uses zip_iterator)

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Pete Bartlett-2
In reply to this post by The Dude

> Nat Goodspeed wrote:
> > Maybe this shouldn't be a BOOST_FOREACH feature at all. As with
> Python's
> > builtin enumerate() function, maybe what we want here is an
> iterator
> > adapter that dereferences to a std::pair
> original_iterator_value_type>?

> Couldn't you just do a BOOST_FOREACH over combine(count_range(),
> foos)
> for that?
> (uses zip_iterator)

Yup, Nat's idea is a nice one and easy to implement. As Eric alluded to with his reference to the ticket on FOREACH_FIELD, the heart of the matter really though is getting a syntactically convenient version. We've seen this situation - where we have the neat iterators/ranges but not the syntactic convenience - a few times (REVERSE_FOREACH, FOREACH_FIELD, this "FOREACH_WITHINDEX" spring to mind) - I wonder if there is an opportunity to expose a lower level API in the FOREACH mini-library that would enable advanced users to build such macros themselves.
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: BOOST_FOREACH with Index

Patrick Horgan-2
In reply to this post by Eric Niebler-3
Eric Niebler wrote:
> This is true, but I'm not convinced. What value BOOST_FOREACH has
> comes primarily from its ability to simplify something that's already
> pretty darn simple -- a plain for(;;) loop. I strongly resist any
> effort to make BOOST_FOREACH more complicated, unless the wins are
> truly significant. In this case, I don't think they are.
>
Thanks:)  It's one of my pet peeves.  How about when someone uses
BOOST_FOREACH when they don't really mean foreach and intend to break
out of the loop and use an internal variable outside the loop.  It gets
more complicated then if they'd written their own loop.  BOOST_FOREACH
does one thing and does it well, please leave it alone, and please don't
use it when it's not what you want.  If you're having to jump through
hoops to make it work, it's not the right tool;)  JM2C;)

Patrick

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users