![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
BasicsBoost , Chapter 1. Phoenix 3.2.0 , Chapter 1. Phoenix 3.2.0
|
![]() |
Note |
---|---|
Забавно, что функции могут даже возвращать функции. Посмотрим, что это значит за короткое время. |
Представьте себе функцию черного ящика. Вы передаете аргументы, и это возвращает что-то обратно. На рисунке ниже показан типичный сценарий.
Полностью оцененная функция — это функция, в которой приводятся все аргументы. Все функции на простом C++ полностью оценены. Когда вы вызываете функцию<sin(x)
>, вы должны пройти число x. Функция возвращает результат взамен: грех х. Когда вы вызываете функцию<add(x,y)
>, вы должны пройти два числа x и y. Функция возвращает сумму двух чисел. Приведенная ниже цифра является полностью оцененной функцией<add
>.
Частично применяемая функция — это функция, в которой представлены не все аргументы. Если мы можем частично применить функцию<add
>выше, мы можем передать только первый аргумент. При этом функция не имеет всей необходимой информации, необходимой для выполнения задачи по вычислению и возврату результата. Вместо этого он возвращает другую функцию, функцию лямбды. В отличие от первоначальной функции<add
>, которая имеет аритмию 2, полученная функция лямбда имеет аритмию 1. Почему? Поскольку мы уже предоставили часть входных данных:<2
>
Теперь, когда мы втиснем число в нашу функцию лямбды, оно вернет 2 плюс все, что мы пройдем. Функция лямбда по существу запоминает 1) исходную функцию,<add
>и 2) частичный вход, 2. На рисунке ниже показан случай, когда мы передаем 3 нашей функции лямбда, которая затем возвращает 5:
Очевидно, что частичное применение функции<add
>, как мы видим выше, не может быть выполнено непосредственно на C++, где мы должны предоставить все аргументы, которые ожидает функция. Именно здесь находится библиотека Феникса. Библиотека предоставляет возможности для выполнения частичных функций. И даже больше, с Фениксом, эти результирующие функции больше не будут черными ящиками.
Так что за шумиха? Что делает приложение частичной функции таким полезным? Вспомните наш оригинальный пример впредыдущем разделе:
std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
Выражение<arg1%
2==1
>оценивает лямбда-функцию.<arg1
>является заполнителем для аргумента, который будет представлен позже. Следовательно, поскольку существует только один непредставленный аргумент, функция лямбда имеет аритмию 1. Так уж вышло, что<find_if
>снабжает непоставленную аргументацию, поскольку она колеблется от<c.begin()
>до<c.end()
>.
![]() |
Note |
---|---|
Функции высшего порядка — это функции, которые могут принимать другие функции в качестве аргументов, а также могут возвращать функции в качестве результатов. Функции высшего порядка — это функции, которые рассматриваются как любые другие объекты и могут использоваться в качестве аргументов и возвращаемых значений из функций. |
В Фениксе, если говорить точнее, оценка функции имеет два этапа:
Первый этап обрабатывается набором функций генератора. Это ваши передние концы (с точки зрения клиента). Эти генераторы создают (через приложение частичной функции) функции более высокого порядка, которые могут передаваться так же, как любой другой указатель функции или объект функции. Вторая стадия, вызов фактической функции, может быть вызвана или выполнена в любое время в будущем, или не выполнена вообще; отсюда«ленивый».
Если присмотреться повнимательнее, то первый шаг предполагает частичное применение функции:
arg1 % 2 == 1
Второй этап — это вызов функции (выполненный внутри функции<find_if
>). Это бэкэнды (часто конечный вызов никогда не виден клиенту). В нашем примере<find_if
>, если мы заглянем внутрь, мы увидим что-то вроде:
template <class InputIterator, class Predicate> InputIterator find_if(InputIterator first, InputIterator last, Predicate pred) { while (first != last && !pred(*first)) // <--- The lambda function is called here ++first; // passing in *first return first; }
Опять же, как правило, мы, как клиенты, видим только первый шаг. Однако в этом документе, а также в приведенных примерах и тестах не удивляйтесь тому, что первый и второй этапы сопоставляются, чтобы проиллюстрировать полную семантику выражений Феникса. Примеры:
int x = 1; int y = 2; std::cout << (arg1 % 2 == 1)(x) << std::endl; // prints 1 or true std::cout << (arg1 % 2 == 1)(y) << std::endl; // prints 0 or false
Обычно мы, как клиенты, записываем функции обратного вызова, в то время как библиотеки (например, STL) предоставляют абонента (например,<find_if
>). Если вам нужно написать алгоритм STL, который принимает предикат, или разработать библиотеку графического интерфейса, которая принимает обработчиков событий, вы должны знать о малоизвестной проблеме на C++, называемой «Проблема функции переадресации».
Посмотрите еще раз на код выше:
(arg1 % 2 == 1)(x)
Обратите внимание, что на втором этапе (окончательная оценка) мы использовали переменную<x
>.
В Phoenix мы эмулировали идеальную пересылку через препроцессорные макросы, генерирующие код, чтобы разрешить ссылки на const и non-const.
Мы генерируем эти перегрузки второй стадии для выражения Феникса до<BOOST_PHOENIX_PERFECT_FORWARD_LIMIT
>.
![]() |
Note |
---|---|
Вы можете установить< |
Если не указано иное, генерируемые Фениксом функции полностью полиморфны. Например, приведенный выше пример<add
>может применяться к целым числам, плавающим точкам, определяемым пользователем сложным числам или даже строкам. Пример:
std::string h("Hello"); char const* w = " World"; std::string r = add(arg1, arg2)(h, w);
Оценить<std::string("Hello
World")
>. Наблюдающий читатель может заметить, что этот вызов функции фактически принимает гетерогенные аргументы, где<arg1
>имеет тип<std::string
>и<arg2
>имеет тип<charconst*
>.<add
>все еще работает, потому что стандартная библиотека C++ позволяет выражение<a+b
>, где<a
>является<std::string
>и<b
>является<char
const*
>.
Статья Basics раздела Chapter 1. Phoenix 3.2.0 Chapter 1. Phoenix 3.2.0 может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Chapter 1. Phoenix 3.2.0 ::
реклама |