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

редактировать
Определение функций, не привязанное к стыкатору

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

Анонимные функции берут начало в работе Алонзо Черча в его изобретении лямбда-исчисления, в котором все функции анонимны, в 1936 году, до вычислительных машин. На нескольких языках программирования анонимные функции вводятся с использованием ключевого слова лямбда, а анонимные функции часто называют лямбда или лямбда-абстракциями. Анонимные функции языков были особенностью программирования с Lisp в 1958 году, и все большее число современных языков программирования анонимные функции.

Содержание
  • 1 Использует
    • 1.1 Сортировка
    • 1.2 Замыкания
    • 1.3 Каррирование
    • 1.4 Расширения высшего порядка
      • 1.4.1 Карта
      • 1.4.2 Фильтр
      • 1.4. 3 Свернуть
  • 2 Список языков
  • 3 Примеры
    • 3.1 APL
    • 3.2 C (нестандартное расширение)
      • 3.2.1 GCC
      • 3.2.2 Clang (C, C ++, Objective- C, Objective-C ++)
    • 3.3 C ++ (начиная с C ++ 11)
    • 3.4 C #
    • 3.5 Язык разметки ColdFusion (CFML)
    • 3.6 D
    • 3.7 Dart
    • 3.8 Delphi
    • 3.9 PascalABC.NET
    • 3.10 Elixir
    • 3.11 Erlang
    • 3.12 Go
    • 3.13 Haskell
    • 3.14 Haxe
    • 3.15 Java
      • 3.15.1 Ограничения Java
    • 3.16 JavaScript
    • 3.17 Julia
    • 3.18 Lisp
      • 3.18.1 Common Lisp
      • 3.18.2 Схема
      • 3.18.3 Clojure
    • 3.19 Lua
    • 3.20 Wolfram Language, Mathematica
    • 3.21 MATLAB, Octave
    • 3.22 Maxima
    • 3.23 ML
      • 3.23.1 OCaml
      • 3.23.2 F #
      • 3.23.3 Standard ML
    • 3.24 Shell Next Generation Shell
    • 3.25 Perl
      • 3.25.1 Perl 5
    • 3.26 PHP
      • 3.26.1 PHP 4.0.1–5.3
      • 3.26.2 PHP 5.3
    • 3.27 Диалекты Prolog
      • 3.27.1 Logtalk
      • 3.27.2 Визуальный пролог
    • 3.28 Python
    • 3.29 R
    • 3.30 Raku
    • 3.31 Ruby
    • 3.32 Rust
    • 3.33 Scala
    • 3.34 Smalltalk
    • 3.35 Swift
    • 3.36 Tcl
    • 3.37 Visual Basic.NET
  • 4 См. Также
  • 5 Ссылки
  • 6 Внешние ссылки
Использование

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

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

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

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

Сортировка

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

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

>>>a = ['house', 'car', 'bike']>>>a.sort (key = lambda x : len (x))>>>print (a) ['car', 'bike', 'house]

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

lambda x: len (x)

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

лямбда arg1, arg2, arg3,...: 

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

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

затем анонимная функция принимает один аргумент, x, и возвращает длину своего аргумента, используется метод sort ()в качестве критерия сортировки. Другой пример - сортировка элементов в списке по имени их класса (в Python все имеет класс):

>>>a = [10, 'number', 11.2]>>>a.sort (key = лямбда x: x. __ class __.__ name__)>>>print (a) [11.2, 10, 'number']

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

Замыкания

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

def comp (threshold): return lambda x: x < threshold

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

>>>func_a = comp (10)>>>func_b = comp (20)>>>print (func_a (5), func_a (8), func_a (13), func_a (21)) True True False False>>>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)>>>half = divisor ( 2)>>>третий = делитель (3)>>>print (половина (32), третий (32)) 16.0 10.666666666666666>>>print (половина (40), третий (40)) 20.0 13.333333333333334

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

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

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

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

Map

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

