?

Log in

No account? Create an account
программистское, замыкания - Поклонник деепричастий [entries|archive|friends|userinfo]
Anatoly Vorobey

[ website | Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| English-language weblog ]

программистское, замыкания [май. 1, 2016|02:47 am]
Anatoly Vorobey
[Tags|]

(эта запись может быть интересна только программистам)

Оказывается, в gcc уже черт знает сколько лет существуют замыкания в виде вложенных функций. Настоящие замыкания! Но только в C, в C++ они не работают (в C++ теперь есть лямбды, но это ж недавно).

А мужики-то и не знали! Если серьезно, я поражен.

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

Ладно, будем лямбды значит внедрять в народное хозяйство. Кстати, пару недель назад впервые написал настоящую лямбду в рабочем коде на C++.
СсылкаОтветить

Comments:
From: rezkiy
2016-05-01 12:19 am
а вам разве кодинг стандарт позволяет?
(Ответить) (Thread)
[User Picture]From: avva
2016-05-01 12:28 am
теперь позволяет. Но вообще не стоит ими злоупотреблять, по-моему.

P.S. Я написал пустое утверждение. Ничем не стоит злоупотреблять. Попытка придать ему значение: мне кажется, что не стоит создавать API, при использовании которых всегда напрашивается использование лямбд. Скажем, если я вызываю foo() и передаю ей callback, при вызове которого, чтобы сделать осмысленную работу, мне наверняка понадобятся локальные переменные, с помощью которых я соорудил вызов foo().

Edited at 2016-05-01 00:33 (UTC)
(Ответить) (Parent) (Thread)
[User Picture]From: solomon2
2016-05-01 02:01 am
Т.е. filter и map (à la Python) отпадают?
(Ответить) (Parent) (Thread)
[User Picture]From: nokachi
2016-05-01 04:02 am
У лямбды к тому же неизвестный программисту тип, так что тут без шаблонов и auto не обойтись, наверно.
(Ответить) (Parent) (Thread)
[User Picture]From: ulfurinn
2016-05-01 04:39 pm
Они замечательно превращаются в std::function.
(Ответить) (Parent) (Thread)
[User Picture]From: mtyukanov
2016-05-02 10:19 am
Это еще более странное утверждение.

Лямбды -- упрощенный синтаксис для создания анонимных функторов. Не стоит создавать API, принимающие функторы? А что вместо них? Сишные коллбэки в виде указателей на функцию и передачей замыканий через дополнительные аргументы? Это удобно только для интерфейса с ассемблером и си, имеет смысл в драйверах и т.п. В общем программировании удобнее принимать аргументом любой callable object, будь то функтор, лямбда, результат std::bind или std::function.

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

Я бы сказал, что появление лямбд увеличивает полезность кода, написанного с использованием callable objects. До C++11 всяческие for_each, find_if и т.п. использовались крайне редко, потому что тривиальный цикл написать проще, чем тривиальный функтор. Функторы писали только для особо сложных или особо частых использований, и то обычно лень было. Лямбды просты, и этим стали пользоваться.
(Ответить) (Parent) (Thread)
[User Picture]From: spamsink
2016-05-01 12:36 am
Мужики знали, но это была чисто gcc-шная фича, поэтому в реальной жизни плохо применимая.
(Ответить) (Thread)
[User Picture]From: ticklish_frog
2016-05-06 09:55 am
К сожалению, эта фича в реальной жизни привела к тому, что у нас, независимо от того, используем или нет эти вложенные функции, исполняемый стек. Причина в том, что эти функции хранятся в стеке, и должны быть вызываемыми, стек надо сделать исполняемым, если есть такие функции в исходном коде. Системы opt-in, чтобы компилятор аннотировал модули, для которых стек должен быть исполняемым, придумано поначалу не было, поэтому пришлось разрешить исполнение по умолчанию, и ввели аннотации по принципу opt-out. Потом, конечно, ввели и opt-in аннотации. Но до сих пор встречаются модули без аннотаций, которе, если попадают в результат при сборке, заставляют делать стек исполняемым, поскольку неясно, есть ли такие функции в модуле.

Вот тут подробно написано: http://www.airs.com/blog/archives/518
(Ответить) (Parent) (Thread)
From: (Anonymous)
2016-05-01 01:42 am
Ну ведь нельзя же так. Я пока читал чуть не испугался. Хотя это иллюстрирует что я ламер в gcc, не слежу за событиями.
(Ответить) (Thread)
[User Picture]From: amigofriend
2016-05-01 02:13 am
Надеюсь, скачет теперь востребованной.
(Ответить) (Thread)
[User Picture]From: niobium0
2016-05-01 05:49 am
too little too late.
(Ответить) (Thread)
From: rustler2000
2016-05-01 06:01 am

Так ведь struct _ { static int sum (....  все время работает

(Ответить) (Thread)
[User Picture]From: link0ff
2016-05-01 11:01 am
Интересный эффект: "If you try to call the nested function through its address after the containing function exits, all hell breaks loose."
(Ответить) (Thread)
[User Picture]From: avva
2016-05-01 11:14 am
Это то что я имел в виду под "они не сохраняют жизнь пойманным локальным переменным при выходе из функции".

Более серьезная имплементация делала бы одно из двух:
- копировала переменные, использованные во вложенной функции, для ее использования (так в лямбдах C++11)
- создавала именно эти переменные не на стэке, а в куче, и давала им жить после выхода из функции (это формально говоря не нарушает стандарт, я думаю, но реально слишком сильно нарушает сложившиеся конвенции, чтобы всерьез рассматривать эту возможность)
(Ответить) (Parent) (Thread)
[User Picture]From: certus
2016-05-02 12:46 pm
Языковое замечание: в русском языке слово «конвенция» означает исключительно «межгосударственное соглашение». На мой взгляд, в используемом контексте английское convention следует переводить как «традиция», «порядок вещей».
(Ответить) (Parent) (Thread)
[User Picture]From: vmozgutuman
2016-05-01 11:25 am
Насколько я понимаю в этих делах, замыкания в языках без сборщика мусора если и возможны, то бессмыслены.

Потому что замыкание, поинтер на который вы должны везде за собой таскать, ничем от обычного объекта не отличается.
(Ответить) (Thread)
[User Picture]From: mounwell
2016-05-01 02:58 pm
Анатолий, вам довелось писать на Go? Как впечатления?
(Ответить) (Thread)
From: selfmade
2016-05-02 05:29 pm
Следующий пост в моей ленте - http://nponeccop.livejournal.com/484286.html
(Ответить) (Thread)