Topic: foreach(collection){f(collection.current());}
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Tue, 21 Jun 2005 19:59:25 GMT Raw View
Maciej Sobczak wrote:
> Gene Bushuyev wrote:
>
>> The only inconvenience is
>> that Func has to be a non-local functor class or function, which may lead
>> to a big number of them living in a namespace scope.
>
> Which brings up an important point: instead of providing many small
> features to solve many small problems, it might be better to solve one
> "true" problem, which is lack of lambda (or whatever we call it).
> Then, foreach (and alike) will become a non-issue.
>
>> So you can
>> write something like:
>> for_each(a.begin(), a.end(), std::cout << _1 << ' ');
>
If we could define and instantiate class objects within a function call,
that might address the problem. And produce its own set of memory
management issues. I haven't given the Boost.Lambda library careful study,
but it's clear from glancing at it that it would require that in order to
use it for all but the simplest circumstances. It seems like a language
unto itsself. Perhaps it could rightly be called a meta-language. I
shouldn't need a PhD in functional programming to use a convenience
feature.
Perhaps I'm overstating the difficulty and novelty of working with
Boost.Lambda. It may also be the case that I need to study the STL
function adapters more closely. If there really are good, learnable ways
to accomplish the same things programmers would use foreach for, it would
be a bad idea to introduce such a redundancy into the language. OTOH, the
foreach construct is very easy to understand and use. I cannot say the
same for working with STL function adapters and algorithms.
A reasonable thing to ask is: what does the current approach of using
function adapters (and perhaps lambda objects) provide that a foreach
construct would not? And vis-versa.
--
STH
http://www.kdevelop.org
http://www.suse.com
http://www.mozilla.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Thorsten Ottosen" <nesotto@cs.auc.dk>
Date: 21 Jun 2005 21:20:02 GMT Raw View
""Steven T. Hatton"" <hattons@globalsymmetry.com> wrote in message
news:U_qdnSfsIe4vvirfRVn-tA@speakeasy.net...
| It's quite obvious that I am not the first person to suggest a foreach
| construct in C++. A simple search of the Internet will show that. What I
| did not immediately find while searching was evidence that this has been
| considered by the C++ Standards Committee.
| I'm not sure if any of the forms discussed in the links above allow for
| specifying a subrange of the collection being iterated over, but it seems
| like a reasonable addition. I will suggest something along the lines of
| Opinions?
Have you seen
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1796.html
???
Subranges are no problem, for example,
for( X& x : my_vector | sub_range( 1, 5 ) )
std::cout x;
^^^^^^^^^^^^^^^^^
The underlined portion would be operator|() and
sub_range() in a library.
-Thorsten
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Tue, 21 Jun 2005 23:29:17 GMT Raw View
Thorsten Ottosen wrote:
>
> ""Steven T. Hatton"" <hattons@globalsymmetry.com> wrote in message
> news:U_qdnSfsIe4vvirfRVn-tA@speakeasy.net...
> | It's quite obvious that I am not the first person to suggest a foreach
> | construct in C++. A simple search of the Internet will show that. What
> | I did not immediately find while searching was evidence that this has
> | been considered by the C++ Standards Committee.
>
> | I'm not sure if any of the forms discussed in the links above allow for
> | specifying a subrange of the collection being iterated over, but it
> | seems
> | like a reasonable addition. I will suggest something along the lines of
>
> | Opinions?
>
> Have you seen
>
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1796.html
>
> ???
>
> Subranges are no problem, for example,
>
> for( X& x : my_vector | sub_range( 1, 5 ) )
> std::cout x;
>
> ^^^^^^^^^^^^^^^^^
> The underlined portion would be operator|() and
> sub_range() in a library.
>
> -Thorsten
Your poposal seem to address the same topic as I was raising. I do have a
couple of questions about your proposal. First of all I'm not sure what
this example means:
// pairs of iterators
typedef vector<int>::iterator iter;
std::pair<iter,iter> p = ...;
for( int i : p )
std::cout << i;
Here p is a pair<vector<int>::iterator, vector<int>::iterator>. What does
it mean to iterate over that? And where is 'i' coming from? Am I to
understand this as p.first = myVector.begin(); p.second = myVector.end();
with the alternative p.first = MyVector.begin() + offset; p.second =
p.first + rangeSize;?
Secondly, is this C++?
namespace std
{
template< class T >
auto begin( T&& t ) -> decltype( t.begin() ) // Huh?
{
return t.begin();
}
template< class T >
auto end( T&& t ) -> decltype( t.end() ) // What does this mean?
{
return t.end();
}
}
I'll be happy to visit the Standard, or authoritative text to learn about
that syntax if you could provide a reference. As it stands, I don't recall
ever seeing a construct like that, and do not know how to apply my
knowledge of C++ to understand it.
--
STH
http://www.kdevelop.org
http://www.suse.com
http://www.mozilla.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Wed, 22 Jun 2005 14:59:02 GMT Raw View
""Steven T. Hatton"" <hattons@globalsymmetry.com> wrote in message
news:PKKdncnXFpTaPCXfRVn-3A@speakeasy.net...
| Thorsten Ottosen wrote:
| Your poposal seem to address the same topic as I was raising. I do have a
| couple of questions about your proposal. First of all I'm not sure what
| this example means:
|
| // pairs of iterators
| typedef vector<int>::iterator iter;
| std::pair<iter,iter> p = ...;
| for( int i : p )
| std::cout << i;
|
| Here p is a pair<vector<int>::iterator, vector<int>::iterator>. What does
| it mean to iterate over that? And where is 'i' coming from? Am I to
| understand this as p.first = myVector.begin(); p.second = myVector.end();
| with the alternative p.first = MyVector.begin() + offset; p.second =
| p.first + rangeSize;?
it does not matter how the pair of iterators is contructed...as long
as the pair denotes a valid range [p.first, p.second)
|
| Secondly, is this C++?
|
| namespace std
| {
|
| template< class T >
| auto begin( T&& t ) -> decltype( t.begin() ) // Huh?
| {
| return t.begin();
| }
|
| template< class T >
| auto end( T&& t ) -> decltype( t.end() ) // What does this mean?
| {
| return t.end();
| }
| }
it means the return type is deduced from the expressions inside "decltype".
| I'll be happy to visit the Standard, or authoritative text to learn about
| that syntax if you could provide a reference. As it stands, I don't recall
| ever seeing a construct like that, and do not know how to apply my
| knowledge of C++ to understand it.
It's not officially C++ yet, but an extension that is being seriously
considered
for C++0x as well. Without it, my proposal would require a lot of extra
machinery.
You can find papers about it among the other official C++ papers.
br
Thorsten
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 22 Jun 2005 15:14:27 GMT Raw View
no.spam@no.spam.com (Maciej Sobczak) writes:
> Gene Bushuyev wrote:
>
>> The only inconvenience is that Func has to be a non-local functor
>> class or function, which may lead to a big number of them living in
>> a namespace scope.
>
> Which brings up an important point: instead of providing many small
> features to solve many small problems, it might be better to solve one
> "true" problem, which is lack of lambda (or whatever we call it).
> Then, foreach (and alike) will become a non-issue.
Solving the true lambda problem is important, but it's at least partly
orthogonal. Lambdas concern getting the body of the function into the
for_each call, but they do nothing to address the problem of pulling
out the iterators to pass on to for_each when the collection is not
sitting in a variable you can name.
Even if we do get real lambdas (and especially if we get them with
parameter type declarations as many people seem to want), these loops
will still be much more verbose and error-prone to write than they
would be with a proper for_each construct.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: f.fracassi@gmx.net (Fabio Fracassi)
Date: Wed, 22 Jun 2005 14:57:15 GMT Raw View
Steven T. Hatton wrote:
> Thorsten Ottosen wrote:
>
>>
>> ""Steven T. Hatton"" <hattons@globalsymmetry.com> wrote in message
>> news:U_qdnSfsIe4vvirfRVn-tA@speakeasy.net...
> Your poposal seem to address the same topic as I was raising. I do have a
> couple of questions about your proposal. First of all I'm not sure what
> this example means:
>
> // pairs of iterators
> typedef vector<int>::iterator iter;
> std::pair<iter,iter> p = ...;
> for( int i : p )
> std::cout << i;
>
> Here p is a pair<vector<int>::iterator, vector<int>::iterator>. What does
> it mean to iterate over that? And where is 'i' coming from? Am I to
> understand this as p.first = myVector.begin(); p.second = myVector.end();
> with the alternative p.first = MyVector.begin() + offset; p.second =
> p.first + rangeSize;?
>
Yes, "p" is just a pair of iterators, which get treated as a range.
The "i" comes from the for declaration. (Read the "for(int i : p )" as "FOR
EACH int i IN p ..." )
> Secondly, is this C++?
>
> namespace std
> {
>
> template< class T >
> auto begin( T&& t ) -> decltype( t.begin() ) // Huh?
> {
> return t.begin();
> }
>
> template< class T >
> auto end( T&& t ) -> decltype( t.end() ) // What does this mean?
> {
> return t.end();
> }
> }
>
It is another proposal:
I suppose its:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1794.pdf
or
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1607.pdf
> I'll be happy to visit the Standard, or authoritative text to learn about
> that syntax if you could provide a reference. As it stands, I don't
> recall ever seeing a construct like that, and do not know how to apply my
> knowledge of C++ to understand it.
Perhaps you should familarize yourself with what is currently being
discussed in the commites. I'd suggest poking around
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/ for a while.
HTH
Fabio
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 22 Jun 2005 15:14:05 GMT Raw View
gb@127.0.0.1 ("Gene Bushuyev") writes:
> I don't think you'll gather a big support for a new language feature, which
> isn't very clear either. But is there really a need for a new language
> extension? I don't think so.
> The standard library for_each:
>
> template<class InputIterator, class Function>
> Function for_each(
> InputIterator _First,
> InputIterator _Last,
> Function _Func
> );
>
> is a straightforward algorithm to traverse ranges.
Not straightforward enough for many peoples' purposes, which is why
they invent library solutions like
http://www.artima.com/cppsource/foreach.html.
The need to name an iterator type can be a real problem in the case
where the collection to be iterated is being generated on the fly as
the result of calling some function.
I think there's room in the language for something like this, but I'm
not sure we know exactly what shape it should take yet.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Mon, 20 Jun 2005 20:30:10 GMT Raw View
It's quite obvious that I am not the first person to suggest a foreach
construct in C++. A simple search of the Internet will show that. What I
did not immediately find while searching was evidence that this has been
considered by the C++ Standards Committee.
The following links discuss some implementation of the "for-each" construct.
This is somewhat different than the C++ for_each() algorithm. This is
something of a cross between the C++ algorithm concept and a traditional
control structure (for, while, do while, etc.).
http://perl.about.com/cs/beginningperl/a/010703_2.htm
http://www.math.uni-bremen.de/techdoc/software1/bash/loops1.html
http://www.codeproject.com/cpp/foreach.asp
http://doc.trolltech.com/4.0/containers.html#the-foreach-keyword
http://www.jaggersoft.com/csharp_standard/15.8.4.htm
http://java.sun.com/j2se/1.5.0/docs/guide/language/foreach.html
I don't claim to be an expert in using any of the forms of foreach discussed
above. I encountered the for-each construct many years ago in perl. I
realized then it was a useful concept. I regularly use the bash variation
on the theme: for f in $(find . -name Makefile); do rm $f; done
I'm not sure if any of the forms discussed in the links above allow for
specifying a subrange of the collection being iterated over, but it seems
like a reasonable addition. I will suggest something along the lines of
foreach(col){ f(col.current(); }
Which could implicitly be interprated as:
foreach(col.begin(), col.end()) { f(col.current(); }
Which would be the default of the more general:
foreach(start, stop) { f(col.current(); }
where start, and stop are iterators over col.
Another reasonable variation might be:
foreach(start) { f(col.current(); }
Which would iterator over (start, col.end()]
The advantage of this kind of foreach over the STL for_each is that the body
of the loop is more flexible than the single function call in the
algorithm.
Opinions?
--
STH
http://www.kdevelop.org
http://www.suse.com
http://www.mozilla.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gb@127.0.0.1 ("Gene Bushuyev")
Date: Mon, 20 Jun 2005 22:20:27 GMT Raw View
""Steven T. Hatton"" <hattons@globalsymmetry.com> wrote in message
news:U_qdnSfsIe4vvirfRVn-tA@speakeasy.net...
.
> I'm not sure if any of the forms discussed in the links above allow for
> specifying a subrange of the collection being iterated over, but it seems
> like a reasonable addition. I will suggest something along the lines of
>
> foreach(col){ f(col.current(); }
>
> Which could implicitly be interprated as:
>
> foreach(col.begin(), col.end()) { f(col.current(); }
>
> Which would be the default of the more general:
>
> foreach(start, stop) { f(col.current(); }
>
> where start, and stop are iterators over col.
>
> Another reasonable variation might be:
> foreach(start) { f(col.current(); }
>
> Which would iterator over (start, col.end()]
>
> The advantage of this kind of foreach over the STL for_each is that the
> body
> of the loop is more flexible than the single function call in the
> algorithm.
I don't think you'll gather a big support for a new language feature, which
isn't very clear either. But is there really a need for a new language
extension? I don't think so.
The standard library for_each:
template<class InputIterator, class Function>
Function for_each(
InputIterator _First,
InputIterator _Last,
Function _Func
);
is a straightforward algorithm to traverse ranges. The only inconvenience is
that Func has to be a non-local functor class or function, which may lead to
a big number of them living in a namespace scope. Of course nothing
precludes you from using a for loop directly:
for(iterator i = first; i != last; ++i)
{
func(*i);
}
which is essentially what you are asking. Just be sure that iterators are
not being invalidated.
And finally, you can find a more syntactically pleasing form of for_each in
boost lambda library (http://www.boost.org/doc/html/lambda.html). So you can
write something like:
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
Gene
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Tue, 21 Jun 2005 13:49:45 GMT Raw View
Gene Bushuyev wrote:
> I don't think you'll gather a big support for a new language feature,
> which isn't very clear either.
I really wasn't trying to be very specific. I see a lot of different ways
such a feature could be designed. I do find it telling that C#, and now
Java, have opted for including/adding a foreach control structure. Also
Microsoft's Managed C++ (if I understood what I skimmed), and Qt have opted
for implementing their own language extention to provide a foreach
construct.
> But is there really a need for a new
> language extension? I don't think so.
> The standard library for_each:
>
> template<class InputIterator, class Function>
> Function for_each(
> InputIterator _First,
> InputIterator _Last,
> Function _Func
> );
>
> is a straightforward algorithm to traverse ranges. The only inconvenience
> is that Func has to be a non-local functor class or function, which may
> lead to a big number of them living in a namespace scope.
It can also be a bother to code them up. The idea is to make things more
consice. When you use the same functor, or functor-interface over and
over, then it makes sense. But if you are creating a namespace local, or
inner class functor for the sake of writing a single slick for_each
statement, you are likely wasting your time.
> Of course
> nothing precludes you from using a for loop directly:
> for(iterator i = first; i != last; ++i)
> {
> func(*i);
> }
foreach(T var, collection) func(var);
> which is essentially what you are asking. Just be sure that iterators are
> not being invalidated.
> And finally, you can find a more syntactically pleasing form of for_each
> in boost lambda library (http://www.boost.org/doc/html/lambda.html). So
> you can write something like:
> for_each(a.begin(), a.end(), std::cout << _1 << ' ');
I'm familiar with the basic idea:
echo "i0=5; j0=7; Table[(#1^#2) & @@ {i, j}, {i, 1, i0}, {j, 1, j0}]" | math
Mathematica 5.1 for Linux
Copyright 1988-2004 Wolfram Research, Inc.
-- Motif graphics initialized --
In[1]:=
Out[1]= {{1, 1, 1, 1, 1, 1, 1}, {2, 4, 8, 16, 32, 64, 128},
{3, 9, 27, 81, 243, 729, 2187}, {4, 16, 64, 256, 1024, 4096, 16384},
{5, 25, 125, 625, 3125, 15625, 78125}}
I've found that kind of syntax to be both powerful and difficult to work
with at times. If I understand correctly, the only limitation on the
complexity of the lambda functors is my skill in functional programming.
That may take some study. I have every confidence I can use the foreach
from Qt with virtually no learning curve to get started.
The big difference between for_each (STL) and foreach (suggested) is that
foreach can have a block of code to execute on each iteration. It's really
just a shorthand for a for() loop implemented using the iterators of the
collection passed to it.
I only mentioned it because I saw that there seems to be a proliferation of
"non-standard" extension being introduced. Actually what Trolltech have
done seems to be standard conforming in the sense that it's all done with
templates and the CPP. The only place they deviated from the standard
looks to be in their use of the GCC typeof extension. Since they only use
that for their GCC compile, it's pretty clear that not even that
constitutes an unreconcilable deviation from the Standard. Nonetheless,
there's evidently a real desire on the part of some significant players to
add the foreach functionality to their collection of utilities. That seems
to be a good indication that there may be a role for standardization in the
area.
--
STH
http://www.kdevelop.org
http://www.suse.com
http://www.mozilla.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: no.spam@no.spam.com (Maciej Sobczak)
Date: Tue, 21 Jun 2005 13:50:48 GMT Raw View
Gene Bushuyev wrote:
> The only inconvenience is
> that Func has to be a non-local functor class or function, which may lead to
> a big number of them living in a namespace scope.
Which brings up an important point: instead of providing many small
features to solve many small problems, it might be better to solve one
"true" problem, which is lack of lambda (or whatever we call it).
Then, foreach (and alike) will become a non-issue.
> So you can
> write something like:
> for_each(a.begin(), a.end(), std::cout << _1 << ' ');
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]