-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160
David Abrahams wrote:
|
| I don't understand yet. What is the difference between stage_1 and
| stage_2? Fewer arguments in stage_1?
|
exactly.
e.g. stage reading from file:
template<typename Result>
struct file_reader {
~ typedef Result result_type;
~ istream f_;
~ const std::pair &operator()() {
~ static std::pair r;
~ f_.read(&r.first, sizeof(Result));
~ r.second = f_;
~ return r;
~ }
~ // some initialization stuff to set f_
};
stage calculating unary function on its input (and input is, of course,
a stage):
template
struct unary_op {
~ typedef Result result_type;
~ F1 f_;
~ Input1 input1_;
~ const std::pair &operator() {
~ static std::pair r;
~ typename Input1::result_type const &i1 = input1_();
~ r.first = f_(i1.first);
~ r.second = i1.second;
~ return r;
~ }
~ // some initialization to set input1_ and f_
};
stage adding its two inputs:
template
struct binary_op {
~ typedef Result result_type;
~ F2 f_;
~ Input1 input1_;
~ Input2 input2_;
~ const std::pair &operator() {
~ static std::pair r;
~ typename Input1::result_type const &i1 = input1_();
~ typename Input2::result_type const &i2 = input2_();
~ r.first = f_(i1.first, i2.first);
~ r.second = i1.second && i2.second;
~ return r;
~ }
~ // init to set i1_ and i2_
};
this would be the intended usage:
//
// reading input from 2 files, producing as result x + sqrt(y)
//
file_reader<double> f1(file1);
file_reader<double> f2(file2);
unary_op sqrt_stage(f2, sqrt);
binary_op add_stage(f1, sqrt_stage,
~ plus());
// this loop would be another "stage" parametrized by the function
// performing the actual work done in the body.
while(1) {
~ typename adder::result_type r = ad();
~ if(!r.second) break;
~ // do something with the data
}
ultimately, would it be possible to write somehting like:
file_reader f1(file1);
file_reader f2(file2);
// note the difference in structs! stages can convert types between
// input and output
//
// do some template magic :)
//
stage_op(
~ my_consumer_functor(), // obvious
~ stage_op( // producer for the consumer
~ plus(), // operation to perform on two inputs
~ f1, // provider for the first argument
~ stage_op(
~ sqrt<double>(), // function for this stage
~ f2))) // provider for this stage
If the outer stage_op(my_consumer_functor()..) is removed then I get a
'stream' from which I can extract individual element by calling
operator() repeatedly.
Please view this final use case as the thing I'm really trying to
achieve. The example stage implementations might be on the totally wrong
track.
Something along current container/iterator[1]/algorithm/functor
framework (no, I can't read the whole data set into memory :)), but
which would work in a 'lazy' manner producing values on demand only. I
believe this is called 'lazy evaluation' in some functional languages.
Also I need to be able to define alternate stopping criterion (e.g. stop
when ALL streams are exhausted, not the first one - this is useful for
merging several streams into a single stream).
[1] maybe just define new iterator classes?
In the meantime I've read the Phoenix documentation and it seems I could
achieve this with Phoenix. I might be mistaken. Tonight I'm writing my
first prototype code. I'm open to all suggestions.
Thanks in advance for all suggestions.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (FreeBSD)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFCye7KFtofFpCIfhMRA+I6AJsGCYmzftPKwYQfolrbryxNbPyMCQCfZo1E
c+qqZL0QV4qaSlKlpV5jsXE=
=O9qT
-----END PGP SIGNATURE-----