>>>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 for x in 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 for x in a if x% 2 = = 0]) [2, 4, 6]

Сворачивание

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

>>>from functools import reduce>>>a = [1, 2, 3, 4, 5]>>>print (reduce (лямбда x, y: x * y, a)) 120

Это действует

(((1 × 2) × 3) × 4) × 5 = 120. {\ displaystyle \ left (\ left (\ left (1 \ раз 2 \ вправо) \ раз 3 \ вправо) \ раз 4 \ вправо) \ раз 5 = 120.}\ left (\ left (\ left (1 \ times 2 \ right) \ умножить на 3 \ вправо) \ умножить на 4 \ вправо) \ умножить на 5 = 120.

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

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

Список языков

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

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

ЯзыкПоддержкаПримечания
ActionScript Зеленая галочка Y
Ada Красный X NФункции выражения являются отдельными Ada2012
ALGOL 68 Зеленая галочка Y
APL Зеленая галочка YDyalog, ngn и dzaima APL полностью функции dfns и tacit. GNU APL имеет довольно ограниченную поддержку dfns.
Языки ассемблера Красный X N
Bash Зеленая галочка YСоздана библиотека для поддержки анонимных функций в Bash.
C Красный X NПоддержка предоставляется в Clang и вместе с компилятором LLVM -rt lib. Поддержка GCC предоставляет возможность реализации макроса, которая дает возможность использования. Подробности смотрите ниже.
C# Зеленая галочка Y
C ++ Зеленая галочка YНачало со стандарта C ++ 11
CFML Зеленая галочка YНачало с Railo 4, ColdFusion 10
Clojure Зеленая галочка Y
COBOL Красный X NНестандартный управляемый диалект COBOL Micro Focus поддерживает лямбда-выражения, которые называются анонимными делегатами / методами.
Curl Зеленая галочка Y
D Зеленая галочка Y
Dart Зеленая галочка Y
Delphi Зеленая галочка Y
Dylan Зеленая галочка Y
Eiffel Зеленая галочка Y
Elm Зеленая галочка Y
Elixir Зеленая галочка Y
Erlang Зеленая галочка Y
F# Зеленая галочка Y
Factor Зеленая галочка Y«Котировки» это
Fortran Красный X N
Frink Зеленая галочка Y
Go Зеленая галочка Y
Gosu Зеленая галочка Y
Groovy Зеленая галочка Y
Haskell Зеленая галочка Y
Haxe Зеленая галочка Y
Java Зеленая галочка YПоддерживается в Java 8. См. Подробности в разделе Ограничения Java ниже.
JavaScript Зеленая галочка Y
Julia Зеленая галочка Y
Kotlin Зеленая галочка Y
Lisp Зеленая галочка Y
Logtalk Зеленая галочка Y
Lua Зеленая галочка Y
MUMPS Красный X N
Mathematica Зеленая галочка Y
Maple Зеленая галочка Y
MATLAB Зеленая галочка Y
Maxima Зеленая галочка Y
Зеленая галочка Y
OCaml Зеленая галочка Y
Octave Зеленая галочка Y
Object Pascal Зеленая галочка YDelphi, диалект Object Pascal, изначально поддерживает анонимные функции (формально анонимные методы), начиная с Delphi 2009. Диалект Oxygene Object Pascal также поддерживает их.
Objective-C (Mac OS X 10.6+)Зеленая галочка YВызывается блоков ; В дополнение к Objective-C блоки тоже Программу на C и C ++ при программировании на Apple.
Паскаль Красный X N
Perl Зеленая галочка Y
PHP Зеленая галочка YНачиная с PHP 5.3.0, поддерживаются настоящие анонимные функции. Раньше поддерживались только частичные анонимные функции, которые работали так же, как реализация C #.
PL / I Красный X N
Python Зеленая галочка YPython поддерживает анонимные функции с помощью лямбда-синтаксиса, поддерживает только выражения, но не операторы.
R Зеленая галочка Y
Racket Зеленая галочка Y
Raku Зеленая галочка Y
Rexx Красный X N
RPG Красный X N
Ruby Зеленая галочка YАнонимные функции Ruby, унаследованные от Smalltalk, называются блоками.
Rust Зеленая галочка Y
Scala Зеленая галочка Y
Схема Зеленая галочка Y
Smalltalk Зеленая галочка YАнонимные функции Smalltalk называются блоками.
Standard ML Зеленая галочка Y
Swift Зеленая галочка YАнонимные функции Swift называются Closures.
TypeScript Зеленая галочка Y
Tcl Зеленая галочка Y
Vala Зеленая галочка Y
Visual Basic.NET v9Зеленая галочка Y
Visual Prolog v 7.2Зеленая галочка Y
v25Зеленая галочка Yязык W PCSoft, используя его WinDev / WebDev / WinDev Mobile Suite поддерживает анонимные функции, начиная с версии 25 (2019)
Wolfram Language Зеленая галочка Y
Примеры

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

