新しい C++11 標準ではラムダ関数がサポートされていますが、これは便利な機能だと思います。C と C++ の標準が互いに異なることは理解していますが、C11 がラムダ関数をサポートしていない理由がわかりません。色々使えそうです。
C11 標準の開発者がこの機能を含めないことを選択した理由はありますか?
2021 年の更新:最小限のセマンティクスを備えた C++ 構文に基づくラムダは、今年 C23 に投票されました。委員会がこの機能が C++ やその他の実装から他に何をもたらすかを正確に特定するにつれて、より詳細な情報が明らかになります。
2016 年の更新:クロージャーを備えた Apple スタイルのラムダは、2016 年のロンドン会議で再びワーキング グループに提示されました。これは、以前の試みの失敗のいくつかに対処しようとする新しい提案文書で、用語と説明を整理して、クロージャーとラムダを「Cライク」にする方法の詳細。
レセプションは慎重に肯定的だったので(7-0-9 はい/いいえ/棄権)、これに似たものがすぐに言語に組み込まれる可能性が非常に高いようです.
簡単に言えば、C にはラムダ関数が含まれていないということです。これは、ISO C ワーキング グループに対して、ラムダ関数を含めるという受け入れ可能な提案をまだ誰も行っていないためです。
ここでワーキンググループによって議論されたいくつかの提案のリストを見ることができます: http://www.open-std.org/jtc1/sc22/wg14/www/documents
そのリストで見つけることができるあらゆる種類のラムダの唯一の提案は、文書N1451の Apple のブロック (Yu Hao の回答に示されているように) です。この提案は、C++ ラムダと比較したN1483 と、これらのドキュメントが提示された会議の議事録であるN1493 および N1542でさらに議論されています。
N1542 で与えられた、N1451 の提案が受け入れられなかったいくつかの理由がありました。
また、現在十分な有用性を示していることに彼らは納得していないようです。C の標準化は非常に保守的であるように思われます。この機能を実装する主要なコンパイラは 1 つだけなので、C++ ラムダとどのように競合するか、他の誰かがそれを採用するかどうかを待ちたいと思うでしょう。複数のコンパイラが提供するまでは、「Clang」機能とは対照的に、実際には「C」機能ではありません。
そうは言っても、委員会の投票は機能を支持することにわずかに傾いていたようですが (6-5-4 はい/いいえ/棄権)、必要なコンセンサスにそれを含めるには十分ではありませんでした。
私が知る限り、もう 1 つの大きなものである C++11 ラムダは、C に含めることを誰からも提案されていません。そして、あなたが尋ねなければ、あなたは得られません。
C でラムダを提案すると、変数の有効期間と場所、コピーと割り当てなどに関する多数の新しいルールが追加されます。多くの人にとって、これは潜在的に C らしくなく、値が移動するように見え始めます。プログラマーの背後に隠れたり、突然予期せぬ寿命の変化を経験したりする - この種のことを避けることが、今日人々が C で書くことを選択する理由の半分です。したがって、真剣に受け止められる前に、C の「哲学」と実際に一致する提案も必要です。私はこれができると確信していますが、これまでの大きな提案は両方とも、この種のことがそれほど障害ではなく、必ずしもC'を反映していない、非常に異なる「哲学」を持つ言語向けに設計されています
委員会が何を考えているか分からないので、これは本当に私の意見です。
一方では、Lisp は 1958 年の誕生以来、ラムダ式をサポートしてきました。C プログラミング言語は 1972 年に誕生しました。つまり、ラムダ式は実際には C よりも長い歴史を持っています。ラムダ式、C89 についても同じ質問をすることができます。
一方、ラムダ式は常に関数型プログラミングのものであり、徐々に命令型プログラミング言語に吸収されます。一部の「上位」言語 (たとえば、予定されている Java 8 より前の Java) は、まだそれをサポートしていません。
最後に、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
*/