[Lambda] Help with if_then_else

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

[Lambda] Help with if_then_else

Scott Meyers
Consider this (working) code using Boost.FileSystem:

   fs::directory_iterator di(dir);
   fs::directory_iterator end;
   while (di != end) {
     if (is_directory(*di)) cout << "D\n";
     else cout << "~D\n";
     ++di;
   }

This looks like it should be lambda-able.  Here's my attempt:

   for_each(fs::directory_iterator(dir), fs::directory_iterator(),
            if_then_else(bind(&fs::is_directory, _1),
                         cout << "D\n",
                         cout << "~D\n"));

VC7.1 doesn't like this -- the diagnostics are below.  Any idea how I can make
this work?

Thanks,

Scott


fs.cpp(39) : error C2784: 'const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::ifthenelse_action,boost::tuples:
:tuple<boost::lambda::lambda_functor<Arg1>,boost::lambda::lambda_functor<Arg2>,boost::lambda::lambda_functor<Arg3>>>>
boost::lambda::if_then_else
(const boost::lambda::lambda_functor<Arg1> &,const
boost::lambda::lambda_functor<Arg2> &,const boost::lambda::lambda_functor<Arg3>
&)' : could no
t deduce template argument for 'const boost::lambda::lambda_functor<T2> &' from
'std::basic_ostream<_Elem,_Traits>'
         with
         [
             _Elem=char,
             _Traits=std::char_traits<char>
         ]
         D:\C++\Boost\Current\boost\lambda\if.hpp(100) : see declaration of
'boost::lambda::if_then_else'
fs.cpp(39) : error C2784: 'const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::ifthenelse_action,boost::tuples:
:tuple<boost::lambda::lambda_functor<Arg1>,boost::lambda::lambda_functor<Arg2>,boost::lambda::lambda_functor<Arg3>>>>
boost::lambda::if_then_else
(const boost::lambda::lambda_functor<Arg1> &,const
boost::lambda::lambda_functor<Arg2> &,const boost::lambda::lambda_functor<Arg3>
&)' : could no
t deduce template argument for 'const boost::lambda::lambda_functor<T2> &' from
'std::basic_ostream<_Elem,_Traits>'
         with
         [
             _Elem=char,
             _Traits=std::char_traits<char>
         ]
         D:\C++\Boost\Current\boost\lambda\if.hpp(100) : see declaration of
'boost::lambda::if_then_else'
fs.cpp(39) : error C2784: 'const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::ifthenelse_action,boost::tuples:
:tuple<boost::lambda::lambda_functor<Arg1>,boost::lambda::lambda_functor<Arg2>,boost::lambda::lambda_functor<Arg3>>>>
boost::lambda::if_then_else
(const boost::lambda::lambda_functor<Arg1> &,const
boost::lambda::lambda_functor<Arg2> &,const boost::lambda::lambda_functor<Arg3>
&)' : could no
t deduce template argument for 'const boost::lambda::lambda_functor<T2> &' from
'std::basic_ostream<_Elem,_Traits>'
         with
         [
             _Elem=char,
             _Traits=std::char_traits<char>
         ]
         D:\C++\Boost\Current\boost\lambda\if.hpp(100) : see declaration of
'boost::lambda::if_then_else'
fs.cpp(39) : error C2784: 'const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::ifthenelse_action,boost::tuples:
:tuple<boost::lambda::lambda_functor<Arg1>,boost::lambda::lambda_functor<Arg2>,boost::lambda::lambda_functor<Arg3>>>>
boost::lambda::if_then_else
(const boost::lambda::lambda_functor<Arg1> &,const
boost::lambda::lambda_functor<Arg2> &,const boost::lambda::lambda_functor<Arg3>
&)' : could no
t deduce template argument for 'const boost::lambda::lambda_functor<T2> &' from
'std::basic_ostream<_Elem,_Traits>'
         with
         [
             _Elem=char,
             _Traits=std::char_traits<char>
         ]
         D:\C++\Boost\Current\boost\lambda\if.hpp(100) : see declaration of
'boost::lambda::if_then_else'

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

Re: [Lambda] Help with if_then_else

Jaakko Järvi

On Mar 8, 2006, at 3:21 PM, Scott Meyers wrote:

> Consider this (working) code using Boost.FileSystem:
>
>    fs::directory_iterator di(dir);
>    fs::directory_iterator end;
>    while (di != end) {
>      if (is_directory(*di)) cout << "D\n";
>      else cout << "~D\n";
>      ++di;
>    }
>
> This looks like it should be lambda-able.  Here's my attempt:
>
>    for_each(fs::directory_iterator(dir), fs::directory_iterator(),
>             if_then_else(bind(&fs::is_directory, _1),
>                          cout << "D\n",
>                          cout << "~D\n"));
>
> VC7.1 doesn't like this -- the diagnostics are below.  Any idea how  
> I can make
> this work?
>