APL

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

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

C (нестандартное расширение)

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

GCC

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

({тип_ возврата анонимного_имя_функций (параметров) {тело_функции} имя_анонимных_функций;})

Следующий пример работает только с GCC. Из-за того, как макросы раскрываются, l_bodyне может содержать никаких запятых вне скобок; GCC рассматривает запятую как разделитель аргументами макроса. Аргумент l_ret_typeможет быть удален, если доступен __typeof__; в приведенном ниже примере использование __typeof__в массиве вернет testtype *, который при необходимости можно разыменовать для получения фактического значения.

#include // * это определение анонимной функции * / #define lambda (l_ret_type, l_arguments, l_body) \ ({\ l_ret_type l_anonymous_functions_name l_arguments \ l_body \ l_anonymous_functions_name; \})#Indefine_name; \}) \} fe_arrType, fe_arr, fe_fn_body) \ {\ int i = 0; \ for (; i 

Clang (C, C ++, Objective-C, Objective-C ++)

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

^ return_type (parameters) {function_body}

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

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

#include #include int main (void) {void (^ count_loop) () = ^ {for (int i = 0; i < 100; i++) printf("%d\n", i); printf("ah ah ah\n"); }; /* Pass as a parameter to another function */ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), count_loop); /* Invoke directly */ count_loop(); return 0; }

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

C ++ (начиная с C ++ 11)

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

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

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

(int x, int y) ->int {return x + y;}

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

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

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

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

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

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

std :: vector some_list {1, 2, 3, 4, 5}; int total = 0; int value = 5; std :: for_each (начало (некоторый_список), конец (некоторый_список), [общее, значение, это] (int x) {total + = x * значение * this->some_func ();});

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

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

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

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

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

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

auto my_lambda_func = [] (int x) {/*...*/}; auto my_onheap_lambda_func = новый auto ([=] (int x) {/*...*/});

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

#include #include #include double eval (std :: function f, double x = 2.0) {return f (x); } int main () {std :: function f0 = (двойной x) {return 1; }; авто f1 = (двойной х) {вернуть х; }; decltype (f0) fa [3] = {f0, f1, (двойной x) {return x * x; }}; std :: vector 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 (autof : fv) { std::cout << f(2.0) << std::endl; } for (autof : 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; }

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

Теперь у нас есть два способа написать функцию приращения:

let inc x = x + 1 let inc = fun x ->x + 1

Они синтаксически разные, но семантически эквивалентны. То, даже если они включают разные ключевые слова и помещают некоторые электрические слова в разные места, они означают одно и то же.

Анонимные функции также называют лямбда-выражениями, термин, который происходит из лямбда-исчисления, которое является математической моделью вычислений в том же смысле, что машины Тьюринга используются моделью вычислений. В лямбда-исчислении fun x ->e будет записано как λx.e. Λ обозначает анонимную функцию.

Синтаксис.

fun x1... xn ->e

Статическая семантика.

