【问题标题】:Are recursive functions a special case of higher order functions递归函数是高阶函数的特例吗
【发布时间】:2014-11-05 15:17:06
【问题描述】:

维基百科指出:

在数学和计算机科学中,高阶函数(也 函数形式,函数或函子)是一个函数 以下至少一项:

  • 将一个或多个函数作为输入
  • 输出函数

还有,

递归函数是在执行过程中调用自身的函数 执行。

这是否意味着递归函数可以归类为高阶函数的一种特殊情况?

请参考这个案例:

int foo(int i)
{
    if(i>10)
    {
       return 10;
    }
    cout<<i;
    return foo(++i);
}

我不想要意见。请用具体的前提说明你的答案。

【问题讨论】:

  • 还有哪些分类可供我们选择?
  • 您在编辑中引用的函数不是“高阶函数”。它返回递归调用自身产生的,而不是返回一个函数。分享和享受。

标签: recursion computer-science higher-order-functions


【解决方案1】:

假设您的 Algol 方言不支持递归,但支持高阶函数。我们还能实现你的例子吗?当然可以!

int foo_aux(int i, Func cont)
{
    if( i>10 ) {
       return 10;
    } else {
       cout<<i;                 // side effect bad!
       return cont(i+1, cont);  // no recursion
    }
}

int foo(int i)
{
    return foo_aux(i, [] (int i, Func cont) -> int { return foo_aux(i,cont) });
}

假设您尝试做同样的事情,但您的语言不支持高阶函数也不支持递归。可以模仿吗?一切皆有可能:

std::stack<int> args;       // integers can be castable pointers or numbers!
int cont = 2;
while( cont ) {
  if( cont == 2 ) {         // main
      args.push(1)
      cont=1;               // continuation == foo_aux
  } else if ( cont == 1 ) { // foo_aux
      int tmp = args.pop();
      if( tmp > 10 ) {
          args.push(10);
          cont=0;           // continuation == return/exit
      } else {
          cout << tmp;
          args.push(tmp+1);
          // not setting cont == recursion
      }
  }
}
// do something with the result
return args.pop();

这是一种进行递归的方式,就像在您的初始示例中一样。也许您可以制作一个预处理器(宏)来从像您的示例这样的花哨的东西进行转换,以使其成为用于编译的对象。如果你想将函数作为参数传递,你只需按下数字,你的接收函数需要设置f

std::stack<int> args;       // integers can be castable pointers or numbers!
args.push(2)                // bootstrap
int cont = 0;
while( cont = args.pop() ) {
  if( cont == 2 ) {            // main / foo
      args.push(1)             // push argument
      args.push(1)             // push function
  } else if ( cont == 1 ) {    // foo_aux
      int tmp = args.pop();
      if( tmp > 10 ) {
          args.push(10);       // push result
          args.push(0);        // push exit as continuation 
      } else {
          cout << tmp;
          args.push(tmp+1);    // push argument
          args.push(1);        // push self as argument
      }
  }
}
// do something with the result
return args.pop();

这不支持所谓的向上funarg,因为那时您需要另一个结构来关闭不再在范围内的变量。

那么递归是高阶函数的特例吗?由于可以使用函数索引来模拟函数,因此从编译器的角度来看,可以同时实现函数、递归和高阶函数。这仅意味着可以以相同的方式对函数进行建模。完全有可能制作一个使用不支持高阶函数但支持递归的汇编函数的编译器,并且可以制作一种不支持高阶函数的没有递归的语言,这将能够使用类似 Y combinator 的方式进行递归.除此之外,它们是完全不同的东西。

【讨论】:

    【解决方案2】:

    没有。

    输出一个函数表示函数可以作为函数的返回值,像这样(Lua中的代码):

    function foo()
        return function(a,b) return a + b end
    end
    

    在您的递归函数示例中,返回值是表达式 foo(++i) 的结果,而不是函数 foo 本身。

    【讨论】:

    • 能不能把lua代码转换成c/c++/java/js.我无法理解单个语句中的使用或两个返回。
    • 我使用Lua是因为它支持高阶函数,即使你不知道也很容易理解。关键是function(a,b) return a + b end是函数定义的语法。
    【解决方案3】:

    没有。在这种情况下“输出”一个函数意味着返回一个函数,而不是返回调用函数的结果。也就是说,返回值本身是可调用的。一般来说,递归函数不一定要这样做。例如:

    def factorial(n: int) -> int:
        if n == 0:
            return 1
        else:
            return n*factorial(n-1)
    

    此代码返回一个整数。你不能调用整数,所以它不是高阶函数。

    【讨论】:

      【解决方案4】:

      高阶函数是可以将条件或函数作为参数的函数。它可以选择输出一个函数作为 return 语句。 因此,递归函数并不都是高级函数。 此外,高级函数并非都是递归的,因为有些函数只是使用条件作为参数。

      【讨论】:

        猜你喜欢
        • 2014-01-22
        • 2014-08-16
        • 2020-04-04
        • 2021-11-01
        • 2021-03-13
        • 2019-08-06
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        相关资源
        最近更新 更多