2008-09-30 3 views
7

Я заинтересован в реальных примерах использования комбинатора неподвижной точки (например, в y-combinator в C++. Вы когда-нибудь использовал комбинатор неподвижной точки с egg или bind в реальном живом коде?неподвижные точка комбинаторов в C++

I нашел этот пример в яйце немного плотное:?

void egg_example() 
{ 
    using bll::_1; 
    using bll::_2; 

    int r = 
     fix2(
      bll::ret<int>(
       // \(f,a) -> a == 0 ? 1 : a * f(a-1) 
       bll::if_then_else_return(_2 == 0, 
        1, 
        _2 * lazy(_1)(_2 - 1) 
       ) 
      ) 
     ) (5); 

    BOOST_CHECK(r == 5*4*3*2*1); 
} 

Можете ли вы объяснить, как это все работает

есть хороший простой пример, возможно, используя привязку с возможно меньшим количеством зависимостями, чем этот

+0

Если вы пишете код, который выглядит так, что никто никогда не сможет его поддерживать, включая вас самих. – 2008-09-30 07:34:41

+1

Моя мысль не в том, что я действительно хочу написать комбинаторы с фиксированной точкой или лямбда в C++, а скорее пример того, что на C++ будет назидать для кого-то вроде меня, который не все знает языки, на которых они могут быть более полезно. – 2008-10-01 06:36:39

ответ

29

Вот такой же код, преобразованный в boost::bind, обратите внимание на y-combinator и его сайт приложения в основной функции. Надеюсь, это поможет.

#include <boost/function.hpp> 
#include <boost/bind.hpp> 
#include <iostream> 

// Y-combinator compatible factorial 
int fact(boost::function<int(int)> f,int v) 
{ 
    if(v == 0) 
    return 1; 
    else 
    return v * f(v -1); 
} 

// Y-combinator for the int type 
boost::function<int(int)> 
    y(boost::function<int(boost::function<int(int)>,int)> f) 
{ 
    return boost::bind(f,boost::bind(&y,f),_1); 
} 


int main(int argc,char** argv) 
{ 
    boost::function<int(int)> factorial = y(fact); 
    std::cout << factorial(5) << std::endl; 
    return 0; 
} 
+0

Именно это я и искал. Хотел бы я дважды проголосовать за вас – 2008-09-30 19:57:19

3

Можете ли вы объяснить, как это все работает?

fix2 является у-комбинатор (в частности, это комбинатор для функций с двумя аргументами; первый аргумент функции (для целей рекурсии), второй аргумент является «правильный» аргумент функции) , Он создает рекурсивные функции.

BLL :: RET (...), как представляется, создать некоторую форму объекта функции, тело которого

if(second arg == 0) 
{ 
    return 1; 
} 
else 
{ 
    return second arg * first arg(second arg - 1); 
} 

«ленивый», по-видимому там, чтобы остановить бесконечное расширение первого (функции) (прочитайте разницу между ленивыми и строгими комбинаторами, чтобы понять, почему).

Код довольно ужасный. Анонимные функции приятно иметь, но хакерство для работы над отсутствием синтаксической поддержки C++ делает их нецелесообразными.

7
#include <functional> 
#include <iostream> 

template <typename Lamba, typename Type> 
auto y (std::function<Type(Lamba, Type)> f) -> std::function<Type(Type)> 
{ 
    return std::bind(f, std::bind(&y<Lamba, Type>, f), std::placeholders::_1); 
} 

int main(int argc,char** argv) 
{ 
    std::cout << y < std::function<int(int)>, int> ([](std::function<int(int)> f, int x) { 
     return x == 0 ? 1 : x * f(x - 1); 
    }) (5) << std::endl; 
    return 0; 
} 
Смежные вопросы