【问题标题】:Fixed point combinators in C++C++ 中的定点组合器
【发布时间】:2010-09-14 04:53:56
【问题描述】:

我对使用定点组合器的实际示例感兴趣(例如 C++ 中的y-combinator。您是否曾经在实际代码中使用过带有eggbind 的定点组合器?

我在 egg 中发现这个例子有点密集:

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);
}

你能解释一下这一切是如何运作的吗?

有没有一个很好的简单示例,可能使用依赖项可能比这个更少的绑定?

【问题讨论】:

  • 如果您编写的代码看起来没有人能够维护它,包括您自己。
  • 我的意思不是我真的想在 C++ 中编写定点组合器或 lambda,而是对于像我这样不太熟悉的人来说,C++ 中的一个例子会有所启发它们可能更有用的语言。

标签: c++ bind y-combinator


【解决方案1】:

这里是转换成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;
}

【讨论】:

  • 这正是我想要的。希望我能两次投票给你
【解决方案2】:
#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;
}

【讨论】:

  • 效果很好,也是纯 C++ 11
【解决方案3】:

你能解释一下这一切是如何运作的吗?

fix2 是一个 y 组合子(具体来说,它是具有两个参数的函数的组合子;第一个参数是函数(用于递归),第二个参数是“适当的”函数参数)。它创建递归函数。

bll::ret(...) 似乎创建了某种形式的函数对象,其主体是

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

“惰性”可能是为了阻止第一个(函数)参数的无限扩展(阅读惰性和严格 y 组合器之间的区别以了解原因)。

代码非常糟糕。匿名函数固然不错,但解决 C++ 缺乏语法支持的黑客行为使它们不值得努力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多