Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В компьютерном программировании , в анонимной функции ( функция буквального , лямбда - абстракции , лямбда - функции или лямбда - выражение ) является функцией определения, которая не связана с идентификатором . Анонимные функции часто являются аргументами, передаваемыми функциям более высокого порядка или используемыми для построения результата функции более высокого порядка, которая должна возвращать функцию. [1] Если функция используется только один раз или ограниченное количество раз, анонимная функция может быть синтаксически легче, чем использование именованной функции. Анонимные функции повсеместны вязыки функционального программирования и другие языки с функциями первого класса , где они выполняют ту же роль для типа функции, что и литералы для других типов данных .

Анонимные функции берут свое начало в работе Алонсо Черча, изобретавшего лямбда-исчисление , в котором все функции анонимны, в 1936 году, до появления электронных компьютеров. [2] В некоторых языках программирования анонимные функции вводятся с использованием ключевого слова лямбда , а анонимные функции часто называют лямбда-выражениями или лямбда-абстракциями. Анонимные функции были особенностью языков программирования со времен Лиспа в 1958 году, и все большее число современных языков программирования поддерживают анонимные функции.

Использует [ редактировать ]

Анонимные функции могут использоваться для хранения функциональных возможностей, которые не нужно называть, и, возможно, для краткосрочного использования. Некоторые известные примеры включают закрытие и каррирование .

Использование анонимных функций - дело стиля. Их использование - никогда не единственный способ решить проблему; Вместо этого каждая анонимная функция может быть определена как именованная функция и вызвана по имени. Некоторые программисты используют анонимные функции для инкапсуляции определенного, не подлежащего повторному использованию кода, не засоряя код множеством мелких однострочных обычных функций.

В некоторых языках программирования анонимные функции обычно реализуются для очень конкретных целей, таких как привязка событий к обратным вызовам или создание экземпляра функции для определенных значений, что может быть более эффективным, более читаемым и менее подверженным ошибкам, чем вызов более универсального именованного функция.

Следующие примеры написаны на Python 3.

Сортировка [ править ]

При попытке выполнить сортировку нестандартным способом может быть проще включить логику сортировки в виде анонимной функции вместо создания именованной функции. Большинство языков предоставляют универсальную функцию сортировки, которая реализует алгоритм сортировки , который сортирует произвольные объекты. Эта функция обычно принимает произвольную функцию, которая определяет, как сравнивать, равны ли два элемента или один больше или меньше другого.

Рассмотрим этот код Python, сортирующий список строк по длине строки:

>>>  a  =  [ 'дом' ,  'машина' ,  'велосипед' ] >>>  a . sort ( key = lambda  x :  len ( x )) >>>  print ( a ) [ 'автомобиль' ,  'велосипед' ,  'дом' ]

Анонимная функция в этом примере - это лямбда-выражение:

лямбда  x :  len ( x )

Анонимная функция принимает один аргумент, xи возвращает длину своего аргумента, которая затем используется sort()методом в качестве критерия для сортировки.

Базовый синтаксис лямбда-функции в Python:

лямбда  arg1 ,  arg2 ,  arg3 ,  ... :  < операция  на  тех  аргументов ,  вернувшихся  в  значение >

Выражение, возвращаемое лямбда-функцией, можно присвоить переменной и использовать в коде в нескольких местах.

>>>  add  =  lambda  a :  a  +  a >>>  print ( add ( 20 )) 40

Другой пример - сортировка элементов в списке по имени их класса (в Python у всего есть класс):

>>>  a  =  [ 10 ,  'число' ,  11.2 ] >>>  a . sort ( ключ = лямбда  x :  x . __class__ . __name__ ) >>>  print ( a ) [ 11.2 ,  10 ,  'number' ]

Обратите внимание, что 11.2имеет имя класса " float", 10имя класса " int" и 'number'имя класса " str". Отсортированный порядок: " float", " int", затем " str".

Закрытия [ править ]

Замыкания - это функции, оцениваемые в среде, содержащей связанные переменные . В следующем примере выполняется привязка переменной «threshold» в анонимной функции, которая сравнивает входные данные с порогом.

def  comp ( threshold ):  вернуть  лямбда  x :  x  <  threshold

Это можно использовать как своего рода генератор функций сравнения:

>>>  func_a  =  comp ( 10 ) >>>  func_b  =  comp ( 20 )>>>  print ( func_a ( 5 ),  func_a ( 8 ),  func_a ( 13 ),  func_a ( 21 )) Истина  Истина  Ложь  Ложь>>>  print ( func_b ( 5 ),  func_b ( 8 ),  func_b ( 13 ),  func_b ( 21 )) Истина  Истина  Истина  Ложь

Было бы непрактично создавать функцию для каждой возможной функции сравнения и было бы слишком неудобно поддерживать порог для дальнейшего использования. Независимо от причины, по которой используется замыкание, анонимная функция - это сущность, которая содержит функции, выполняющие сравнение.

Каррирование [ править ]

Каррирование - это процесс изменения функции, так что вместо того, чтобы принимать несколько входов, он принимает один вход и возвращает функцию, которая принимает второй вход, и так далее. В этом примере функция, выполняющая деление на любое целое число, преобразуется в функцию, выполняющую деление на заданное целое число.

>>>  def  div ( x ,  y ): ...  вернуть  x  /  y>>>  def  divisor ( d ): ...  вернуть  лямбда  x :  div ( x ,  d )>>>  половина  =  делитель ( 2 ) >>>  третья  =  делитель ( 3 )>>>  печать ( половина ( 32 ),  третья ( 32 )) 16.0  10.666666666666666>>>  печать ( половина ( 40 ),  третья ( 40 )) 20,0  13,333333333333334

Хотя использование анонимных функций, возможно, не является обычным для каррирования, его все же можно использовать. В приведенном выше примере делитель функции генерирует функции с указанным делителем. Функции half и third картируют функцию деления с фиксированным делителем.

Функция делителя также формирует замыкание, связывая переменную d.

Функции высшего порядка [ править ]

Функция высшего порядка - это функция, которая принимает функцию в качестве аргумента. Это обычно используется для настройки поведения универсально определенной функции, часто конструкции цикла или схемы рекурсии. Анонимные функции - удобный способ указать такие аргументы функции. Следующие примеры относятся к Python 3.

Карта [ править ]

Функция карты выполняет вызов функции для каждого элемента списка. В следующем примере каждый элемент массива возводится в квадрат с помощью анонимной функции.

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  print ( list ( map ( lambda  x :  x * x ,  a ))) [ 1 ,  4 ,  9 ,  16 ,  25 ,  36 ]

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

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  print ([ x * x  вместо  x  в  a ]) [ 1 ,  4 ,  9 ,  16 ,  25 ,  36 ]

Фильтр [ править ]

Функция фильтра возвращает все элементы из списка, которые оценивают True при передаче в определенную функцию.

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  print ( list ( filter ( lambda  x :  x  %  2  ==  0 ,  a ))) [ 2 ,  4 ,  6 ]

Анонимная функция проверяет, четен ли переданный ей аргумент. То же, что и с формой карты ниже, считается более подходящим:

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  print ([ x  вместо  x  в  a,  если  x  %  2  ==  0 ]) [ 2 ,  4 ,  6 ]

Сложить [ править ]

Функция сворачивания проходит по всем элементам в структуре (для списков обычно слева направо, "левый сверток", называемый reduceв Python), накапливая значение по мере его прохождения. Это можно использовать для объединения всех элементов структуры в одно значение, например:

>>>  из  функций  импорта  уменьшить >>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ] >>>  print ( reduce ( lambda  x , y :  x * y ,  a )) 120

Это выполняет

Анонимная функция здесь - это умножение двух аргументов.

Результатом сворачивания не обязательно должно быть одно значение. Вместо этого с помощью свертки можно создать и карту, и фильтр. В map накопленное значение представляет собой новый список, содержащий результаты применения функции к каждому элементу исходного списка. В фильтре накапливаемое значение представляет собой новый список, содержащий только те элементы, которые соответствуют заданному условию.

Список языков [ править ]

Ниже приведен список языков программирования, которые полностью или частично поддерживают безымянные анонимные функции в качестве некоторого варианта или совсем не поддерживают.