I can spot one thing at least:
Arguments to if_then_else must be lambda functions:

>             if_then_else(bind(&fs::is_directory, _1),
>                          var(cout) << "D\n",
>                          var(cout) << "~D\n"));


This delays the evaluation of the branches (which would otherwise  
just print D or ~D once,
when the lambda function is created, rather than during every  
iteration of for_each

Best, Jaakko

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

Re: [Lambda] Help with if_then_else

Daniel James
In reply to this post by Scott Meyers
On 3/8/06, Scott Meyers <[hidden email]> wrote:
> This looks like it should be lambda-able.  Here's my attempt:
>
>    for_each(fs::directory_iterator(dir), fs::directory_iterator(),
>             if_then_else(bind(&fs::is_directory, _1),
>                          cout << "D\n",
>                          cout << "~D\n"));
>
> VC7.1 doesn't like this -- the diagnostics are below.  Any idea how I can make
> this work?

Try out:

    for_each(fs::directory_iterator(dir), fs::directory_iterator(),
             if_then_else(bind(&fs::is_directory, _1),
                          cout << constant("D\n"),
                          cout << constant("~D\n")));

The problem is that 'cout << "D\n"' is getting called immediately - as
it's not a lambda expression, by making "D\n" a delayed constant it
becomes one. This is documented at http://tinyurl.com/7jq3v.

Hope that helps,

Daniel

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

Re: [Lambda] Help with if_then_else

Peter Dimov
In reply to this post by Scott Meyers
Scott Meyers wrote:

> Consider this (working) code using Boost.FileSystem:
>
>   fs::directory_iterator di(dir);
>   fs::directory_iterator end;
>   while (di != end) {
>     if (is_directory(*di)) cout << "D\n";
>     else cout << "~D\n";
>     ++di;
>   }
>
> This looks like it should be lambda-able.  Here's my attempt:
>
>   for_each(fs::directory_iterator(dir), fs::directory_iterator(),
>            if_then_else(bind(&fs::is_directory, _1),
>                         cout << "D\n",
>                         cout << "~D\n"));
>
> VC7.1 doesn't like this -- the diagnostics are below.  Any idea how I
> can make this work?

The cout << "D\n" subexpression is evaluated immediately since it doesn't
have any lambda components. Use var(cout) << "D\n" instead, or the ?:
variant:

    cout << if_then_else_return( bind(&fs::is_directory, _1), "D\n",
"~D\n" )

You could also make an alias for var(std::cout):

    var_type<std::ostream>::type cout = var( std::cout );

and use that in the lambda expressions.

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

Re: [Lambda] Help with if_then_else

Scott Meyers
In reply to this post by Scott Meyers
I tried both suggested solutions (applying var to cout, applying constant to the
  output string -- see below), but neither works.  What follows is a complete
compilation unit (not program -- there's no main) that fails with both VC7.1 and
gcc 3.4.2 when I uncomment either of the two for_each loops.  The error messages
are, um, not as enlightening as they might be.  Any suggestions how to get this
to work?

Thanks,

Scott

#include <iostream>
#include <string>
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/if.hpp"

void f(const std::string& dirName)
{
   using namespace std;

   namespace fs = boost::filesystem;
   fs::path dir(dirName, fs::native);

   using namespace boost::lambda;

//    for_each(fs::directory_iterator(dir), fs::directory_iterator(),
//             if_then_else(bind(&fs::is_directory, _1),
//                          cout << constant("D\n"),
//                          cout << constant("~D\n")));

//    for_each(fs::directory_iterator(dir), fs::directory_iterator(),
//             if_then_else(bind(&fs::is_directory, _1),
//                          var(cout) << "D\n",
//                          var(cout) << "~D\n"));

}

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

Re: [Lambda] Help with if_then_else

Daniel James
On 3/8/06, Scott Meyers <[hidden email]> wrote:

>The error messages
> are, um, not as enlightening as they might be.  Any suggestions how to get this
> to work?
>
> Thanks,
>
> Scott
>
> #include <iostream>
> #include <string>
> #include "boost/filesystem/operations.hpp"
> #include "boost/filesystem/path.hpp"
> #include "boost/lambda/bind.hpp"
> #include "boost/lambda/if.hpp"

You also need to include "boost/lambda/lambda.hpp", to declare operator<<.

Daniel

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

Re: [Lambda] Help with if_then_else

Scott Meyers
Daniel James wrote:
> You also need to include "boost/lambda/lambda.hpp", to declare operator<<.

Doh!  [Blush]

Thanks.

Scott

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