Lazy sequences in idiomatic C++ using iterators
ideone.com
ideone.com
auto q = LINQ(
from(z, boost::irange(1, std::numerical_limits<int>::max()))
from(x, boost::irange(1, z))
from(y, boost::irange(1, x))
where(x*x + y*y == z*z)
select(boost::fusion::make_vector(x, y, z))
);
for(auto&& x:q | linq::take(10)) std::cout << x << std::endl;
Hopefully, once we get ranges in the C++ standard library, we can add list comprehension to the language, perhaps something like this: auto q = [
for (z, std::irange(1, std::numerical_limits<int>::max()))
for (x, std::irange(1, z))
for (y, std::irange(1, x))
if (x*x + y*y == z*z)
boost::fusion::make_vector(x, y, z)
];
for(auto&& x:q | std::take(10)) std::cout << x << std::endl; goto cont;
for (; ; ++z)
for (; x <= z; ++x)
for (; y <= z; ++y) {
if (x*x + y*y == z*z) return *this;
cont:
}I saw another proposal referencing the original article which used a trio of functions in a nice way to achieve something similar without the goto (and without the ifs). My main point was to illustrate the use of custom iterators.
The goto version only has one unconditional branch outside of a loop, rather than three conditional branches inside loops. Anyways, the speed difference shouldn't be too big, as the branches are pretty predictable (pretty much always not taken).
Quick benchmark of the original and mine, up to the first 3000 triples:
$ c++ -O3 pyth1.cpp && time ./a.out | md5
33aa33d6cad59951489757e06aeb5a15
real 0m5.492s
user 0m5.484s
sys 0m0.007s
$ c++ -O3 pyth2.cpp && time ./a.out | md5
33aa33d6cad59951489757e06aeb5a15
real 0m4.248s
user 0m4.238s
sys 0m0.011sAnd the only point of having named break/continue would be to not use goto. I don't see the point in that, since to me, this:
for (i = 0; i < ie; i++) {
continue_i:
for (j = 0; j < je; j++) {
if (cond1)
goto break_i;
if (cond2)
goto continue_i;
/* ... */
}
}
break_i:
is as readable as this: loop_i:
for (i = 0; i < ie; i++) {
for (j = 0; j < je; j++) {
if (cond1)
break loop_i;
if (cond2)
continue loop_i;
/* ... */
}
}Your code is
take 10 mutable_spaghetti_functionI've found using const a lot also goes hand-in-hand with raii. If a member of a class is const it must be initialized in the constructor, and it just seems to make me code a bit more "hygienically".
pyth x = [(a,b,c) | a<-[1..x], b<-[1..x], c<-[1..x], (a^2)+(b^2) == (c^2)]The code may be spaghetti, but I mostly just lifted it from the referenced article and solved the problems the original author brought up, namely the separation of concerns. The C++ solution to this problem will never be as beautiful as the Haskell one, but I wanted to show it doesn't have to be alienating for people who program C++ daily.
C++ iterators are powerful, and can be used for a lot more than stepping through a container. We write too few of them.
Edit: A better way to write the inner loop: http://ideone.com/wEfNyh
Edit: When the values are initialized to 3, 4, 5 instead of 0, 0, 0, the program can be simplified to: http://ideone.com/oyNk1O
error: ‘copy_n’ was not declared in this scope
what is the problem? Is it something to do with gcc-4.8 and shared libs?
Thanks