В математике и информатике apply — это функция, которая применяет функцию к аргументам. Он занимает центральное место в языках программирования , производных от лямбда-исчисления , таких как LISP и Scheme , а также в функциональных языках . Она играет важную роль в изучении денотационной семантики компьютерных программ, поскольку представляет собой непрерывную функцию на полных частичных порядках . Apply также является непрерывной функцией в теории гомотопий и фактически лежит в основе всей теории: она позволяет рассматривать гомотопическую деформацию как непрерывный путь в пространстве функций. Аналогично, допустимые мутации (рефакторинги) компьютерных программ можно рассматривать как «непрерывные» в топологии Скотта .
Наиболее общая установка для применения находится в теории категорий , где она правильно сопряжена с каррированием в закрытых моноидальных категориях . Особым случаем являются декартовы закрытые категории , внутренний язык которых представляет собой просто типизированное лямбда-исчисление .
В компьютерном программировании Apply применяет функцию к списку аргументов. Eval и apply — два взаимозависимых компонента цикла eval-apply , который составляет суть оценки Lisp, описанной в SICP . [1] Применение функции соответствует бета-редукции в лямбда-исчислении .
Apply во многих языках также является именем специальной функции, которая принимает функцию и список и использует этот список в качестве собственного списка аргументов функции, как если бы функция вызывалась с элементами списка в качестве аргументов. Это важно в языках с вариационными функциями , потому что это единственный способ вызвать функцию с неопределенным (во время компиляции) количеством аргументов.
В Common Lisp apply — это функция, которая применяет функцию к списку аргументов (обратите внимание, что «+» — это вариативная функция, принимающая любое количество аргументов):
( применить #' + ( список 1 2 ))
Аналогично на схеме:
( применить + ( список 1 2 ))
В C++ Bind [2] используется либо через пространство имен std, либо через пространство имен boost.
В C# и Java переменные аргументы просто собираются в массив. Вызывающая сторона может явно передать массив вместо переменных аргументов. Это можно сделать только для вариативного параметра. Невозможно применить массив аргументов к невариативному параметру без использования отражения . Неоднозначный случай возникает, если вызывающая сторона хочет передать сам массив в качестве одного из аргументов, а не использовать массив в качестве списка аргументов. В этом случае вызывающая сторона должна привести массив к, Object
чтобы компилятор не использовал интерпретацию применения .
variadicFunc ( массивOfArgs );
В версии 8 были представлены лямбда-выражения. Функции реализованы как объекты с функциональным интерфейсом, интерфейсом только с одним нестатическим методом. Стандартный интерфейс
Функция < Т , Р >
состоят из метода (плюс некоторые статические служебные функции):
R применить ( T пункт )
В Go типизированные переменные аргументы просто собираются в срез. Вызывающий может явно передать срез вместо переменных аргументов, добавив ...
к аргументу среза. Это можно сделать только для вариативного параметра. Вызывающий не может применить массив аргументов к невариативным параметрам без использования отражения.
s := [] string { "foo" , "bar" } variadicFunc ( s ... )
В Haskell функции можно применять простым сопоставлением:
функция параметр1 параметр2 ...
В Haskell синтаксис также можно интерпретировать так, что каждый параметр по очереди выполняет свою функцию. В приведенном выше примере «func param1» возвращает другую функцию, принимающую на один параметр меньше, которая затем применяется к param2 и так далее, пока у функции не останется параметров.
В JavaScript объекты функций имеют apply
метод, первый аргумент — это значение this
ключевого слова внутри функции; второй — список аргументов:
функция . применить ( ноль , аргументы );
ES6 добавляет оператор расширения func(...args)
[3] , который можно использовать вместо apply
.
В Lua apply можно записать так:
функция apply ( f ,...) return f (...) end
В Perl массивы, хэши и выражения автоматически «сглаживаются» в один список при оценке в контексте списка, например, в списке аргументов функции.
# Эквивалентные вызовы подпрограмм: @args = ( @some_args , @more_args ); функция ( @args ); func ( @some_args , @more_args );
В PHP это apply
называется call_user_func_array
:
call_user_func_array ( 'имя_функции' , $args );
В Python и Ruby та же нотация звездочки, которая используется при определении переменных функций , используется для вызова функции в последовательности и массиве соответственно:
функция ( * аргументы )
Изначально в Python была функция Apply, но в версии 2.3 она была устаревшей в пользу звездочки и удалена в версии 3.0. [4]
В R создает do.call
и выполняет вызов функции по имени или функции и списку аргументов, которые ей нужно передать:
f ( x1 , x2 ) # также можно выполнить через do.call ( what = f , args = list ( x1 , x2 ))
В Smalltalk объекты блоков (функций) имеют valueWithArguments:
метод, который принимает массив аргументов:
aBlock valueWithArguments: args
Начиная с Tcl 8.5, [5] функцию можно применять к аргументам с помощью apply
команды
применить функцию ? arg1 arg2 ... ?
где функция представляет собой список из двух элементов {тело args} или список из трёх элементов {пространство имен тела args}.
Рассмотрим функцию , то есть где скобочные обозначения обозначают пространство функций от A до B. С помощью каррирования есть уникальная функция . Тогда Apply предоставляет универсальный морфизм
так что
или, что то же самое, имеется коммутационная диаграмма
Точнее, curry и apply — сопряженные функторы .
Обозначение пространства функций от A до B чаще встречается в информатике. Однако в теории категорий он известен как экспоненциальный объект и записывается как . Есть и другие общие различия в обозначениях; например, Apply часто называют Eval , [6] хотя в информатике это не одно и то же, причем eval отличается от Apply , поскольку это оценка строковой формы функции с ее аргументами, а не приложения. функции к некоторым аргументам.
Кроме того, в теории категорий карри обычно обозначается как , поэтому оно пишется как карри ( g ). Это обозначение противоречит использованию в лямбда-исчислении , где лямбда используется для обозначения связанных переменных. С учетом всех этих изменений в обозначениях сопряженность Apply и curry выражается в коммутирующей диаграмме.
Статьи об экспоненциальном объекте и декартовой замкнутой категории дают более точное обсуждение теоретико-категорной формулировки этой идеи. Таким образом, использование лямбды здесь не случайно; Внутренний язык декартовых замкнутых категорий — это просто типизированное лямбда-исчисление . Наиболее общими настройками Apply являются закрытые моноидальные категории , примером которых являются декартовы закрытые категории. В гомологической алгебре сопряженность curry и apply известна как присоединение тензорного хома .
В теории порядка , в категории полных частичных порядков , наделенных топологией Скотта , и curry , и apply являются непрерывными функциями (то есть они непрерывны по Скотту ). [7] Это свойство помогает установить фундаментальную обоснованность изучения денотационной семантики компьютерных программ.
В алгебраической геометрии и теории гомотопий , curry и apply являются непрерывными функциями, когда пространство непрерывных функций от до задано компактной открытой топологией , и локально компактно по Хаусдорфу . Этот результат очень важен, поскольку он лежит в основе теории гомотопий, позволяя понимать гомотопические деформации как непрерывные пути в пространстве функций.