Если предположить, что x1: t1 и x2: t2 и... и xn: tn, мы можем заключить, что e: u, то забавное x1... xn ->e: t1 ->t2 ->... ->tn ->u. Динамическая семантика.

Анонимная функция уже является значением. Никаких вычислений не нужно.

fun arg ->arg * arg

Фрагмент из CS3110, Корнелл, преподавал Майкл Р. Кларксон, Роберт Л. Констебл, Нейт Фостер, Майкл Д. Джордж, Дэн Гроссман, Дэниел П. Хаттенлочер, Декстер Козен, Грег Моррисетт, Эндрю С. Майерс, Раду Ругина и Рамин Забих.

F #

F# поддерживает анонимные функции, а именно:

(fun x ->x * x) 20 // 400

Standard ML

Standard ML Поддерживает анонимные функции, следующим образом:

fn arg =>arg * arg

Оболочка следующего поколения

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

Синтаксисы:

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

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

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

Perl

Perl 5

Perl 5 поддерживает анонимные функции, а именно:

(sub {print "Мне позвонили \ n"}) ->(); # 1. полностью анонимный, называется как created my $ squarer = sub {my $ x = shift; $ x * $ x}; # 2. присваивается изменяемая подпрограмма {my ($ 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)

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

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

PHP

До 4.0.1, PHP не поддерживаются анонимные функции.

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 (), который делает экземпляр класса вызываемым.

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

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

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

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

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

Диалекты Пролога

Logtalk

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

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

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

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

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

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

Visual Prolog

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

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

mkAdder (X) = {(Y) = X + Y}.

Python

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

>>>foo = lambda 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>>>cub = make_pow (3)>>>print (cub (10)) 1000

R

В R анонимные функции с использованием синтаксиса function (аргумент-список) выражение.

>f <- function(x)x*x; f(8) [1] 64>(function (x, y) x + y) (5,6) [1] 11

Raku

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

  1. полностью анонимный, называется как созданный
    {скажем "мне позвонили"};
  2. присвоено стандарт
    my $ 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} my $ seven = add (3, 4); мой $ add_one = add.assuming (m =>1); мои восемь долларов = $ add_one (семь долларов);
  4. Объект WhateverCode
    мой $ w = * - 1; # Объект WhateverCode my $ b = {$ _ - 1}; # та же функциональность, но как вызываемый блок

Ruby

Ruby поддерживает анонимные функции с помощью синтаксической структуры, называемой блоком. В Ruby есть два типа данных для блоков. Procведут себя аналогично замыканиям, тогда как лямбдаведут себя более аналогично анонимной функции. При передаче в метод блок в некоторых случаях преобразуется в 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 (main): 004: 0>ex.sort_by {| х | x - x.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 {помещает "Привет, мир!" } =># irb (main): 008: 0>ex.call Привет, мир! =>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) =># irb (main): 015: 0>multiple_four.call (16) =>true irb (main): 016: 0>multiple_four [15] =>false

Rust

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

|: | ->{};

Например:

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

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

let f = | х | {x * 2};

Для замыканий с одним выражением (т. Е. Тело с одной строкой) фигурные скобки можно опустить:

let f = | х | х * 2;

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

let f = || println! («Привет, мир!»);

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

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

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

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

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

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

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

Scala

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

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

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

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

Smalltalk

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

[: x | x * x] value: 4 «возвращает 16»

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

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

Swift

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

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

Например:

{(s1: String, s2: String) ->Bool in return s1>s2}

Для краткости

{s1, s2 взамен s1>s2}

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

{s1, s2 в s1>s2}

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

{$ 0>$ 1 }

Tcl

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

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

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

{*} $ f $ x

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

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

Visual Basic.NET

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

Dim foo = Function (x) x * x Console.WriteLine (foo (10))

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

Dim t As New System.Threading.Thread (Sub () For n As Integer = 0 To 10 'Count to 10 Console.WriteLine (n)' Распечатать каждое число Next End Sub) t.Start ()
См. Также
  • значок Портал компьютерного программирования
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-11 17:17:34
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте