Почему 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 нет лямбда-функций, потому что они на самом деле не нужны. Вместо этого вы можете просто использовать статическую функцию и поместить контекст в структуру.

Другие вопросы по тегам