Анонімна функція

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

В комп'ютерному програмуванні, анонімною функцією (інші назви функціональний літерал або лямбда вираз, лямбда функція) називається така функція, яка визначена без вказання пов'язаного з нею ідентифікатора. Анонімні функція зазвичай:

  1. передаються у вигляді аргументу у функції вищого порядку, або
  2. використовуються для побудови результату функції вищого порядку, яка має повертати функцію.

Якщо функція використовується в програмі лише раз, або обмежену визначену кількість раз, використання анонімної функції може бути більш синтаксично простішим ніж використання іменованої функції. Анонімні функції широко застосовуються у функціональних мовах програмування і інших мовах програмування з функціями першого класу, де вони виконують ту саму роль для функціонального типу, що і літерали для інших типів даних.

Анонімні функції були представлені в роботі Алонзо Черча як винайдене ним лямбда числення у 1936 (до появи електронно-обчислюваних машин), в якому всі функції анонімні. В деяких мовах програмування, анонімні функції оголошуються з використанням ключового слова lambda, а самі анонімні функції часто називаються лямбда абстракціями або лямбда виразами. Анонімні функції почали використовуватись в мовах програмування починаючи з мови Lisp в 1958 і тепер дедалі більше сучасних мов програмування підтримують анонімні функції.

Анонімні функції є формою вкладених функцій, в тому плані, що вони дозволяють доступ до змінних в зоні видимості функції, в яку вони вкладені (не локальні змінні). Це означає, що анонімні функції повинні визначатися з використанням замикань. На відміну від іменованих вкладених функцій, вони не можуть бути рекурсивними без використання оператору фіксованої точки (також називається анонімною фіксованою точкою або анонімною рекурсією).

Приклади[ред. | ред. код]

Багато мов програмування мають підтримку анонімних функцій, або чогось подібного.

C (не стандартне розширення)[ред. | ред. код]

Анонімні функції не підтримуються стандартним C, але підтримуються деякими його діалектами, такими як gcc і clang.

GCC[ред. | ред. код]

GCC має підтримку анонімних функцій, що є поєднанням вкладених функцій і операторних виразів. Вони мають таку форму:

( { return_type anonymous_functions_name (parameters) { function_body } anonymous_functions_name; } )

Даний приклад працює лише в проектах, що компілюються GCC. Слід відмітити, що завдяки роботі макросу, якщо ваша 'l_body' матиме коми за межами дужок, тоді цей код не скомпілюється оскільки gcc використовує кому як роздільник для наступного аргументу макросу. Аргумент 'l_ret_type' можна прибрати, якщо доступне використання '__typeof__'; в наведеному прикладі використання __typeof__ для масиву поверне 'testtype *', який можна розіменувати для отримання фактичного значення, якщо це необхідно.

#include <stdio.h>

//* це є визначення анонімної функції */
#define lambda(l_ret_type, l_arguments, l_body)       \
  ({                                                  \
   l_ret_type l_anonymous_functions_name l_arguments  \
   l_body                                             \
   &l_anonymous_functions_name;                       \
   })

#define forEachInArray(fe_arrType, fe_arr, fe_fn_body)                                    \
{                                                                                         \
  int i=0;                                                                                \
  for(;i<sizeof(fe_arr)/sizeof(fe_arrType);i++) {  fe_arr[i] = fe_fn_body(&fe_arr[i]); }  \
}

typedef struct __test
{
  int a;
  int b;
} testtype;

void printout(const testtype * array)
{
  int i;
  for ( i = 0; i < 3; ++ i )
    printf("%d %d\n", array[i].a, array[i].b);
  printf("\n");
}

int main(void)
{
  testtype array[] = { {0,1}, {2,3}, {4,5} };

  printout(array);
  /* анонімна функція задається як функція для foreach */
  forEachInArray(testtype, array,
    lambda (testtype, (void *item),
    {
      int temp = (*( testtype *) item).a;
      (*( testtype *) item).a = (*( testtype *) item).b;
      (*( testtype *) item).b = temp;
      return (*( testtype *) item);
    }));
  printout(array);
  return 0;
}