Haskell中的高阶函数究竟可以做什么,扩展C可以';T
GCC具有允许使用嵌套函数的功能Haskell中的高阶函数究竟可以做什么,扩展C可以';T,c,haskell,lambda,functional-programming,higher-order-functions,C,Haskell,Lambda,Functional Programming,Higher Order Functions,GCC具有允许使用嵌套函数的功能 实际上,我不明白Haskell中的高阶函数(或其他纯函数语言)能做什么,而C(函数指针和嵌套函数扩展)不能做什么?我从未使用过这个gcc扩展;但我会根据我对你给出的链接的解释来解释 就我对文档的理解而言,关键的区别在于,这些嵌套函数不允许您构建函数程序员在“闭包”下理解的内容——这些嵌套函数不能在其定义上下文之外使用,因为它们使用的堆栈变量在外部函数退出后丢失 在Haskell中,当我执行以下操作时: const x=\y->x foo=const 2——记住或
实际上,我不明白Haskell中的高阶函数(或其他纯函数语言)能做什么,而C(函数指针和嵌套函数扩展)不能做什么?我从未使用过这个gcc扩展;但我会根据我对你给出的链接的解释来解释 就我对文档的理解而言,关键的区别在于,这些嵌套函数不允许您构建函数程序员在“闭包”下理解的内容——这些嵌套函数不能在其定义上下文之外使用,因为它们使用的堆栈变量在外部函数退出后丢失 在Haskell中,当我执行以下操作时:
const x=\y->x
foo=const 2——记住或“结束”2
bar=foo1——现在,bar=2
您可以看到,当将const
应用于2
时,参数2
被我们称为foo
的闭包“保存”。之后,在栏中可以调用并返回2
,因为它仍然在foo
中被记住。然而,在C中:
typedef int(*int_至int_fn)(int);
int_至int_fn常数(int x)
{
int常数_impl(int y){返回x;}
返回常数\u impl;
}
int main()
{
int_至int_fn foo=常数(2);
int bar=foo(1);
}
这甚至可能不会编译,但如果它会编译,它将违背我们对C函数的基本期望:foo
中的x
,由常量
参数构成,需要保留在某个地方(可能不在堆栈上!),直到稍后调用foo
。这不是东西的基本工作原理——从这个意义上说,C是基本的(我们可能需要在堆上分配一些东西,复制东西,稍后清理,担心引用/值等)
通过研究C++11 lambda语法,可能会获得一些启示。在那里,constant\u impl
可以写在下面的某个地方:
auto constant_impl=[x](int y){return x;}
这里的[x]
部分正是我们告诉编译器“请替我记住x!”的地方。实际使用高阶函数的关键是需要闭包:一个普通的旧C函数,除了它的参数外,只能使用全局/静态数据。这意味着
GHCi>过滤器(>4)[7,4,3,6,87,5,4]
[7,6,87,5]
不能真正工作,除非你定义全局
bool largerThan4(int i) {return (i>4);}
这显然不符合比例。无法从程序中的其他地方“注入”数字4。函数式语言将此类信息打包在闭包中
现在,这个GNUC扩展为您提供了有限意义上的闭包,我认为这与:局部函数可以引用其包含范围内的变量的意义相同。这对,比如说
typedef std::vector<int> IntArray;
IntArray filter (const IntArray& a, std::function<bool(int)> pred) {
IntArray result;
for(auto& i: a) if (pred(i)) result.push_back(i);
return result;
}
int main() {
std::vector<int> v{{7,4,3,6,87,5,4}};
int minNumber = 4;
for(auto i: filter(v, [&](int i){return i>minNumber;}))
cout << i << endl;
return 0;
}
typedef std::vector IntArray;
IntArray过滤器(常量IntArray&a,标准::函数pred){
无阵列结果;
对于(auto&i:a)if(pred(i))结果,向后推(i);
返回结果;
}
int main(){
std::向量v{{7,4,3,6,87,5,4};
int minNumber=4;
for(自动i:filter(v,[&](int i){return i>minNumber;}))
cout高阶函数与嵌套函数定义几乎无关。您可以编写高阶函数,而无需此扩展;只需将函数指针作为参数或返回一个参数即可。是的,这些语言同样“强大”,haskell只需要做这些高阶函数,而不需要C所需的冗长。就像C可以处理状态而不需要haskell所需的冗长一样。@SteveCox正在替换的冗长{
withdo
,=
with它编译,但根据:如果在包含函数退出后试图通过其地址调用嵌套函数,所有的麻烦都会随之消失。