Почему C11 не поддерживает лямбда-функции
Новый стандарт C++ 11 поддерживает лямбда-функции, что я считаю полезной функцией. Я понимаю, что стандарты C и C++ отличаются друг от друга, но я не понимаю, почему C11 не поддерживает лямбда-функции. Я думаю, что это может иметь много пользы.
Есть ли причина, по которой разработчики стандарта C11 решили не включать эту функцию?
3 ответа
Это действительно только мое мнение, так как я не знаю, что думает комитет.
С одной стороны, Lisp поддерживает лямбда-выражения с момента его рождения, то есть в 1958 году. Язык программирования C родился в 1972 году. Так что лямбда-выражение на самом деле имеет более длинную историю, чем C. Поэтому, если вы спросите, почему C11 не поддерживает лямбда-выражение, такой же вопрос можно задать о С89.
С другой стороны, лямбда-выражения - это всегда функциональная вещь программирования, которая постепенно внедряется в императивные языки программирования. Некоторые из "более высоких" языков (например, Java, до запланированной Java 8) еще не поддерживают его.
Наконец, C и C++ всегда учатся друг у друга, так что, возможно, это будет в следующем стандарте C. Пока вы можете взглянуть на Blocks, нестандартное расширение, добавленное Apple. Это пример кода из Википедии:
#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
*/
Обновление 2016 года: лямбды в стиле Apple с крышками снова были представлены Рабочей группе на совещании в Лондоне в 2016 году в новом документе с предложением, в котором рассматриваются некоторые недостатки предыдущей попытки, приводятся терминология и пояснения, а также рассматриваются гораздо больше подробностей о том, как крышки и лямбды могут быть сделаны "C-like".
Поскольку прием был осторожно позитивным (7-0-9 Да / Нет / Воздержался), вполне возможно, что что-то похожее на это скоро попадет на язык.
Короткий ответ прост: C не включает лямбда-функции, потому что никто еще не сделал приемлемого предложения рабочей группе ISO C по включению лямбда-функций.
Вы можете взглянуть на список некоторых предложений, обсужденных рабочей группой, здесь: http://www.open-std.org/jtc1/sc22/wg14/www/documents
Единственное предложение о лямбдах любого вида, которое я могу найти в этом списке, - это блоки Apple (как показано в ответе Ю Хао) в документе N1451. Это предложение обсуждается далее в N1483, который сравнивает его с лямбдами C++, и N1493 и N1542, которые являются протоколами собраний, на которых были представлены эти документы.
Было несколько причин, по которым предложение в N1451 не могло быть принято, приведенное в N1542:
- Первоначально комитет с трудом понимал предложение
- он использует неправильные цитаты и терминологию, которая противоречит существующему стандарту C
- это очевидно расплывчато и неполно
- Apple пыталась запатентовать эту функцию (не ясно, является ли это препятствием для стандартизации или нет, но я бы предположил, что так)
- Абсолютно новая функция с совершенно новой семантикой, предложенной в 2010 году, имела абсолютно нулевой шанс быть готовой ко времени к 2011 году и задержала бы выпуск C11.
- Представленные блоки не совместимы с лямбдами C++11
Похоже, что они не были убеждены, что в данный момент он демонстрирует достаточную полезность. Стандартизация C, очевидно, пытается быть очень консервативной, и, имея только один основной компилятор, реализующий эту функцию, вполне вероятно, что они захотят подождать и посмотреть, как она конкурирует с лямбдами C++, и подхватит ли это кто-нибудь еще. На самом деле это не функция "C", в отличие от функции "Clang", пока ее не предложат несколько компиляторов.
Все это говорит о том, что голоса комитета, по-видимому, очень немного склонялись в пользу этой функции (6-5-4 Да / Нет / Воздержался), но не настолько, чтобы необходимый консенсус включил ее.
Насколько я могу судить, другой большой, C++11 lambdas, никто не предлагал для включения в C; и если вы не спросите, вы не получите.
Любое предложение о лямбдах на C добавило бы целый ряд новых правил о времени жизни переменных и их расположении, а также о копировании и размещении и... и т. Д. Для многих людей это потенциально начинает выглядеть очень не по-C, со значениями, перемещаемыми за спиной программиста или внезапные неожиданные изменения в их продолжительности жизни - избегание такого рода вещей - половина причины, по которой люди предпочитают писать на C в наше время. Таким образом, также должно быть предложение, которое фактически соответствует "философии" Си, прежде чем его можно будет воспринимать всерьез. Я уверен, что это можно сделать, но оба больших предложения до сих пор были разработаны для языков с совершенно другой "философией", где подобные вещи не являются препятствием и не обязательно отражают цель и характер С как они сейчас стоят.
C предназначен, чтобы быть маленьким и простым языком. Он намеренно пропускает высокоуровневые функции, когда то же самое можно сделать более простыми средствами. Он направлен на предоставление только базовых функций, которые абсолютно необходимы для переносимого программирования.
C не имеет ссылок, потому что они просто указатели. C не имеет классов, наследования и виртуальных функций, потому что вы можете просто использовать структуры и создавать таблицы самостоятельно, используя указатели на функции. У него нет сборщика мусора, потому что программисты могут сами отслеживать распределение памяти, у него нет шаблонов, потому что они на самом деле просто макросы. Если вам нужны исключения, вы можете использовать longjmp, и вместо пространств имен вы просто добавляете префиксы к именам.
Добавление любого из этих ярлыков высокого уровня может сделать программирование немного более удобным, но это происходит за счет усложнения языка, что нельзя недооценивать. Это скользкий путь, который напрямую ведет к путанице, в которую превратился C++.
В C нет лямбда-функций, потому что они на самом деле не нужны. Вместо этого вы можете просто использовать статическую функцию и поместить контекст в структуру.