为什么C11不支持lambda函数

时间:2013-08-09 13:23:40

标签: c lambda c11

新的C ++ 11标准支持lambda函数,我认为这是一个有用的功能。我知道C和C ++标准彼此不同但我不明白为什么C11不支持lambda函数。我认为它可以有很多用途。

C11标准的开发人员是否选择不包含此功能?

3 个答案:

答案 0 :(得分:8)

C旨在成为一种简单易懂的语言。当通过更简单的方法完成相同的事情时,它故意省略高级功能。它旨在提供便携式编程绝对必要的基本功能。

C没有引用,因为它们只是指针。 C没有类,继承和虚函数,因为你可以使用结构并使用函数指针自己创建vtable。它没有垃圾收集器,因为程序员可以自己跟踪内存分配,它没有模板,因为它们实际上只是宏。如果需要例外,可以使用longjmp,而不是命名空间,只需在名称中添加前缀即可。

添加任何这些高级快捷方式可能会使编程更加舒适,但这需要以使语言更复杂为代价,这一点不容小觑。这是一个滑坡,直接导致C ++变得混乱。

C没有lambda函数,因为它们不是必需的。相反,您可以使用静态函数并将上下文放在结构中。

答案 1 :(得分:7)

2016更新:带有封闭的苹果风格的lambd再次在伦敦2016年会议上以new proposal document的形式呈现给工作组,试图解决其中的几个失败问题。以前的尝试,整理术语和解释,并详细介绍如何将闭包和lambdas制成“C-like”。

the reception was cautiously positive(7-0-9是/否/弃权)以来,很可能会发现类似于此的内容很快就会成为语言。


简短的回答只是C不包含lambda函数,因为还没有人向ISO C工作组提出可接受的提议来包含lambda函数。

您可以在此处查看工作组讨论的一些提案列表:http://www.open-std.org/jtc1/sc22/wg14/www/documents

我在该列表中可以找到的任何类型的lambdas的唯一提议是Apple的块(如Yu Hao的回答所示),在文档N1451中。该提案将在N1483进一步讨论,将其与C ++ lambdas进行比较,N1493N1542进行讨论,这些会议记录是提交这些文件的会议记录。

在N1542中,有几个原因导致N1451中的提案无法被接受:

  • 最初委员会难以理解提案
  • 它使用与现有C标准相矛盾的错误引用和术语
  • 显然含糊不清
  • Apple正在尝试为该功能申请专利(不清楚这是否是标准化的障碍,但我会这样认为)
  • 2010年提出全新语义的全新功能在2011年及时准备就绪的可能性很小,并且会阻碍C11的发布
  • 提供的块与C ++ 11 lambdas不兼容

看起来他们也不相信它目前正在展示足够的实用性。 C标准化显然试图非常保守,只有一个主要的编译器实现该功能,他们可能想等待,看看它如何与C ++ lambdas竞争,以及是否有其他人选择它。在多个编译器提供它之前,它不是真正的“C”功能而不是“Clang”功能。

所有这一切,委员会的投票显然略微倾向于支持该功能(6-5-4是/否/弃权),但还不足以达成必要的共识以包含它。

据我所知,另一个大的,C ++ 11 lambdas,并没有被任何人提议包含在C中;如果你不问你没有得到。

任何关于C语言中lambdas的提议都会添加大量关于变量生命周期和位置以及复制和分配的新规则......等等。对于很多人来说,这可能会开始看起来非常不像C一样,价值观在程序员的背后移动或者在他们的生命周期中突然发生意外变化 - 避免这种情况是人们现在选择用C语言写作的原因的一半。因此,在认真对待之前,还必须有一个实际上符合C的“哲学”的提案。我确信这可以做到,但到目前为止,两个大的提案都是针对具有非常不同的“哲学”的语言而设计的,在这种语言中,这种事情不是一个障碍,而且必然反映了C目前的目的和特征。

答案 2 :(得分:3)

这真的只是我的意见,因为我不知道委员会的想法。

一方面,Lisp自1958年诞生以来一直支持lambda表达.C编程语言诞生于1972年。因此lambda表达式实际上比C语言更长。所以如果你问为什么C11没有不支持lambda表达式,可以询问有关C89的同样问题。

另一方面,lambda表达式总是一个函数式编程事物,逐渐被命令式编程语言所吸收。一些“更高级”的语言(例如Java,在计划的Java 8之前)还不支持它。

最后,C和C ++总是相互学习,所以它可能会在下一个C标准中。目前,您可以查看由Apple添加的非标准扩展程序Blocks。这是来自维基百科的示例代码:

#include <stdio.h>
#include <Block.h>
typedef int (^IntBlock)();

IntBlock MakeCounter(int start, int increment) {
        __block int i = start;

        return Block_copy( ^ {
                int ret = i;
                i += increment;
                return ret;
        });

}

int main(void) {
        IntBlock mycounter = MakeCounter(5, 2);
        printf("First call: %d\n", mycounter());
        printf("Second call: %d\n", mycounter());
        printf("Third call: %d\n", mycounter());

        /* because it was copied, it must also be released */
        Block_release(mycounter);

        return 0;
}
/* Output:
        First call: 5
        Second call: 7
        Third call: 9
*/