А вот представляете, в том, что воплощено в жизнь в C++, этот общий ответ таки есть! Невероятно для вас, не так ли?
А размещение на стеке без копирования куда-либо оказывается всего лишь приятным следствием оптимизации.
Вот ведь какая реальность. Сурово она с вами.
Я ж вам написал – в памяти, предоставленной функцией, вычислившей значение лямбда-выражения.
Это тот же самый стек. Который не применим, если лямбда должна пережить вызов создавшей её функции.
Более поучительно рассмотреть такой пример.
Я вам привел более поучительный пример выше с использованием копирования лямбд и хранения их в контейнере. Вы явно его не поняли. Разберитесь сперва с ним.
Например не катит, хватит уже строить из себя великого теоретика. Лямбда в C++ может быть вызвана несколько раз. Где именно будет храниться ее состояние между вызовами? Стек не подойдет в общем случае.
Разумеется, рано или поздно вы сможете извлечь какую-нибудь пользу от существования в C++ неполноценного класса-функтора
Ой, какие эпитеты, какая патетика.
Те, кто нормально программируют на C++ (а не строят из себя самого умного в комментариях на Хабре) постоянно извлекают полезную пользу из того факта, что лямбда в C++ -- это функтор.
Речь идёт о том, что эти класс и объект не являются ни концептуально, ни технически необходимыми.
Это уже разговоры о том, что и как могло бы быть у бабушки, чтобы это была уже не бабушка, а скорее дедушка. Но в C++ сделали именно так, получилось и просто, и понятно, и удобно (по крайней мере по меркам C++).
Весь их смысл состоит в том, чтобы соответствовать парадигме C++ “всё есть объект”
Еще раз попрошу координаты вашего дилера. Уж очень крутые вещества он вам поставляет. В C++ нет такой парадигмы.
Это не описание объекта ООП. Это описание того, что получается в результате работы компилятора. А получается объект. К которому применимы некоторые признаки ООП. А посему термин "инстанс" здесь вполне уместен, но именно что в смысле "экземпляр". Поэтому когда вы лезете в разговор о C++ со своим абстрактным "инстансом", то это вызывает недоумение и просьбы уточнить что вы имеете в виду.
И очень, очень удивительно, что вы настолько косноязычны в описании простых вещей. Тогда как наукообразные, но непонятные, высказывания способны выдавать длинными абзацами.
А почему бы им не использоваться в шаблонах?
Потому что в шаблонах используются не "выражения", а типы или значения. А вот этот вот ваше "лексическое" определение лямбды в виде [...](...){...} ничего на сей счет не говорит.
Здесь “an unnamed function object capable of capturing variables in scope” – это и есть просто определение closure.
Как по мне, так это не определение closure, это описание того, что создается в результате обработки лямбда выражения компилятором C++. А именно -- функциональный объект. Который может быть замыканием, а может и не быть.
Так ничего, кроме синтаксиса, по самому большому счёту и не нужно.
Не нужно для чего? Если для того, чтобы продемонстрировать свою банальную эрудицию в сраче на Хабре, то да, больше ничего не нужно.
Если для того, чтобы без проблем пользоваться лямбдами в C++, то это только-только самое начало. Поскольку синтаксис ничего не говорит о том, почему же тогда лямбды могут использоваться в шаблонах. Вроде:
Он изучил то, чего раньше не знал. Я специально лямбда-исчисление не изучал, но наслышан. И это одна из причин почему я вынужден снова и снова макать вас в известную субстанцию и повторять: речь идет о лямбдах в C++, о сугубо практических вещах, перестаньте натягивать на глобус какую-то абстрактную теорию.
А всякие классы и объекты – это просто детали реализации.
Ну ёжкинжеж... Гладко было на бумаге, да, как известно что забыли.
Из этого многообразия у меня ничего не называется “инстанс”.
Здесь – это в определении термина closure, которое вы процитировали.
Я не цитировал определение closure, не приписывайте мне того, чего я не говорил.
И если речь идет про замыкание, то это и есть та часть "сахара", который дает программисту C++ный компилятор. Во времена C++98 функторы приходилось делать вручную и замыкание можно было соорудить на обычных классах только врукопашную, поэтому речь о closure и не шло. Теперь компилятор позволяет это сделать.
Никакой “лямбды” в C++ нет.
Ну надо же. Ж есть, а слова нет.
Есть лямбда-выражение, и это ни что иное, как именно выражение ... {...}.
Это выражение на уровне синтаксиса. Как, например, есть шаблон функции на уровне синтаксиса. Только вот это лишь часть всей истории, отнюдь не самая главная.
А есть ООП-шный объект, который порождается от безымянного класса и является значением лямбда-выражения.
О, надо же, до вас дошло.
И ещё есть результат применения функтора, являющегося значением лямбда-выражения, к конкретному списку фактических параметров.
А есть еще и само по себе "применение функтора", т.е. вызов operator(), который может занимать какое-то время и приводить к разным результатам.
И, проблема в общении с вами в том, что вы не можете вменяемо обозначить что из всего этого многообразия у вас называется "инстанс".
Но роль лямбда-выражения не сводится только к генерации функтора, она ещё и лексическая.
Лексическая роль пусть волнует разработчиков компиляторов, статических анализаторов и IDE. Мне, как простому пользователю языка, интересно то, чем лямбда является в итоге.
Не-не. Здесь речь идёт об определении closure, и имеется в виду список захвата, который как раз и требует применения лексического замыкания.
Здесь -- это где?
Лексическое замыкание делается компилятором. Но, при этом, в C++ оно так же специфическое, т.к. программист должен явным образом описывать что же именно (и как именно) он хочет "замкнуть".
Ну и добавим сюда, что в C++ лямбда может "замкнуть" не только что-то из объемлющего контекста, но и определить собственные "члены" в виде новых объектов, доступных только внутри лямбды (но не локальные переменные в теле лямбды). Вроде вот такого:
int make_value() {...}
auto l = [v = make_value()]() { ... };
Вот только к экземпляру класса (объекту в смысле ООП) это не имеет никакого отношения, а является поведением функционального объекта в смысле
Еще раз: в C++ лямбда -- это экземпляр анонимного класса. Список захвата трансформируется в поля этого класса. Грубо говоря:
int a = ...;
auto l = [a]() {...};
есть ни что иное как:
class __autogenerated_lambda_1 {
int a;
public:
__autogenerated_lambda_1(int a_initial) : a{a_initial} {}
auto operator()() { ... /* здесь имеем дело с __autogenerated_lambda_1::a */ }
};
...
int a = ...;
__autogenerated_lambda_1 l{a};
И как раз этот автоматически сгенерированный функтор и есть вполне себе нормальный ООП-шный объект (при условии, что вам достаточно только инкапсуляции из ООП-шной триады).
является поведением функционального объекта в смысле функционального программирования, которое в C++ целиком реализуется на этапе компиляции
Поделитесь контактами поставщика вашей дури. Аж завидно.
В C++ уже давным давно есть устоявшийся термин "function object" (он же функтор -- functor). Вы его можете найти на том же cppreference. Или, например, здесь.
И да, ссылка на Wiki там сделана не для function object-а, а для closure.
Тот факт, что вы отрицаете применимость ООП к C++ными функторам... Ну тут у вас либо опять "горе от ума", либо вообще дефицит этого самого ума.
Я с самого начала написал, что под инстансом понимаю лямбда-выражение в контексте его вызова. Но вы стали требовать определение, которого нет.
Еще раз вам повторю: лямбда в C++ -- это инстанс (т.е. экземпляр, т.е. объект) некоторого автоматически сгенерированного анонимного класса.
Поэтому с точки зрения C++ это ваше заумное "лямбда-выражение в контексте его вызова" -- это вообще что-то странное. Поскольку есть а) экземпляр лямбды и b) есть конкретный вызов лямбды (т.е. вызов operator() у экземпляра лямбды). И вот ХЗ что вы под "инстансом" понимаете.
Видите, вы сами интуитивно понимаете, о чём идёт речь.
Еще раз, для людей с проблемами развития и пониженной социальной ответственностью: вы используете термин "инстанс", у вас спрашивают что вы под этим понимаете, вы не можете дать вменяемое описание вашего использования термин "инстанс".
Мне не хочется "интуитивно понимать" о чем вы, мне хочется знать конкретно. А вы не можете "в конкретно". Но при этом одеваете на себя мантию величественного теоретика.
Тьфу, срамота.
а стек-фрейма может и вообще не быть.
А вы допустите. Типа "в случае традиционной реализации на стековой архитектуре это будет вызов со своим конкретным стековым фреймом". Этого могло бы быть достаточно.
Но, так понимаю, проста изложения мыслей и вы проживаете в разных вселенных.
Я отвечаю на конкретные обращённые ко мне вопросы.
Я ж вам написал выше, что в программировании это первичное понятие, не определимое через какие-либо формы, и не надо раньше времени сюда погружаться.
Вы дали ссылку на Wiki, в которой термин instance использовался для обозначения двух разных вещей. Так что от вас ожидалось хотя бы объяснение в каком именно смысле вы здесь, в этом обсуждении используете "инстанс". Но вы не смогли.
В философском понимании, инстанс – это онтологический бытийный статус какой-либо сущности. Полегчает нам от этого в техническом смысле?
Вам -- не знаю. Для меня это еще одно доказательство того, что у вас с головой нелады. Ибо в данном разговоре достаточно определить "инстанс" -- это синоним экземпляра/объекта (типа "инстанс класса D" как "объект класса D") или же это "конкретный вызов конкретной функции в конкретным фрейм-стеком и конкретными значениями переданных параметров". Или же еще что-то.
Если вы не можете разговаривать на таком уровне, то я мог бы сказать, куда свою ученость вы могли бы засунуть из-за ее полной бесполезности. Но, боюсь, на Хабре не принято в прямой разговор.
И это нормально, особенно в молодости.
Конечно, и только вы с высоты своих лет познали истину.
Поэтому локальная переменная в теле метода класса, безусловно, является частью класса.
Ну да, ну да.
Но и это слишком глубокое рассуждение, пока мы с вами не договорились о более фундаментальной вещи, а именно, что же такое переменная: имя, обладающее значением, или значение, которому присвоено имя?
Нам бы о более приземленных вещах договориться, например: зачем все эти околотеоритические блуждания в комментариях к данной конкретной статье?
Я человек педантичный и люблю правильное использование терминологии.
Но при этом не можете в ходе дискуссии сформулировать определение используемого вами же термина "инстанс".
Очень жаль, если обсуждение фундаментальных вопросов вы воспринимаете как сотрясения воздуха.
И какой практический смысл в обсуждении "фундаментальных вопросов" в комментариях к сугубо утилитарной статье?
Если вы считаете, что в C++ используется какая-то "неправильная" терминология, а C++ники намеренно искажают какие-то устоявшиеся в некоторой теории понятия, то напишите статью с изложением вашей точки зрения и ссылками на работы, в которых эти самые "термины" и "понятия" вводятся.
Может от этого будет больше пользы.
Здесь же вы пока договорились лишь до того, что локальная переменная в теле метода класса является частью класса. Если "фундаментальные вопросы" в вашем понимании ведут к такому маразму, то может ну их вообще?
Вот так для вас достаточно наглядно: https://wandbox.org/permlink/fPZtYE5VtpKvWc9l
?
Можете еще обратить внимание, что f и g принимают аргументы по-разному.
А вот представляете, в том, что воплощено в жизнь в C++, этот общий ответ таки есть! Невероятно для вас, не так ли?
А размещение на стеке без копирования куда-либо оказывается всего лишь приятным следствием оптимизации.
Вот ведь какая реальность. Сурово она с вами.
Это тот же самый стек. Который не применим, если лямбда должна пережить вызов создавшей её функции.
Я вам привел более поучительный пример выше с использованием копирования лямбд и хранения их в контейнере. Вы явно его не поняли. Разберитесь сперва с ним.
Например не катит, хватит уже строить из себя великого теоретика. Лямбда в C++ может быть вызвана несколько раз. Где именно будет храниться ее состояние между вызовами? Стек не подойдет в общем случае.
Ой, какие эпитеты, какая патетика.
Те, кто нормально программируют на C++ (а не строят из себя самого умного в комментариях на Хабре) постоянно извлекают полезную пользу из того факта, что лямбда в C++ -- это функтор.
Это уже разговоры о том, что и как могло бы быть у бабушки, чтобы это была уже не бабушка, а скорее дедушка. Но в C++ сделали именно так, получилось и просто, и понятно, и удобно (по крайней мере по меркам C++).
Еще раз попрошу координаты вашего дилера. Уж очень крутые вещества он вам поставляет. В C++ нет такой парадигмы.
А что такое "локальная память" функции? Стек?
А если так: https://wandbox.org/permlink/AX8YzQKz7xsmHYXF
Да что же вы такое несете?
https://wandbox.org/permlink/PHtTWQypppHytz0r
Здесь
c
в лямбде захвачено по значению. Иc
из лямбды должно где-то хранится.Это не описание объекта ООП. Это описание того, что получается в результате работы компилятора. А получается объект. К которому применимы некоторые признаки ООП. А посему термин "инстанс" здесь вполне уместен, но именно что в смысле "экземпляр". Поэтому когда вы лезете в разговор о C++ со своим абстрактным "инстансом", то это вызывает недоумение и просьбы уточнить что вы имеете в виду.
И очень, очень удивительно, что вы настолько косноязычны в описании простых вещей. Тогда как наукообразные, но непонятные, высказывания способны выдавать длинными абзацами.
Потому что в шаблонах используются не "выражения", а типы или значения. А вот этот вот ваше "лексическое" определение лямбды в виде
[...](...){...}
ничего на сей счет не говорит.В отличии от.
Как по мне, так это не определение closure, это описание того, что создается в результате обработки лямбда выражения компилятором C++. А именно -- функциональный объект. Который может быть замыканием, а может и не быть.
Не нужно для чего? Если для того, чтобы продемонстрировать свою банальную эрудицию в сраче на Хабре, то да, больше ничего не нужно.
Если для того, чтобы без проблем пользоваться лямбдами в C++, то это только-только самое начало. Поскольку синтаксис ничего не говорит о том, почему же тогда лямбды могут использоваться в шаблонах. Вроде:
и какой смысл здесь играет "universal reference".
Или вот такое:
Он изучил то, чего раньше не знал. Я специально лямбда-исчисление не изучал, но наслышан. И это одна из причин почему я вынужден снова и снова макать вас в известную субстанцию и повторять: речь идет о лямбдах в C++, о сугубо практических вещах, перестаньте натягивать на глобус какую-то абстрактную теорию.
Ну ёжкинжеж... Гладко было на бумаге, да, как известно что забыли.
Тогда что такое "инстанс"?
"Имя, сестра! Имя!" (с)
И то хорошо.
Скорее всего вы правы.
Я не цитировал определение closure, не приписывайте мне того, чего я не говорил.
И если речь идет про замыкание, то это и есть та часть "сахара", который дает программисту C++ный компилятор. Во времена C++98 функторы приходилось делать вручную и замыкание можно было соорудить на обычных классах только врукопашную, поэтому речь о closure и не шло. Теперь компилятор позволяет это сделать.
Ну надо же. Ж есть, а слова нет.
Это выражение на уровне синтаксиса. Как, например, есть шаблон функции на уровне синтаксиса. Только вот это лишь часть всей истории, отнюдь не самая главная.
О, надо же, до вас дошло.
А есть еще и само по себе "применение функтора", т.е. вызов operator(), который может занимать какое-то время и приводить к разным результатам.
И, проблема в общении с вами в том, что вы не можете вменяемо обозначить что из всего этого многообразия у вас называется "инстанс".
Лексическая роль пусть волнует разработчиков компиляторов, статических анализаторов и IDE. Мне, как простому пользователю языка, интересно то, чем лямбда является в итоге.
Здесь -- это где?
Лексическое замыкание делается компилятором. Но, при этом, в C++ оно так же специфическое, т.к. программист должен явным образом описывать что же именно (и как именно) он хочет "замкнуть".
Ну и добавим сюда, что в C++ лямбда может "замкнуть" не только что-то из объемлющего контекста, но и определить собственные "члены" в виде новых объектов, доступных только внутри лямбды (но не локальные переменные в теле лямбды). Вроде вот такого:
Еще раз: в C++ лямбда -- это экземпляр анонимного класса. Список захвата трансформируется в поля этого класса. Грубо говоря:
есть ни что иное как:
И как раз этот автоматически сгенерированный функтор и есть вполне себе нормальный ООП-шный объект (при условии, что вам достаточно только инкапсуляции из ООП-шной триады).
Поделитесь контактами поставщика вашей дури. Аж завидно.
В смысле инкапсуляции. Что есть один из трех "китов" ООП.
Если для вас непонятно, то речь идет о том, что в функциональном объекте есть свои члены, которые доступны из operator():
К содержимому fo.a_ и fo.b_ вы снаружи просто так не доберетесь. Что и есть инкапсуляция.
Ну ёжкинжеж...
В C++ уже давным давно есть устоявшийся термин "function object" (он же функтор -- functor). Вы его можете найти на том же cppreference. Или, например, здесь.
И да, ссылка на Wiki там сделана не для function object-а, а для closure.
Тот факт, что вы отрицаете применимость ООП к C++ными функторам... Ну тут у вас либо опять "горе от ума", либо вообще дефицит этого самого ума.
Вы тут уже пытались блеснуть цитатой:
Только вот это относится лишь к синтаксису описания лямбды.
Ну и, например, первая же строчка описания lambda-expression на cppreference.com говорит:
В теории.
На практике вы путаете теорию (возможно ведомую только лично вам) с практикой языка C++.
Еще раз вам повторю: лямбда в C++ -- это инстанс (т.е. экземпляр, т.е. объект) некоторого автоматически сгенерированного анонимного класса.
Поэтому с точки зрения C++ это ваше заумное "лямбда-выражение в контексте его вызова" -- это вообще что-то странное. Поскольку есть а) экземпляр лямбды и b) есть конкретный вызов лямбды (т.е. вызов operator() у экземпляра лямбды). И вот ХЗ что вы под "инстансом" понимаете.
Или в том, что взялся что-то объяснять вам.
Еще раз, для людей с проблемами развития и пониженной социальной ответственностью: вы используете термин "инстанс", у вас спрашивают что вы под этим понимаете, вы не можете дать вменяемое описание вашего использования термин "инстанс".
Мне не хочется "интуитивно понимать" о чем вы, мне хочется знать конкретно. А вы не можете "в конкретно". Но при этом одеваете на себя мантию величественного теоретика.
Тьфу, срамота.
А вы допустите. Типа "в случае традиционной реализации на стековой архитектуре это будет вызов со своим конкретным стековым фреймом". Этого могло бы быть достаточно.
Но, так понимаю, проста изложения мыслей и вы проживаете в разных вселенных.
Т.е. вышли
позвиздпокичиться своей ученостью?А вы не блудите мыслею по древу.
Вы дали ссылку на Wiki, в которой термин instance использовался для обозначения двух разных вещей. Так что от вас ожидалось хотя бы объяснение в каком именно смысле вы здесь, в этом обсуждении используете "инстанс". Но вы не смогли.
Вам -- не знаю. Для меня это еще одно доказательство того, что у вас с головой нелады. Ибо в данном разговоре достаточно определить "инстанс" -- это синоним экземпляра/объекта (типа "инстанс класса D" как "объект класса D") или же это "конкретный вызов конкретной функции в конкретным фрейм-стеком и конкретными значениями переданных параметров". Или же еще что-то.
Если вы не можете разговаривать на таком уровне, то я мог бы сказать, куда свою ученость вы могли бы засунуть из-за ее полной бесполезности. Но, боюсь, на Хабре не принято в прямой разговор.
Конечно, и только вы с высоты своих лет познали истину.
Ну да, ну да.
Нам бы о более приземленных вещах договориться, например: зачем все эти околотеоритические блуждания в комментариях к данной конкретной статье?
Но при этом не можете в ходе дискуссии сформулировать определение используемого вами же термина "инстанс".
И какой практический смысл в обсуждении "фундаментальных вопросов" в комментариях к сугубо утилитарной статье?
Если вы считаете, что в C++ используется какая-то "неправильная" терминология, а C++ники намеренно искажают какие-то устоявшиеся в некоторой теории понятия, то напишите статью с изложением вашей точки зрения и ссылками на работы, в которых эти самые "термины" и "понятия" вводятся.
Может от этого будет больше пользы.
Здесь же вы пока договорились лишь до того, что локальная переменная в теле метода класса является частью класса. Если "фундаментальные вопросы" в вашем понимании ведут к такому маразму, то может ну их вообще?
Простите, с этого момента я пас.
А то, что вы не определили смысл своего "инстанс" и говорить "мы в итоге договорились о терминологии" преждевременно.