mikeash.com pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html commentshttp://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsmikeash.com Recent CommentsFri, 29 Mar 2024 10:15:49 GMTPyRSS2Gen-1.0.0http://blogs.law.harvard.edu/tech/rssBalakrishann B - 2012-12-14 10:17:20http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsAutomatic return type deduction works for even complex code in c++. Probably it was fixed after this post. <br /><code> <br />&nbsp;&nbsp;auto ans = []{if(true) return 42; else return 43;}; <br />&nbsp;&nbsp;cout &lt;&lt; ans() &lt;&lt; endl; <br /></code>289ab6c43edefbb76eb86c520c22a9e1Fri, 14 Dec 2012 10:17:20 GMTAlex - 2012-02-25 16:28:38http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#comments@Iouri <br /> <br />There is one. It is called D. There's also Go which is to C like what D is to C++. Hope that makes sense.1de2406e489a6f88ea1f3d1a2d076f17Sat, 25 Feb 2012 16:28:38 GMTIouri - 2011-06-07 03:17:30http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsC++0x is making C++ even more complex. We need different system level programming language!e357263036d82940eee4ebe9e9539c12Tue, 07 Jun 2011 03:17:30 GMTextremeboredom - 2011-06-04 08:00:31http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#comments@DeadParrot: <br /> <br />That threw me for a second at first, I was expecting x to be reset again in the second block call. But I realised that the copy of x is being made at the time that the block was created, not each time it is called. So there are two x's, one for the main code block, and another which is shared between both runs of the lambda. <br /> <br />Hope that helps.c6f9dcf0edead231d9c004fc29bc091bSat, 04 Jun 2011 08:00:31 GMTDave G - 2011-06-04 07:56:28http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsNice read, I haven't really bothered to try and learn either language's approaches but this was a good place to start. I agree with foobaz that the C++ approach seems more independent of an API or framework, but I still prefer the simplicity of Apple's approach even if it does come with more overhead (it's more or less how I feel about Objective-C versus C++ anyway).c96b7bc024ef194710af64b3454e8a2dSat, 04 Jun 2011 07:56:28 GMTmikeash - 2011-06-03 21:51:21http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#comments<b>charles:</b> Thanks. For some reason, this post is just full of typos. Fixed. <br /> <br /><b>Bavarious:</b> Makes sense. I really hope something like this gets approved, blocks deserve to be widely available outside of Apple platforms.afb419942953c2964b69fed82dbb443bFri, 03 Jun 2011 21:51:21 GMTBavarious - 2011-06-03 21:15:03http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsFor the record, Apple’s latest (N1451) submission to ISO/IEC uses the term ‘closure’ because blocks in C refer to compound statements inside {}. I, for one, welcome this change, although N1451 tries to make a point for keeping the ‘block’ nomenclature.b70ffb21faec73d9fb875eff2563fff5Fri, 03 Jun 2011 21:15:03 GMTcharles - 2011-06-03 21:07:31http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsGreat write-up, thanks! <br />One more little typo 'performany' --&gt; 'perform any'af4f288ba7b99c9f62dc5815ff83115eFri, 03 Jun 2011 21:07:31 GMTJordy - 2011-06-03 20:06:30http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsI was going through Clang mailing list archives and found someone who very much wanted auto-conversion between blocks and lambdas. It's easy to write wrappers to do this, though you'd have to specialize for each argument list (or do some strong C++0x template-fu): <br /> <br /><code> <br />/*** All untested ***/ <br />// Lambdas to Blocks <br />typedef void (^simple_callback)(void); <br /> <br />simple_callback callableToBlock (std::function&lt;void()&gt; fn) { <br />&nbsp;&nbsp;return Block_copy(^{ fn(); }); <br />} <br /> <br /> <br />// Blocks to lambdas <br />class block_wrapper { <br />&nbsp;&nbsp;simple_callback block; <br /> <br />public: <br />&nbsp;&nbsp;block_wrapper (const simple_callback&amp; blk) <br />&nbsp;&nbsp;: block(Block_copy(blk)) {} <br /> <br />&nbsp;&nbsp;~block_wrapper () { <br />&nbsp;&nbsp;&nbsp;&nbsp;Block_release(blk); <br />&nbsp;&nbsp;} <br /> <br />&nbsp;&nbsp;void operator() () { <br />&nbsp;&nbsp;&nbsp;&nbsp;block(); <br />&nbsp;&nbsp;} <br />}; <br /> <br />std::function&lt;void()&gt; blockAsCallable (simple_callback block) { <br />&nbsp;&nbsp;return block_wrapper(block); <br />} <br /></code> <br /> <br />But it seems like it'd be really difficult to actually make things auto-convert while still respecting the reference counts, since <code>callableToBlock()</code> leaves a block with refcount 1. Maybe under GC it would work? (<code>blockAsCallable()</code> works as is, I think, as long as you don't have cycles.)377458838c320151f0680571c7ced613Fri, 03 Jun 2011 20:06:30 GMTmikeash - 2011-06-03 19:23:14http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsPassing by value is more consistent but can only work in C++, since doing it with lambdas really needs language support for pass-by-value semantics that are more complicated than memcpy. <br /> <br />Blocks don't really depend on NSAnything. Aside from the C level Block_copy and Block_release, the fact that they handle copy/retain/release/autorelease can be considered to be independent of NSObject, even if in practice they do descend from NSObject. As far as I know, NSObject inheritance isn't part of the actual API. (Although lots of people certainly do rely on it, and I've posted code that assumes it as well.) <br /> <br />In any case, whether you consider it to be good or bad, ObjC language features are becoming more and more tied to Cocoa. @property syntax assumes that retain/copy/release/autorelease are how you manage memory, message forwarding is now built on top of NSInvocation rather than the other way around, etc.08df1b4d9bbe3500b6fe22d7c122c578Fri, 03 Jun 2011 19:23:14 GMTfoobaz - 2011-06-03 19:06:03http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsI like the C++ memory management style better. I always thought the Obj-C style was clumsy because of how they start on the stack but must be copied onto the heap. The C++ method of passing by value is more consistent. <br /> <br />Also, unlike Obj-C blocks, C++ are independent of the API. Blocks depend on NSObject and NSCopying, constructs that seem too high level to be part of a fundamental language feature.83845ed5cd117bf2c52a0ba8c5075149Fri, 03 Jun 2011 19:06:03 GMTmikeash - 2011-06-03 18:32:58http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsThanks guys, I must have been asleep when I figured out the values for that snippet. It's fixed now.3464ee9d2929be22d4cf632ea7d491f2Fri, 03 Jun 2011 18:32:58 GMTAaron Ballman - 2011-06-03 18:29:54http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#comments<div class="blogcommentquote"><div class="blogcommentquoteinner">"In order to store them in variables, pass them to functions, or return them from functions, C++ templates or the C++0x auto keyword (which infers the type of a variable from the type of its initializer) must be used."</div></div> <br /> <br />You can use std::function to do this. For instance: <br /><code> <br />std::function&lt; void(int) &gt; my_func = [](int i) {}; <br /></code> <br />Be sure to #include &lt;functional&gt; so you can access std::function.1081e891a224049d52db04a396fbe2e8Fri, 03 Jun 2011 18:29:54 GMTRick - 2011-06-03 17:28:36http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsDeadParrot: <br /> <br />"wouldn't it print 43, 100 then 42, 100 then 43, 101? " <br /> <br />No. In lambda parameter declaration: <br /> <br />"auto lambda = [x, &amp;y]()..." <br /> <br />"x" is passed by value, while "y" is passed by reference.f83e909b00bca8aa187dd086773e3e74Fri, 03 Jun 2011 17:28:36 GMTJesper Särnesjö - 2011-06-03 16:31:17http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsActually, it prints: <br /> <br /><code>43, 100 <br />42, 100 <br />44, 101</code> <br /> <br />(Compiled with g++ 4.5.)6303eb56a15932bd04e04662e979b71aFri, 03 Jun 2011 16:31:17 GMTDeadParrot - 2011-06-03 16:02:44http://www.mikeash.com/?page=pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html#commentsIn the code block <br /><code> <br />&nbsp;&nbsp;&nbsp;&nbsp;int x = 42; <br />&nbsp;&nbsp;&nbsp;&nbsp;int y = 99; <br />&nbsp;&nbsp;&nbsp;&nbsp;auto lambda = [x, &amp;y]() mutable { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x++, y++; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d, %d\n", x, y); <br />&nbsp;&nbsp;&nbsp;&nbsp;}; <br />&nbsp;&nbsp;&nbsp;&nbsp;lambda(); // prints 42, 99 <br />&nbsp;&nbsp;&nbsp;&nbsp;printf("%d, %d\n", x, y); // prints 42, 100 <br />&nbsp;&nbsp;&nbsp;&nbsp;lambda(); // prints 43, 100! <br /></code> <br /> <br />wouldn't it print 43, 100 then 42, 100 then 43, 101? <br /> <br />x &amp; y are incremented before the print statement in the lambda function. The changes to x are forgotten but the changes to y remain.c14c6f0208cdf5a870d4a32d4ee7e06eFri, 03 Jun 2011 16:02:44 GMT