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