В этой таблице показаны некоторые общие тенденции. Во-первых, языки, которые не поддерживают анонимные функции ( C , Pascal , Object Pascal ), являются языками со статической типизацией. Однако языки со статической типизацией могут поддерживать анонимные функции. Например, языки ML имеют статическую типизацию и в основном включают анонимные функции, а Delphi , диалект Object Pascal , был расширен для поддержки анонимных функций, как и C ++ (по стандарту C ++ 11 ). Во-вторых, языки, которые рассматривают функции как функции первого класса ( Dylan , Haskell ,JavaScript , Lisp , ML , Perl , Python , Ruby , Scheme ) обычно имеют поддержку анонимных функций, поэтому функции можно определять и передавать так же легко, как и другие типы данных.

Примеры [ править ]

Многие языки поддерживают анонимные функции или что-то подобное.

APL [ править ]

Только некоторые диалекты поддерживают анонимные функции, такие как dfns , в неявном стиле или их комбинацию.

 f { × }  ⍝ Как dfn  f  1  2  3 1  4  9  g ⊢ × ⊢  ⍝ Как неявная 3-цепочка (вилка)  g  1  2  3 1  4  9  h ×  ⍝ Как производная неявная функция  ч  1  2  3 1  4  9

C (нестандартное расширение) [ править ]

Анонимная функция не поддерживается стандартным языком программирования C, но поддерживается некоторыми диалектами C, такими как GCC и Clang .

GCC [ править ]

Коллекция компиляторов GNU (GCC) поддерживает анонимные функции, смешанные с вложенными функциями и выражениями операторов. Он имеет вид:

(  {  return_type  anonymous_functions_name  ( параметры )  {  function_body  }  anonymous_functions_name ;  }  )

Следующий пример работает только с GCC. Из-за того, как макросы раскрываются, в l_bodyскобках не должно быть запятых; GCC рассматривает запятую как разделитель между аргументами макроса. Аргумент l_ret_typeможно удалить, если __typeof__он доступен; в приведенном ниже примере при использовании __typeof__массива on будет возвращен 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 (; я <sizeof (fe_arr) / sizeof (fe_arrType); i ++) {fe_arr [i] = fe_fn_body (& fe_arr [i]); } \ }typedef  struct  __test {  int  a ;  int  b ; }  testtype ;недействительным  распечатка ( Const  TestType  *  массив ) {  INT  я ;  for  (  i  =  0 ;  i  <  3 ;  ++  i  )  printf ( "% d% d \ n " ,  array [ i ]. a ,  array [ i ]. b );  printf ( " \ п " ); }int  main ( void ) {  массив тестов  [] = { { 0 , 1 }, { 2 , 3 }, { 4 , 5 } };       распечатка ( массив );  / * анонимная функция задается как функция для foreach * /  forEachInArray ( testtype ,  array ,  lambda  ( testtype ,  ( void  * item ),  {  int  temp  =  ( * (  testtype  * )  item ). a ;  ( * (  testtype  *) )  элемент ). a  =  ( * (  testtype  * ) пункт ). б ;  ( * (  testtype  * )  элемент ). b  =  темп ;  return  ( * (  testtype  * )  item );  }));  распечатка ( массив );  возврат  0 ; }

Clang (C, C ++, Objective-C, Objective-C ++) [ править ]

Clang поддерживает анонимные функции, называемые блоками , которые имеют вид:

^ return_type  (  параметры  )  {  function_body  }

Тип блоков выше return_type (^)(parameters).

Используя вышеупомянутое расширение блоков и Grand Central Dispatch (libdispatch), код может выглядеть проще:

#include  <stdio.h>#include  <dispatch / dispatch.h>int  main ( void )  {  void  ( ^ count_loop ) ()  =  ^ {  для  ( int  я  =  0 ;  я  <  100 ;  я ++ )  printf ( "% d \ n " ,  я );  printf ( "ах ах ах \ п " );  };/ * Передача в качестве параметра другой функции * /  dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT ,  0 ),  count_loop );/ * Вызов напрямую * /  count_loop (); возврат  0 ; }

Код с блоками должен быть скомпилирован -fblocksи связан с-lBlocksRuntime

C ++ (начиная с C ++ 11) [ править ]

C ++ 11 поддерживает анонимные функции, называемые лямбда-выражениями , которые имеют форму:

[ захват ] ( параметры )  ->  return_type  {  function_body  }

Это пример лямбда-выражения:

[] ( int  x ,  int  y )  ->  int  {  вернуть  x  +  y ;  }

C ++ 11 также поддерживает замыкания . Замыкания определяются между квадратными скобками [и ]в объявлении лямбда-выражения. Механизм позволяет захватывать эти переменные по значению или по ссылке. Следующая таблица демонстрирует это:

[]  // переменные не определены. Попытка использовать какие-либо внешние переменные в лямбде является ошибкой. [ x ,  & y ]  // x фиксируется по значению, y фиксируется по ссылке [ & ]  // любая внешняя переменная неявно фиксируется по ссылке, если используется [ = ]  // любая внешняя переменная неявно фиксируется по значению, если используется [ & ,  x ]  // x явно захватывается значением. Другие переменные будут захвачены по ссылке [ = ,  & z ]  // z явно захвачен по ссылке. Другие переменные будут захвачены по значению

Переменные, фиксируемые по значению, по умолчанию являются постоянными. Добавление mutableпосле списка параметров делает их непостоянными.

Следующие два примера демонстрируют использование лямбда-выражения:

std :: vector < int >  some_list {  1 ,  2 ,  3 ,  4 ,  5  }; int  total  =  0 ; std :: for_each ( начало ( некоторый_список ),  конец ( некоторый_список ),  [ & всего ] ( int  x )  { total  + =  x ;  });

Это вычисляет сумму всех элементов в списке. Переменная totalсохраняется как часть закрытия лямбда-функции. Поскольку это ссылка на переменную стека total, она может изменять ее значение.

std :: vector < int >  some_list {  1 ,  2 ,  3 ,  4 ,  5  }; int  total  =  0 ; int  value  =  5 ; std :: for_each ( begin ( some_list ),  end ( some_list ),  [ & total ,  value ,  this ] ( int  x )  {  total  + =  x *  значение  *  это -> some_func ();  });

Это приведет totalк тому, что он будет сохранен как ссылка, но valueбудет сохранен как копия.

Захват thisособенный. Его можно получить только по значению, а не по ссылке. thisможет быть захвачен, только если ближайшая включающая функция является нестатической функцией-членом. Лямбда будет иметь тот же доступ, что и член, который ее создал, с точки зрения защищенных / закрытых членов.

Если thisзахватывается явно или неявно, то также проверяется область действия включенных членов класса. Для доступа к членам thisне требуется явного использования this->синтаксиса.

Конкретная внутренняя реализация может варьироваться, но ожидается, что лямбда-функция, которая захватывает все по ссылке, будет хранить фактический указатель стека функции, в которой она создана, а не отдельные ссылки на переменные стека. Однако, поскольку большинство лямбда-функций являются небольшими и локальными по объему, они, вероятно, являются кандидатами для встраивания и, следовательно, не нуждаются в дополнительном хранилище для ссылок.

Если закрывающий объект, содержащий ссылки на локальные переменные, вызывается после самого внутреннего блока области его создания, поведение не определено .

Лямбда-функции - это функциональные объекты зависимого от реализации типа; имя этого типа доступно только компилятору. Если пользователь желает использовать лямбда-функцию в качестве параметра, тип параметра должен быть типом шаблона, или он должен создать std::functionили аналогичный объект для захвата значения лямбда. Использование autoключевого слова может помочь сохранить лямбда-функцию,

auto  my_lambda_func  =  [ & ] ( int  x )  {  /*...*/  }; auto  my_onheap_lambda_func  =  новое  авто ([ = ] ( int  x )  {  /*...*/  });

Вот пример хранения анонимных функций в переменных, векторах и массивах; и передав их как именованные параметры:

#include  <функциональный>#include  <iostream>#include  <вектор>двойной  eval ( std :: function < double ( double ) >  f ,  double  x  =  2.0 )  {  return  f ( x ); }int  main ()  {  std :: function < double ( double ) >  f0  =  [] ( двойной  x )  {  return  1 ;  };  авто  f1  =  [] ( двойной  х )  {  вернуть  х ;  };  decltype ( f0 )  fa [ 3 ]  =  { f0 ,  f1 ,  [] ( double  x )  { вернуть  х  *  х ;  }};  std :: vector < decltype ( f0 ) >  fv  =  { f0 ,  f1 };  fv . push_back ([] ( двойной  x )  {  return  x  *  x ;  });  for  ( size_t  i  =  0 ;  i  <  fv . size ();  i ++ )  {  std :: cout <<  fv [ i ] ( 2.0 )  <<  std :: endl ;  }  for  ( size_t  i  =  0 ;  i  <  3 ;  i ++ )  {  std :: cout  <<  fa [ i ] ( 2.0 )  <<  std :: endl ;  }  for  ( auto &  f  :  fv )  {  std :: cout  << f ( 2.0 )  <<  std :: endl ;  }  for  ( auto &  f  :  fa )  {  std :: cout  <<  f ( 2.0 )  <<  std :: endl ;  }  std :: cout  <<  eval ( f0 )  <<  std :: endl ;  std :: cout  <<  eval ( f1 )  <<  std:: endl ;  std :: cout  <<  eval ([] ( double  x )  {  return  x  *  x ;  })  <<  std :: endl ; }

Лямбда-выражение с пустой спецификацией захвата ( []) может быть неявно преобразовано в указатель на функцию того же типа, с которым была объявлена ​​лямбда. Итак, это законно:

auto  a_lambda_func  =  [] ( int  x )  {  /*...*/  }; void  ( *  func_ptr ) ( int )  =  a_lambda_func ; func_ptr ( 4 );  // вызывает лямбду.

Библиотека Boost также предоставляет собственный синтаксис для лямбда-функций, используя следующий синтаксис: [32]

for_each ( a . begin (),  a . end (),  std :: cout  <<  _1  <<  '' );

C # [ править ]

В C # поддержка анонимных функций стала глубже благодаря различным версиям компилятора языка. Язык v3.0, выпущенный в ноябре 2007 года вместе с .NET Framework v3.5, полностью поддерживает анонимные функции. C # называет их лямбда-выражениями , следуя исходной версии анонимных функций, лямбда-исчислению . [33]

// первое int - это тип x // второе int - это возвращаемый тип // <см. href = " http://msdn.microsoft.com/en-us/library/bb549151.aspx " />Func<int,int> foo = x => x * x;Console.WriteLine(foo(7));

Хотя функция является анонимной, ее нельзя присвоить неявно типизированной переменной, поскольку лямбда-синтаксис может использоваться для обозначения анонимной функции или дерева выражений, и компилятор не может автоматически принять решение о выборе. Например, это не работает:

// НЕ компилируется! var  foo  =  ( int  x )  =>  х  *  х ;

Однако лямбда-выражение может принимать участие в выводе типа и использоваться в качестве аргумента метода , например, для использования анонимных функций с возможностью Map, доступной с System.Collections.Generic.ListConvertAll()методе):

// Инициализируем список: var  values  =  new  List < int > ()  {  7 ,  13 ,  4 ,  9 ,  3  }; // Сопоставляем анонимную функцию по всем элементам в списке, возвращаем новый список var  foo  =  values . ConvertAll ( д  =>  д  *  д )  ;  // результат переменной foo имеет тип System.Collections.Generic.List <Int32>

Предыдущие версии C # имели более ограниченную поддержку анонимных функций. C # v1.0, представленный в феврале 2002 г. вместе с .NET Framework v1.0, обеспечивал частичную поддержку анонимных функций посредством использования делегатов . Эта конструкция чем-то похожа на делегаты PHP. В C # 1.0 делегаты подобны указателям на функции, которые ссылаются на явно названный метод внутри класса. (Но, в отличие от PHP, имя не требуется во время использования делегата.) C # v2.0, выпущенный в ноябре 2005 года с .NET Framework v2.0, представил концепцию анонимных методов как способ написания безымянных встроенных операторов. блоки, которые могут быть выполнены при вызове делегата. C # 3.0 продолжает поддерживать эти конструкции, но также поддерживает конструкцию лямбда-выражения.

Этот пример компилируется в C # 3.0 и демонстрирует три формы:

 открытый  класс  TestDriver  {  делегат  int  SquareDelegate ( int  d );  статический  int  Square ( int  d )  {  return  d  *  d ;  }  static  void  Main ( string []  args )  {  // C # 1.0: необходим исходный синтаксис делегата  // инициализация именованным методом.  SquareDelegate  A  =  новый  SquareDelegate ( Квадрат );  Система . Консоль . WriteLine ( A ( 3 ));  // C # 2.0: делегат может быть инициализирован  // встроенным кодом, который называется «анонимным методом». Этот  // метод принимает в качестве входного параметра int.  SquareDelegate  B  =  делегат ( int  d )  {  return  d  *  d ;  };  Система . Консоль . WriteLine ( B ( 5 ));  // C # 3.0. Делегат может быть инициализирован  // лямбда-выражением. Лямбда принимает int и возвращает int.  // Тип x определяется компилятором.  SquareDelegate  C  =  х  =>  х  *  х ;  Система . Консоль . WriteLine ( C ( 7 ));  // C # 3.0. Делегат, который принимает один ввод и  // возвращает один вывод, также может быть неявно объявлен с типом Func <>.  Система . Func < int , int >  D  =  x  =>  x  *  x ;  Система . Консоль . WriteLine ( D ( 9 ));  }  }

В случае версии C # 2.0 компилятор C # берет блок кода анонимной функции и создает статическую частную функцию. Конечно, внутренне функция получает сгенерированное имя; это сгенерированное имя основано на имени метода, в котором объявлен делегат. Но имя не отображается в коде приложения, кроме как с помощью отражения .

В случае версии C # 3.0 применяется тот же механизм.

Язык разметки ColdFusion (CFML) [ править ]

fn  =  function () {  // операторы };

CFML поддерживает любые операторы в определении функции, а не просто выражения.

CFML поддерживает рекурсивные анонимные функции:

factorial  =  function ( n ) {  return  n  >  1  ?  n  *  факториал ( n - 1 )  :  1 ; };

Анонимные функции CFML реализуют закрытие.

D [ править ]

D использует встроенные делегаты для реализации анонимных функций. Полный синтаксис встроенного делегата:

return_type  делегат ( аргументы ) { / * тело * / }

Если это однозначно, тип возвращаемого значения и ключевое слово делегата можно не указывать.

( x ) { return  x * x ;} delegate  ( x ) { return  x * x ;}  // если требуется больше подробностей ( int  x ) { return  x * x ;}  // если тип параметра не может быть определен делегатом  ( int  x ) { return  x * x ;}  // то же самое делегировать  double ( int  x ) { return  x * x ;} // если тип возвращаемого значения необходимо принудительно установить вручную

Начиная с версии 2.0, D выделяет замыкания в куче, если компилятор не докажет, что в этом нет необходимости; scopeключевое слово можно использовать для принудительного выделения стека. Начиная с версии 2.058, можно использовать сокращенную запись:

х  =>  х * х ; ( int  х )  =>  х * х ; ( х , у )  =>  х * у ; ( int  x ,  int  y )  =>  х * у ;

Анонимная функция может быть назначена переменной и использована следующим образом:

авто  sqr  =  ( двойной  х ) { вернуть  х * х ;}; двойной  y  =  sqr ( 4 );

Дротик [ править ]

Dart поддерживает анонимные функции. [8]

var  sqr  =  ( x )  =>  х  *  х ; печать ( sqr ( 5 ));

или же

печать ((( х )  =>  х  *  х ) ( 5 ));

Delphi [ править ]

В версии 2009 Delphi представила анонимные функции.

 демонстрация программы ;тип  TSimpleProcedure  =  ссылка  на  процедуру ;  TSimpleFunction  =  ссылка  на  функцию ( const  x :  string ) :  Integer ;var  x1 :  TSimpleProcedure ;  y1 :  TSimpleFunction ;begin  x1  : =  процедура  begin  Writeln ( 'Hello World' ) ;  конец ;  x1 ;  // вызываем только что определенный анонимный метод y1  : =  function ( const  x :  string ) :  Integer  begin  Результат  : =  Длина ( x ) ;  конец ;  Writeln ( y1 ( 'бар' )) ;  конец .

PascalABC.NET [ править ]

PascalABC.NET поддерживает анонимные функции с использованием лямбда-синтаксиса

начало  var  n  : =  10000000 ;  var  pp  : =  Диапазон ( 1 , n )  . Выберите ( x -> Rec ( Random () , Random ()))  . Где ( p -> sqr ( p . Item1 ) + sqr ( p . Item2 ) < 1 )  . Счет / п * 4 ;  Распечатать( пп ) ; конец .

Эликсир [ править ]

Эликсир использует закрытие fn для анонимных функций. [10]

sum  =  fn ( a ,  b )  ->  a  +  b  конечная сумма . ( 4 ,  3 ) # => 7квадрат  =  fn ( x )  ->  x  *  x  end Enum . карта  [ 1 ,  2 ,  3 ,  4 ],  квадрат # => [1, 4, 9, 16]

Эрланг [ править ]

Erlang использует синтаксис анонимных функций, аналогичный синтаксису именованных функций. [11]

% Анонимная функция, привязанная к переменной Square Square  =  fun ( X )  ->  X  *  X  end .% Названная функция с одной и той же функциональности квадрата ( X )  ->  Х  *  Х .

Перейти [ править ]

Go поддерживает анонимные функции. [15]

foo  : =  func ( x  int )  int  { return  x  *  x } fmt . Println ( foo ( 10 ))

Haskell [ править ]

Haskell использует сжатый синтаксис для анонимных функций (лямбда-выражений).

 \ х  ->  х  *  х

Лямбда-выражения полностью интегрированы с механизмом вывода типов и поддерживают весь синтаксис и возможности «обычных» функций (за исключением использования нескольких определений для сопоставления с образцом, поскольку список аргументов указывается только один раз).

 map  ( \ x  ->  x  *  x )  [ 1 .. 5 ]  - возвращает [1, 4, 9, 16, 25]

Все следующие варианты эквивалентны:

 е  х  у  =  х  +  у  е  х  =  \ у  ->  х  +  у  е  =  \ х  у  ->  х  +  у

Haxe [ править ]

В Haxe анонимные функции называются лямбда и используют синтаксис function(argument-list) expression;.

var  f  =  function ( x )  return  x * x ; f ( 8 );  // 64( функция ( x , y )  return  x + y ) ( 5 , 6 );  // 11

Java [ править ]

Java поддерживает анонимные функции, называемые лямбда-выражениями , начиная с JDK 8 . [34]

Лямбда-выражение состоит из разделенного запятыми списка формальных параметров, заключенных в круглые скобки, маркера стрелки (->) и тела. Типы данных параметров всегда можно опустить, как и круглые скобки, если параметр только один. Тело может состоять из одного оператора или блока операторов. [35]

// без параметра ()  ->  System . из . println ( "Привет, мир." )// с одним параметром (этот пример - функция идентификации). а  ->  а// с одним выражением ( a ,  b )  ->  a  +  b// с явной информацией о типе ( длинный  идентификатор ,  имя строки  ) -> "id:" + id + ", name:" + name        // с блоком кода ( a ,  b )  ->  {  return  a  +  b ;  }// с несколькими операторами в теле лямбда. Нужен блок кода. // Этот пример также включает два вложенных лямбда-выражения (первое также является замыканием). ( id ,  defaultPrice )  ->  {  Необязательно < Product >  product  =  productList . поток (). фильтр ( p  ->  p . getId ()  ==  id ). findFirst ();  вернуть  товар . карта ( p  ->  p . getPrice()). orElse ( defaultPrice ); }

Лямбда-выражения преобразуются в «функциональные интерфейсы» (определенные как интерфейсы, содержащие только один абстрактный метод в дополнение к одному или нескольким стандартным или статическим методам) [35], как в следующем примере:

общедоступный  класс  Calculator  {  interface  IntegerMath  {  int  operation ( int  a ,  int  b ); по умолчанию  IntegerMath  swap ()  {  return  ( a ,  b )  ->  operation ( b ,  a );  }  } private  static  int  apply ( int  a ,  int  b ,  IntegerMath  op )  {  return  op . операция ( а ,  б );  } public  static  void  main ( String ...  args )  {  дополнение IntegerMath  = ( a , b ) -> a + b ; IntegerMath вычитание = ( a , b ) -> a - b ; Система . из . println ( "40 + 2 =" + применить ( 40 , 2 , сложение )); Система                      . из . println ( "  20-10 =" +  применить ( 20 ,  10 ,  вычитание ));  Система . из . println ( "10-20 ="  +  применить ( 20 ,  10 ,  вычитание . swap ()));  } }

В этом примере IntegerMathобъявляется функциональный интерфейс с именем . Реализующие лямбда-выражения IntegerMathпередаются apply()методу для выполнения. Методы по умолчанию, такие как методы swapопределения функций.

В Java 8 появился еще один механизм, названный ссылкой на метод (оператор ::), для создания лямбда-выражения для существующего метода. Ссылка на метод не указывает количество или типы аргументов, потому что они извлекаются из абстрактного метода функционального интерфейса.

IntBinaryOperator  сумма  =  Целое число :: сумма ;

В приведенном выше примере функциональный интерфейс IntBinaryOperatorобъявляет абстрактный метод int applyAsInt(int, int), поэтому компилятор ищет метод int sum(int, int)в классе java.lang.Integer.

Ограничения Java [ править ]

Лямбды Java 8 имеют следующие ограничения:

  • Лямбда-выражения могут генерировать проверенные исключения, но такие лямбда-выражения не будут работать с интерфейсами, используемыми API коллекции.
  • Переменные, которые находятся в области видимости, в которой объявлена ​​лямбда, могут быть доступны внутри лямбда только в том случае, если они фактически являются окончательными, т. Е. Если переменная не изменяется внутри или за пределами области лямбда.

JavaScript [ править ]

JavaScript / ECMAScript поддерживает анонимные функции.

предупреждение (( функция ( х ) {  возврат  х  *  х ; }) ( 10 ));

ES6 поддерживает синтаксис «стрелочной функции», где символ => отделяет список параметров анонимной функции от тела:

предупреждение (( x  =>  x  *  x ) ( 10 ));

Эта конструкция часто используется в букмарклетах . Например, чтобы изменить заголовок текущего документа (видимого в строке заголовка его окна ) на его URL-адрес , может показаться, что следующий букмарклет работает.

javascript : документ . title = location . href ;

Однако, поскольку оператор присваивания возвращает значение (сам URL), многие браузеры фактически создают новую страницу для отображения этого значения.

Вместо этого можно использовать анонимную функцию, которая не возвращает значение:

JavaScript : ( функция () { документ . название = местоположение . href ;}) ();

Оператор функции в первой (внешней) паре круглых скобок объявляет анонимную функцию, которая затем выполняется при использовании с последней парой скобок. Это почти эквивалентно следующему, который заполняет среду fнепохожей на анонимную функцию.

javascript : var  f  =  function () { document . title = location . href ;};  f ();

Используйте void (), чтобы избежать появления новых страниц для произвольных анонимных функций:

javascript : void ( function () { return  document . title = location . href ;} ());

или просто:

javascript : void ( документ . название = местоположение . href );

JavaScript имеет синтаксические тонкости для семантики определения, вызова и оценки анонимных функций. Эти подсознательные нюансы являются прямым следствием оценки выражений в скобках. Следующие конструкции, которые называются выражением функции с немедленным вызовом, иллюстрируют это:

( функция () {  ...  } ())

и

( функция () {  ...  }) ()

Представляя " function(){ ... }" с помощью f, формы конструкций представляют собой скобки внутри скобок (f())и скобки, применяемые к скобкам (f)().

Обратите внимание на общую синтаксическую неоднозначность выражения в круглых скобках, заключенных в скобки аргументов функции и круглых скобок вокруг формальных параметров в определении функции. В частности, JavaScript определяет оператор ,(запятую) в контексте выражения в скобках. Совпадение синтаксических форм выражения и аргументов функции не является простым совпадением (без учета синтаксиса формальных параметров функции)! Если fэто не определено в приведенных выше конструкциях, они становятся (())и ()(). Первый не дает синтаксических указаний на какую-либо резидентную функцию, но второй ДОЛЖЕН оценивать первую скобку как функцию, которая является допустимым JavaScript. (Помимо: например, ()'s может быть ([], {}, 42, "abc", function () {}), пока выражение оценивается как функция.)

Кроме того, функция является экземпляром объекта (аналогично объектам являются экземплярами функции), а скобки обозначения литерала объекта {}для кода в фигурных скобках используются при определении функции таким образом (в отличие от использования new Function(...)). В очень широком нестрогом смысле (тем более , что глобальные привязки скомпрометированы), произвольной последовательности закрепленных утверждений JavaScript, {stuff}можно рассматривать как фиксированную точку из

( функция () {(  функция () {(  ...  {(  функция () { материал } ()  )}  ...  )} ()  )} ()  )

Вернее, но с оговорками,

(  function () { stuff } ()  )  ~ =  A_Fixed_Point_of (  function () {  return  function () {  return  ...  {  return  function () { stuff } ()  }  ...  } ()  } ()  ))

Обратите внимание на значение анонимной функции в следующих фрагментах JavaScript:

  • function(){ ... }()без окружающих ()вообще не законно
  • (f=function(){ ... })не «забывает» fглобально в отличие от(function f(){ ... })
Производительность метрики для анализа пространства и времени сложности вызовов функций, стек вызовов и т.д. в JavaScript интерпретатора двигателя легко реализовать с помощью этих последних анонимных функций конструктов. Из значения результатов можно вывести некоторые детали рекурсивной и итеративной реализации движка, особенно хвостовую рекурсию .

Юлия [ править ]

В Julia анонимные функции определяются с использованием синтаксиса (arguments)->(expression),

Юлия>  е  =  х  ->  х * х ;  f ( 8 ) 64 Джулия>  (( x , y ) -> x + y ) ( 5 , 6 ) 11

Лисп [ править ]

Lisp и Scheme поддерживают анонимные функции, используя конструкцию «лямбда», которая является ссылкой на лямбда-исчисление . Clojure поддерживает анонимные функции со специальной формой "fn" и синтаксисом чтения # ().

( лямбда  ( аргумент )  ( *  аргумент  аргумент ))

Common Lisp [ править ]

В Common Lisp есть концепция лямбда-выражений. Лямбда-выражение записывается в виде списка с символом «лямбда» в качестве первого элемента. Затем список содержит список аргументов, документацию или объявления и тело функции. Лямбда-выражения можно использовать внутри лямбда-форм и со специальным оператором function.

( Функция  ( лямбда  ( Arg )  ( делать-то ,  Arg )))

«функция» может быть сокращена как # '. Также существует макрос лямбда , который расширяется в форму функции:

; с использованием четкой кавычки # ' ( lambda  ( arg )  ( do-something  arg )) ; используя лямбда-макрос: ( lambda  ( arg )  ( do-something  arg ))

Типичное использование анонимных функций в Common Lisp - передача их функциям более высокого порядка, таким как mapcar , который применяет функцию к каждому элементу списка и возвращает список результатов.

( mapcar  # ' ( лямбда  ( x )  ( *  x  x ))  ' ( 1  2  3  4 )) ; -> (1 4 9 16)

Форма лямбда в Common Lisp позволяет лямбда - выражения , чтобы записать в вызове функции:

(( лямбда  ( x  y )  ( +  ( sqrt  x )  ( sqrt  y )))  10,0  12,0 )

Анонимным функциям в Common Lisp позже можно будет дать глобальные имена:

( setf  ( символ-функция  'sqr )  ( лямбда  ( x )  ( *  x  x ))) ; что позволяет нам называть его, используя имя SQR: ( sqr  10.0 )

Схема [ править ]

Именованные функции схемы - это просто синтаксический сахар для анонимных функций, привязанных к именам:

( define ( somename  arg )  ( do-something  arg ))

расширяется (и эквивалентно) до

( определить какое-то имя  ( лямбда ( аргумент )  ( сделать-что-то  аргумент )))

Clojure [ править ]

Clojure поддерживает анонимные функции через специальную форму "fn":

( fn  [x]  ( +  x  3 ))

Также существует синтаксис читателя для определения лямбда:

#  ( +  %%  2% 3 )  ; Определяет анонимную функцию, которая принимает три аргумента и суммирует их.

Как и Scheme, «именованные функции» Clojure - это просто синтаксический сахар для лямбда-выражений, привязанных к именам:

( defn  func  [arg]  ( +  3  arg ))

расширяется до:

( def  func  ( fn  [arg]  ( +  3  arg )))

Lua [ править ]

В Lua (как и в Scheme) все функции анонимны. Имя функция в Lua просто переменная , содержащая ссылку на объект функции. [36]

Таким образом, в Lua

функция  foo ( x )  return  2 * x  end

просто синтаксический сахар для

foo  =  function ( x )  return  2 * x  end

Пример использования анонимных функций для сортировки в обратном порядке:

table.sort ( сеть ,  функция ( a , b )  возвращает  a . имя  >  b . конец имени )

Wolfram Language, Mathematica [ править ]

Wolfram Язык является языком программирования Mathematica . Анонимные функции важны при программировании последних. Их можно создать несколькими способами. Ниже приведены несколько анонимных функций, увеличивающих число. Первый - самый распространенный. #1относится к первому аргументу и &отмечает конец анонимной функции.

 # 1 + 1 & Функция [ x , x + 1 ] x \ [ Функция ] x + 1  

Так, например:

 f : = # 1 ^ 2 & ; f [ 8 ]  64 # 1 + # 2 и [ 5 , 6 ] 11

Кроме того, в Mathematica есть дополнительная конструкция для создания рекурсивных анонимных функций. Символ «# 0» относится ко всей функции. Следующая функция вычисляет факториал своего ввода:

 Если [ # 1 == 1 , 1 , # 1 * # 0 [ # 1 -1 ]] &      

Например, 6 факториал будет:

 Если [ # 1 == 1 , 1 , # 1 * # 0 [ # 1 -1 ]] & [ 6 ]      720

MATLAB, Octave [ править ]

Анонимные функции в MATLAB или Octave определяются с использованием синтаксиса @(argument-list)expression. Любые переменные, которые не найдены в списке аргументов, наследуются из окружающей области.

 > f = @ ( x ) x * x ; ж ( 8 )     ans = 64   > (@ ( x , y ) x + y ) ( 5 , 6 ) % Работает только в Octave   ans = 11  

Максима [ править ]

В Maxima анонимные функции определяются с использованием синтаксиса lambda(argument-list,expression),

е: лямбда ([х], х * х); f (8);64лямбда ([х, у], х + у) (5,6);11

ML [ править ]

Различные диалекты ML поддерживают анонимные функции.

OCaml [ править ]

Анонимные функции в OCaml - это функции без объявленного имени. Вот пример анонимной функции, которая умножает свой ввод на два:

весело  х  ->  х * 2

В этом примере fun - это ключевое слово, указывающее, что функция является анонимной. Мы передаем аргумент x и ->, чтобы отделить аргумент от тела. [37]

F # [ править ]

F # поддерживает анонимные функции [12] следующим образом:

( веселье  x  ->  x  *  x )  20  // 400

Стандартный ML [ править ]

Стандартный ML поддерживает следующие анонимные функции:

fn arg => arg * arg

Оболочка нового поколения [ править ]

Оболочка следующего поколения имеет несколько синтаксисов для анонимных функций из-за их распространенности в языке и различных вариантов использования.

Синтаксисы:

е  =  Х * Х ;  f ( 8 )  # Результат: 64 f  =  {  A * B + C  };  f ( 2 , 3 , 4 )  # Результат: 10 f  =  F ( x : Int ,  y : Int )  x * y + 2 ;  f ( 3 ,  4 )  # Результат: 14f  =  "$ {X} все о $ {Y}" f ( "программирование" ,  "семантика" )  # Результат: "программирование - это семантика"

Примеры использования анонимных функций:

[ 0 , 1 , 2 ]. map ( X * 2 )  # Результат: [0,2,4]data  =  { "a" :  "xxx" ,  "b" :  "yyy" } данные . map ( "$ {X} is $ {Y}" )  # Результат: ["a is xxx", "b is yyy"]

Ним [ править ]

Nim поддерживает многострочные анонимные функции с несколькими выражениями. [38]

var  anon  =  proc  ( var1 ,  var2 :  int ):  int  =  var1  +  var2 assert  anon ( 1 ,  2 )  ==  3

Многострочный пример:

var  anon  =  func  ( x :  int ):  bool  =  if  x  >  0 :  result  =  true  else :  result  =  falseотстаивать  анон ( 9 )

Анонимные функции могут передаваться как входные параметры других функций:

var  cities  =  @ [ "Франкфурт" ,  "Токио" ,  "Нью-Йорк" ]города . sort (  proc  ( x ,  y :  строка ):  int  =  cmp ( x . len ,  y . len ) )

Анонимная функция - это, по сути, функция без имени.

Perl [ править ]

Perl 5 [ править ]

Perl 5 поддерживает анонимные функции [27] следующим образом:

( sub  {  print  "Мне позвонили \ n"  }) -> ();  # 1. полностью анонимный, называется как созданныймой  $ squarer  =  sub  {  мой  $ x  =  shift ;  $ x  *  $ x  };  # 2. присваивается переменнойsub  карри  {  мой  ( $ sub ,  @args )  =  @_ ;  вернуть  подпрограмму  {  $ sub -> ( @args ,  @_ )  };  # 3. как возвращаемое значение другой функции }# пример каррирования в программировании на Perl sub  sum  {  my  $ tot  =  0 ;  $ tot  + =  $ _  для  @_ ;  $ tot  }  # возвращает сумму своих аргументов my  $ curried  =  curry  \ & sum ,  5 ,  7 ,  9 ; print  $ curried -> ( 1 , 2 , 3 ),  "\ n" ;  # выводит 27 (= 5 + 7 + 9 + 1 + 2 + 3)

Другие конструкции принимают в качестве аргументов голые блоки , которые выполняют функцию, аналогичную лямбда-функциям одного параметра, но не имеют того же соглашения о передаче параметров, что и функции - @_ не установлено.

мои  @squares  =  map  {  $ _  *  $ _  }  1 .. 10 ;  # map и grep не используют ключевое слово sub my  @ square2  =  map  $ _  *  $ _ ,  1 .. 10 ;  # фигурные скобки не нужны для одного выражениямой  @bad_example  =  map  {  print  for  @_  }  1 .. 10 ;  # значения не передаются как обычная функция Perl

PHP [ править ]

До 4.0.1 в PHP не было поддержки анонимных функций. [39]

PHP с 4.0.1 по 5.3 [ править ]

В PHP 4.0.1 впервые появилась create_functionподдержка анонимных функций. Этот вызов функции создает новую функцию со случайным именем и возвращает ее имя (в виде строки)

$ foo  =  create_function ( '$ x' ,  'return $ x * $ x;' ); $ bar  =  create_function ( " \ $ x" ,  "return \ $ x * \ $ x;" ); эхо  $ foo ( 10 );

Список аргументов и тело функции должны быть заключены в одинарные кавычки, или знаки доллара должны быть экранированы. В противном случае PHP предполагает, что " $x" означает переменную, $xи подставит ее в строку (хотя, возможно, не существует) вместо того, чтобы оставить " $x" в строке. Для функций с кавычками или функций со многими переменными может быть довольно утомительно следить за тем, чтобы предполагаемое тело функции было тем, что интерпретирует PHP.

Каждый вызов create_functionсоздает новую функцию, которая существует для остальной части программы и не может быть собрана мусором , необратимо используя память в программе. Если это используется для создания анонимных функций много раз, например, в цикле, это может вызвать такие проблемы, как раздувание памяти.

PHP 5.3 [ править ]

PHP 5.3 добавил новый вызываемый класс Closureи магический метод, __invoke()который делает экземпляр класса вызываемым. [40]

$ х  =  3 ; $ func  =  функция ( $ z )  {  return  $ z  *  2 ;  }; echo  $ func ( $ x );  // выводит 6

В этом примере $funcявляется экземпляром Closureи echo $func($x)эквивалентен echo $func->__invoke($x). PHP 5.3 имитирует анонимные функции, но не поддерживает настоящих анонимных функций, потому что функции PHP по-прежнему не являются объектами первого класса.

PHP 5.3 поддерживает замыкания, но переменные должны быть явно указаны как таковые:

$ х  =  3 ; $ func  =  function ()  использовать ( & $ x )  {  $ x  * =  2 ;  }; $ func (); echo  $ x ;  // выводит 6

Переменная $xсвязана ссылкой, поэтому вызов $funcмодифицирует ее, и изменения видны вне функции.

PHP 7.4 [ править ]

Стрелочные функции были введены в PHP 7.4.

$ х  =  3 ; $ func  =  fn ( $ z )  =>  $ z  *  2 ; echo  $ func ( $ x );  // выводит 6

Диалекты Пролога [ править ]

Logtalk [ править ]

Logtalk использует следующий синтаксис для анонимных предикатов (лямбда-выражений):

{ FreeVar1 , FreeVar2 , ... } / [ LambdaParameter1 , LambdaParameter2 , ...] >> Цель

Простой пример без свободных переменных и с использованием предиката отображения списка:

| ? - meta :: map ([ X , Y ] >> ( Y  равно  2 * X ), [ 1 , 2 , 3 ], Ys ).Ys  = [ 2 , 4 , 6 ]да

Также поддерживается каррирование. Приведенный выше пример можно записать как:

| ? - meta :: map ([ X ] >> ([ Y ] >> ( Y  равно  2 * X )), [ 1 , 2 , 3 ], Ys ).Ys  = [ 2 , 4 , 6 ]да

Визуальный пролог [ править ]

Анонимные функции (обычно анонимные предикаты ) были введены в Visual Prolog в версии 7.2. [41] Анонимные предикаты могут захватывать значения из контекста. Если он создан в члене объекта, он также может получить доступ к состоянию объекта (путем захвата This).

mkAdderвозвращает анонимную функцию, которая захватила аргумент Xв закрытии. Возвращенная функция - это функция, которая добавляет Xк своему аргументу:

пункты  mkAdder ( X )  =  {  ( Y )  =  X + Y  }.

Python [ править ]

Python поддерживает простые анонимные функции через лямбда-форму. [29] Исполняемое тело лямбда-выражения должно быть выражением и не может быть оператором, что является ограничением, ограничивающим его полезность. Значение, возвращаемое лямбдой, является значением содержащегося в нем выражения. Лямбда-формы можно использовать везде, где это возможно для обычных функций. Однако эти ограничения делают его очень ограниченной версией нормальной функции. Вот пример:

>>> foo  =  лямбда  x :  x  *  x >>> print ( foo ( 10 )) 100

В общем, соглашение Python поощряет использование именованных функций, определенных в той же области, что и анонимные функции на других языках. Это приемлемо, поскольку локально определенные функции реализуют всю мощь замыканий и почти так же эффективны, как использование лямбда-выражения в Python. В этом примере можно сказать, что встроенная степенная функция каррирована :

>>> def  make_pow ( n ): ...  def  fixed_exponent_pow ( x ): ...  return  pow ( x ,  n ) ...  return  fixed_exponent_pow ... >>> sqr  =  make_pow ( 2 ) >>> print  ( SQR ( 10 )) 100 >>> детеныш  =  make_pow ( 3 ) >>> печати  ( детеныш ( 10)) 1000

R [ править ]

В R анонимные функции определяются с использованием синтаксиса function(argument-list)expression.

> f  <-  функция ( x ) x * x ;  f ( 8 ) [1] 64 > ( функция ( x , y ) x + y ) ( 5 , 6 ) [1] 11

Раку [ править ]

В Raku все блоки (даже связанные с if, while и т. Д.) Являются анонимными функциями. Блок, который не используется в качестве rvalue , выполняется немедленно.

  1. полностью анонимный, называется как созданный
    { скажите  "мне позвонили" };
  2. присвоено переменной
    мой  $ squarer1 = -> $ x { $ x * $ x }; №2а. заостренный блок my  $ squarer2 = { $ ^ x * $ ^ x }; # 2б. twigil my  $ squarer3 = { мой  $ x = shift  @_ ; $ x * $ x }; # 2c. Стиль Perl 5
  3. карри
    sub  add ( $ m , $ n ) { $ m + $ n } мой  $ seven = add ( 3 , 4 );мой  $ add_one = & добавить . предполагая ( m => 1); мои восемь долларов =  $ add_one ( семь долларов );
  4. Объект WhateverCode
    мой  $ w = * - 1 ; # Объект WhateverCode my  $ b = { $ _ - 1 }; # тот же функционал, но как блок Callable

Руби [ править ]

Ruby поддерживает анонимные функции с помощью синтаксической структуры, называемой блоком . В Ruby есть два типа данных для блоков. Procs ведут себя аналогично замыканиям , тогда как lambdas ведут себя более аналогично анонимной функции. [42] При передаче в метод блок в некоторых случаях преобразуется в Proc.

irb (main): 001: 0> # Пример 1: irb (main): 002: 0 * # Чисто анонимные функции, использующие блоки. irb (main): 003: 0 * ex  =  [ 16 . 2 ,  24 . 1 ,  48 . 3 ,  32 . 4 ,  8 . 5 ] => [16.2, 24.1, 48.3, 32.4, 8.5] IRB (основной): 004: 0> ех . sort_by  {  | х |  х  -  х . to_i  }  # Сортировка по дробной части без учета целой части.=> [24.1, 16.2, 48.3, 32.4, 8.5] irb (main): 005: 0> # Пример 2: irb (main): 006: 0 * # Функции первого класса как явный объект Proc - irb (main ): 007: 0 * ex  =  Proc . new  {  добавляет  "Привет, мир!"  } => # <Proc: 0x007ff4598705a0 @ (IRB): 7> IRB (основной): 008: 0> ех . Звоните Привет, мир! => nil irb (main): 009: 0> # Пример 3: irb (main): 010: 0 * # Функция, возвращающая объект лямбда-функции с параметрами irb (main): 011: 0 * def  is_multiple_of ( n ) irb ( основной): 012: 1> лямбда { | х |  x  %  n  ==  0 } irb (main): 013: 1> end => nil irb (main): 014: 0> multiple_four  =  is_multiple_of ( 4 ) => # <Proc: 0x007ff458b45f88 @ (irb): 12 (lambda )> irb (основной): 015: 0> multiple_four . call ( 16 ) => true irb (main): 016: 0> multiple_four [ 15 ] => false

Ржавчина [ править ]

В Rust анонимные функции называются замыканиями. [43] Они определены с использованием следующего синтаксиса:

| < параметр - имя > : < тип > |  -> < возврат - тип > { < тело > };   

Например:

пусть f = | x : i32 | -> i32 { x * 2 };         

Однако с помощью вывода типа компилятор может сделать вывод о типе каждого параметра и возвращаемом типе, поэтому приведенная выше форма может быть записана как:

пусть f = | х | { x * 2 };        

В замыканиях с одним выражением (например, тело с одной линией) фигурные скобки можно опустить:

пусть f = | х | х * 2 ;      

Замыкания без входного параметра записываются так:

пусть f = || println! ( «Привет, мир!» );    

Замыкания могут передаваться как входные параметры функций, которые ожидают указатель на функцию:

// Функция, которая принимает указатель на функцию в качестве аргумента и вызывает его // со значением `5`. fn  apply ( f : fn ( i32 )  -> i32 )  -> i32  { // Нет точки с запятой, чтобы указать неявный возврат f ( 5 ) }fn  main () {  // Определение замыкания let f = | х | х * 2 ;        println! ( "{}" , применить ( f )); // 10 println! ( "{}" , f ( 5 )); // 10 }     

Однако могут потребоваться сложные правила для описания того, как собираются значения в теле замыкания. Они реализуются с помощью Fn, FnMutи FnOnceчерты: [44]

  • Fn: замыкание захватывается по ссылке ( &T). Они используются для функций, которые все еще могут быть вызваны, если у них есть только справочный доступ (с &) к своей среде.
  • FnMut: замыкание захватывается изменяемой ссылкой ( &mut T). Они используются для функций, которые могут быть вызваны, если у них есть изменяемый ссылочный доступ (с &mut) к их среде.
  • FnOnce: закрытие захватывается по значению ( T). Они используются для функций, которые вызываются только один раз.

С помощью этих свойств компилятор будет захватывать переменные с наименьшими ограничениями. [45] Они помогают управлять тем, как значения перемещаются между областями действия, что очень важно, поскольку Rust следует конструкции времени жизни, чтобы гарантировать, что значения «заимствуются» и перемещаются предсказуемым и явным образом. [46]

Ниже показано, как можно передать замыкание в качестве входного параметра с помощью Fnтрейта:

// Функция, которая принимает значение типа F (который определяется как // общий тип, реализующий черту `Fn`, например, замыкание) // и вызывает его со значением` 5`. fn  apply_by_ref < F > ( f : F )  -> i32,  где F : Fn ( i32 ) -> i32 {   ж ( 5 )}fn  main () {  пусть f = | х | {     println! ( "Я получил значение: {}" , x );  х * 2   };  // Применяет функцию перед выводом ее возвращаемого значения println! ( "5 * 2 = {}" , apply_by_ref ( f ));  }// ~~ Вывод программы ~~ // Получил значение: 5 // 5 * 2 = 10

Scala [ править ]

В Scala анонимные функции используют следующий синтаксис: [47]

( x :  Int ,  y :  Int )  =>  x  +  y

В определенных контекстах, например, когда анонимная функция является параметром, передаваемым другой функции, компилятор может вывести типы параметров анонимной функции, и они могут быть опущены в синтаксисе. В таких контекстах также можно использовать сокращение для анонимных функций, используя символ подчеркивания для введения безымянных параметров.

val  list  =  Список ( 1 ,  2 ,  3 ,  4 ) список . reduceLeft (  ( x ,  y )  =>  x  +  y  )  // Здесь компилятор может сделать вывод, что типы x и y оба являются Int. // Таким образом, аннотации типов для параметров анонимной функции не требуются.список . reduceLeft (  _  +  _  )  // Каждое подчеркивание обозначает новый безымянный параметр в анонимной функции. // Это приводит к еще более короткому эквиваленту анонимной функции выше.

Smalltalk [ править ]

В Smalltalk анонимные функции называются блоками, и они вызываются (вызываются) путем отправки им сообщения «значения». Если аргументы должны быть переданы, должно использоваться сообщение «значение: ... значение:» с соответствующим количеством аргументов значения.

[ : x  |  x * x ] значение:  4 "возвращает 16"

Блоки Smalltalk технически закрываются, что позволяет им пережить определенную область видимости и по-прежнему ссылаться на объявленные в них переменные.

[ : a  |  [ : n  |  а  +  п ]] value:  10 "возвращает внутренний блок, который добавляет 10 к его аргументу."

Swift [ править ]

В Swift анонимные функции называются закрытием. [48] Синтаксис имеет следующий вид:

{  ( параметры )  ->  returnType  в  заявлении }

Например:

{  ( S1 :  строка ,  s2 :  строка )  ->  Bool  в  возвращении  s1  >  s2 }

Для краткости и выразительности типы параметров и возвращаемый тип могут быть опущены, если они могут быть выведены:

{  S1 ,  s2  в  возвращении  s1  >  s2  }

Точно так же Swift также поддерживает неявные операторы возврата для замыканий с одним оператором:

{  s1 ,  s2  в  s1  >  s2  }

Наконец, имена параметров также можно не указывать; если он опущен, на параметры ссылаются с использованием сокращенных имен аргументов, состоящих из символа $, за которым следует их позиция (например, $ 0, $ 1, $ 2 и т. д.):

{  $ 0  >  $ 1  }

Tcl [ править ]

В Tcl применение анонимной функции возведения в квадрат к 2 выглядит следующим образом: [49]

apply  { x  {expr  { $ x * $ x }}}  2 # возвращает 4

В этом примере используются два кандидата на роль функции в Tcl. Самый общий обычно называется префиксом команды , и если переменная f содержит такую ​​функцию, то способ выполнения приложения функции f ( x ) будет следующим:

{ * } $ f  $ x

где {*}- префикс расширения (новый в Tcl 8.5). Префикс команды в приведенном выше примере - применить. {x {expr {$x*$x}}}Имена команд могут быть связаны с префиксами команд с помощью interp aliasкоманды. Префиксы команд поддерживают каррирование . Префиксы команд очень распространены в API Tcl .

Другой кандидат на «функцию» в Tcl обычно называется лямбда и появляется как {x {expr {$x*$x}}}часть приведенного выше примера. Это часть, которая кэширует скомпилированную форму анонимной функции, но ее можно вызвать только путем передачи applyкоманде. Лямбда-выражения не поддерживают каррирование, если они не связаны с applyпрефиксом команды. Лямбды редко встречаются в API Tcl.

Visual Basic .NET [ править ]

Visual Basic .NET 2008 представил анонимные функции через лямбда-форму. В сочетании с неявной типизацией VB обеспечивает экономичный синтаксис для анонимных функций. Как и в Python, в VB.NET анонимные функции должны быть определены в одной строке; они не могут быть составными утверждениями. Кроме того, анонимная функция в VB.NET действительно должна быть VB.NET Function- она ​​должна возвращать значение.

Dim  foo  =  Функция ( x )  x  *  x Консоль . WriteLine ( foo ( 10 ))

В Visual Basic.NET 2010 добавлена ​​поддержка многострочных лямбда-выражений и анонимных функций без возвращаемого значения. Например, функция для использования в Thread.

Dim  т  Как  Новая  система . Резьба . Thread ( Sub  ()  для  n  как  целое число  = от  0  до  10  'Считайте до 10  консоли . WriteLine ( n )  ' Распечатайте каждое число  Next  End  Sub  ) t . Старт ()

См. Также [ править ]

  • Первоклассная функция

Ссылки [ править ]

  1. ^ «Функции высшего порядка» . Learnyouahaskell.com . Проверено 3 декабря 2014 .
  2. ^ Фернандес, Марибель (2009), Модели вычислений: Введение в теорию вычислимости , Темы для бакалавров в области компьютерных наук, Springer Science & Business Media, стр. 33, ISBN 9781848824348, Лямбда-исчисление ... было введено Алонзо Черчем в 1930-х годах как точное обозначение теории анонимных функций.
  3. ^ "Баш лямбда" . 2019-03-08.
  4. ^ Билл Вагнер. «Лямбда-выражения - справочник по C #» . docs.microsoft.com . Проверено 24 ноября 2020 .
  5. ^ «Закрытие поддержки» . Архивировано из оригинала на 2014-01-06 . Проверено 5 января 2014 .
  6. ^ «Что нового в ColdFusion 10» . Архивировано из оригинала на 2014-01-06 . Проверено 5 января 2014 .
  7. ^ «Справочник по управляемому COBOL» . Документация Micro Focus . Микро Фокус . Проверено 25 февраля 2014 года .
  8. ^ a b «Экскурсия по языку Дарт» . dart.dev . Проверено 24 ноября 2020 .
  9. ^ «Анонимные методы в Delphi - RAD Studio» . docwiki.embarcadero.com . Проверено 24 ноября 2020 .
  10. ^ a b «Синтаксис Erlang / Elixir: ускоренный курс» . elixir-lang.github.com . Проверено 24 ноября 2020 .
  11. ^ а б «Эрланг - Funs» . erlang.org . Проверено 24 ноября 2020 .
  12. ^ а б картермп. «Лямбда-выражения: забавное ключевое слово - F #» . docs.microsoft.com . Проверено 24 ноября 2020 .
  13. ^ «Котировки - Факторная документация» . Проверено 26 декабря 2015 года . Цитата - это анонимная функция (значение, обозначающее фрагмент кода), которую можно использовать как значение и вызывать с помощью комбинаторов Fundamental.
  14. ^ "Фринк" . frinklang.org . Проверено 24 ноября 2020 .
  15. ^ a b «Анонимные функции в GoLang» . Документы GoLang . Проверено 24 ноября 2020 .
  16. ^ "Документация Госу" (PDF) . Проверено 4 марта 2013 года .
  17. ^ "Groovy Documentation" . Архивировано из оригинального 22 мая 2012 года . Проверено 29 мая 2012 года .
  18. ^ «Функции · Язык Джулии» . docs.julialang.org . Проверено 24 ноября 2020 .
  19. ^ "Функции высшего порядка и лямбды - язык программирования Котлин" . Котлин . Проверено 24 ноября 2020 .
  20. ^ «Программирование на Lua: 6» . www.lua.org . Проверено 24 ноября 2020 .
  21. ^ «Программирование Maple: 1.6: Анонимные функции и выражения - Центр приложений» . www.maplesoft.com . Проверено 24 ноября 2020 .
  22. ^ "Maxima 5.17.1 Руководство: 39. Определение функции" . maths.cnam.fr . Проверено 24 ноября 2020 .
  23. ^ "Руководство Nim, анонимные процедуры" .
  24. ^ «Примеры кода - OCaml» . ocaml.org . Проверено 24 ноября 2020 .
  25. ^ «GNU Octave: анонимные функции» . octave.org . Проверено 24 ноября 2020 .
  26. ^ "Функциональные литералы" . Руководство пользователя OpenSCAD . Викиучебники . Проверено 22 февраля 2021 года .
  27. ^ a b "perlsub - Подпрограммы Perl - Браузер Perldoc" . perldoc.perl.org . Проверено 24 ноября 2020 .
  28. ^ «PHP: Анонимные функции - Руководство» . www.php.net . Проверено 24 ноября 2020 .
  29. ^ a b «6. Выражения - документация Python 3.9.0» . docs.python.org . Проверено 24 ноября 2020 .
  30. ^ «4.4 Функции: лямбда» . docs.racket-lang.org . Проверено 24 ноября 2020 .
  31. ^ a b "Проекты / Vala / Учебник - GNOME Wiki!" . wiki.gnome.org . Проверено 24 ноября 2020 .
  32. Ярви, Яакко; Пауэлл, Гэри (nd). «Глава 16. Boost.Lambda» . Документация по усилению . Boost . Проверено 22 декабря 2014 года .
  33. ^ Спецификация языка C # 4.0, раздел 5.3.3.29
  34. ^ «Что нового в JDK 8» .
  35. ^ a b Учебники по Java: лямбда-выражения , docs.oracle.com
  36. ^ «Программирование на Lua - Подробнее о функциях» . Архивировано 14 мая 2008 года . Проверено 25 апреля 2008 .
  37. ^ https://www.cs.cornell.edu/courses/cs3110/2019sp/textbook/basics/anonymous_functions.html
  38. ^ https://nim-lang.github.io/Nim/manual.html#procedures-anonymous-procs
  39. ^ http://php.net/create_function в верхней части страницы указывает это с помощью «(PHP 4> = 4.0.1, PHP 5)»
  40. ^ "PHP: rfc: closures" .
  41. ^ «Анонимные предикаты» . в справочнике по языку Visual Prolog
  42. ^ Sosinski, Роберт (2008-12-21). «Понимание Ruby Blocks, Procs и Lambdas» . Reactive.IO. Архивировано из оригинала на 2014-05-31 . Проверено 30 мая 2014 .
  43. ^ «Замыкания - пример ржавчины» .
  44. ^ «В качестве входных параметров - Rust by Example» .
  45. ^ «В качестве входных параметров - Rust by Example» .
  46. ^ «Время жизни - ржавчина на примере» .
  47. ^ «Синтаксис анонимной функции - Документация Scala» . Архивировано из оригинала на 2013-07-23 . Проверено 31 декабря 2010 .
  48. ^ «Язык программирования Swift (Swift 3.0.1): закрытие» .
  49. ^ применить страницу руководства , получено 06.09.2012.

Внешние ссылки [ править ]

  • Анонимные методы - когда их использовать? (блог об анонимной функции в Delphi)
  • Компиляция лямбда-выражений: Scala против Java 8
  • анонимные функции php анонимные функции php
  • Лямбда-функции на разных языках программирования