<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/friday-qa-2008-12-26.html comments</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Fri, 07 Aug 2026 12:12:56 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Psy| - 2009-01-07 23:09:23</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>I agree with Mikeash, you can't say MacRuby will ever replace Objective-C. Apple is essentially adding features to the language to make it more fun to code with but also to make it even more efficient.
&lt;br /&gt;The biggest problem of ObjC is that it's between two separate families... It's too high-level to seem suitable for resource-intensive processes, and it's too low-level to be as flexible as scripting languages.
&lt;br /&gt;So to me, those new features, instead of pushing the language to one side or the other, increases its range of action.
&lt;br /&gt;With blocks you're getting a high-level feature, a high-level abstraction allowing you to literally customize code written by others without being able to even see that code, but also a very low-level system as it is made to be as fast as normal functions.</description><guid isPermaLink="true">5b85c7d3385b2c602a6da288ca8de23f</guid><pubDate>Wed, 07 Jan 2009 23:09:23 GMT</pubDate></item><item><title>mikeash - 2009-01-05 05:07:31</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Honestly I see no indication that Ruby is causing Apple to do anything. I see no evidence in the community that MacRuby is gaining any real traction in becoming a mainstream development tool. These language bridges are great to have but it has always been the case, and will be for the forseeable future, that straight Objective-C programming accounts for the vast, vast majority of Cocoa programming.
&lt;br /&gt;
&lt;br /&gt;Furthermore, blocks are not "Ruby features", unless by "Ruby features", you just mean "features that Ruby happened to borrow from other languages while it was being designed". Might as well call them C++ or Java features if you're going to do that.</description><guid isPermaLink="true">7e5adb2ec15309cedf72af4e0a38bb77</guid><pubDate>Mon, 05 Jan 2009 05:07:31 GMT</pubDate></item><item><title>Paul Howson - 2009-01-05 04:14:36</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>I wonder if the MacRuby project is one of the reasons Apple is adding blocks to Objective-C? My guess is it won't be too long before Ruby becomes the preferred language for Cocoa development. After 25 years Objective-C is &lt;b&gt;looking&lt;/b&gt; rather clunky. A Ruby front-end onto the Cocoa and Objective-C runtime sounds sweet. Is this why Apple is quietly adding Ruby features to Objective-C?</description><guid isPermaLink="true">e8d3e91f38aeb67b5e09314c5d928db9</guid><pubDate>Mon, 05 Jan 2009 04:14:36 GMT</pubDate></item><item><title>mikeash - 2009-01-04 10:38:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Well obviously we all have our opinions, and mine is that my statement was one of opinion, not fact. Thus your refutation was nonsensical and annoying.
&lt;br /&gt;
&lt;br /&gt;I welcome your continued contribution of ideas and differing opinions, but if you're going to persist in calling my opinions wrong and carrying on arguments long after they've reached their sell-by date I will have to ask you to refrain from posting.</description><guid isPermaLink="true">d0ce39bc6f48a8fee91b0beb4f0d6675</guid><pubDate>Sun, 04 Jan 2009 10:38:10 GMT</pubDate></item><item><title>Marcel Weiher - 2009-01-04 10:12:31</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Mike, you're not relaxing!  I am not being in the least bit silly: when you say "HOM is essentially a poor man's substitute for blocks", then you are making a claim that is false.  This is not what HOM *essentially* is, and I gave you the background to help you understand what that essence is.
&lt;br /&gt;
&lt;br /&gt;As a matter of fact, that essence is not even achievable with blocks, so saying that HOM is essentially a poor man's substitute for blocks is not just false, it is almost non-sensical.
&lt;br /&gt;
&lt;br /&gt;Similarly, if "GPS Enthusiast" were to evaluate the iPhone and say that an iPhone is "essentially a poor man's substitute for a real GPS receiver", then I would not have qualms with their saying that a "real" GPS receiver makes for a better GPS unit, but I would object to any claims that that is what an iPhone "essentially" is.  It does a lot of other things, and does things differently, because the aims of the developers of the iPhone (and its GPS capabilities) were different from those of a GPS receiver.
&lt;br /&gt;
&lt;br /&gt;I hope that makes things clear.
&lt;br /&gt;
&lt;br /&gt;Cheers,
&lt;br /&gt;
&lt;br /&gt;Marcel
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">1005513d71edfe44673fd14fa3a50620</guid><pubDate>Sun, 04 Jan 2009 10:12:31 GMT</pubDate></item><item><title>mikeash - 2009-01-01 07:16:57</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Marcel, please stop being so silly. I'm not being defensive at all. I didn't get any relationship wrong. There is a big difference between "HOM was created as a poor man's substitute for blocks" (which is what you're criticizing) and "HOM is a poor man's substitute for blocks" (which is pure opinion and which is what is actually said).
&lt;br /&gt;
&lt;br /&gt;You're perfectly entitled to your opinion about HOM and blocks and I have no real problem with people who think that blocks don't survive on their own merits. What I do have a problem with is someone criticizing me for "getting [something] wrong" when I have merely stated an opinion. If you persist in thinking that I have gotten something wrong then please quote the wrongness verbatim and explain it. However you will find that I have merely stated my opinion as to the merits of each, and never stated any factual information (right or wrong) about the origins of HOM or its relationship with blocks.</description><guid isPermaLink="true">8c8212593bc31f69b80962c2b16c23f9</guid><pubDate>Thu, 01 Jan 2009 07:16:57 GMT</pubDate></item><item><title>Anonymous - 2009-01-01 06:52:11</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Kind of along the idea of callbacks, blocks can also be used for observing notifications via NSNotificationCenter.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Mike Ash&lt;/b&gt; clever spam-filtering system. I'll have to steal it.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Everyone&lt;/b&gt; Happy New Year (soon)!</description><guid isPermaLink="true">38d9be3aeb09de1f0f75ec69d0980d36</guid><pubDate>Thu, 01 Jan 2009 06:52:11 GMT</pubDate></item><item><title>Marcel Weiher - 2009-01-01 06:39:17</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Relax, Mike! :-)   There's no need to get defensive about getting the relationship between blocks and HOM wrong.   It is an extremely common mistake because the connection seems so obvious and the disquiet with blocks is rather subtle, overshadowed by their tremendous utility.
&lt;br /&gt;
&lt;br /&gt;In fact, I pretty much made the same mistake, dismissing my discomfort with blocks as an &lt;i&gt;obvious&lt;/i&gt; symptom of inventor's pride.  It was only gentle but insistent nagging over many years (Hi Philippe!) that got me to finally consider publishing the paper linked above.
&lt;br /&gt;
&lt;br /&gt;I do have one big ally in my discomfort with blocks: 
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;
&lt;br /&gt;But later I decided I didn't like blocks as values because they are 
&lt;br /&gt;super time bombs when passed around and completely violate 
&lt;br /&gt;encapsulation. I really wanted external objects (not internal blocks) 
&lt;br /&gt;to be passed around, and wanted a simpler way to think of contexts 
&lt;br /&gt;internally. So we left them out of the first few Smalltalks. (I still 
&lt;br /&gt;don't like them ...)
&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;&lt;i&gt; &lt;a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2007-September/120493.html"&gt;http://lists.squeakfoundation.org/pipermail/squeak-dev/2007-September/120493.html&lt;/a&gt;&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;While he may be just as wrong as the idiot (that would be me), I do believe Alan is hard to dismiss as just being ignorant on the matter.
&lt;br /&gt;
&lt;br /&gt;Happy New Year!
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">0dea3279bd6481002743e96466698c06</guid><pubDate>Thu, 01 Jan 2009 06:39:17 GMT</pubDate></item><item><title>mikeash - 2009-01-01 00:07:37</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>See, I knew the guy who invented HOM would disagree with me.
&lt;br /&gt;
&lt;br /&gt;Note that I never talked about why HOM was invented, only what it is, and that most certainly &lt;i&gt;is&lt;/i&gt; a matter of opinion. Marcel, you could do with being a bit less combative on this sort of thing, it will give you a better chance at recruiting people....
&lt;br /&gt;
&lt;br /&gt;As for the rest, I shall let it stand. Of course I disagree, but I think all of my points have already been adequately made. I certainly encourage everyone to read the linked PDF, as it's very interesting, and if you aren't already familiar with HOM it will teach you some good things.</description><guid isPermaLink="true">733d6c3958895e4610efc7662974ccca</guid><pubDate>Thu, 01 Jan 2009 00:07:37 GMT</pubDate></item><item><title>Marcel Weiher - 2008-12-31 16:57:21</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Yes, if you think that HOM was just invented as a poor man's substitute for blocks, then it would be redundant now.  You would be wrong, of course, because that was not how HOM came about, and that's not a matter of opinion, but of fact.
&lt;br /&gt;
&lt;br /&gt;While HOM was invented to solve the same kinds of problems that blocks solve, my inspiration were ideas such as Backus's FP and APL, not blocks, which I actually found rather distasteful.
&lt;br /&gt;
&lt;br /&gt;Why distasteful?  It's difficult to explain, but distaste really best describe how it felt having to deal with (name, proces, return) individual elements after previously just dealing with entire collections in one fell swoop.  It's just a lower-level of abstraction.
&lt;br /&gt;
&lt;br /&gt;Blocks are undeniably the more powerful construct, just like goto is more powerful than structured constructs such as if, for and while.  There are also some legitimate applications such as nested HTML generation in Seaside that don't seem to be doable with HOM, or at least I haven't been able to figure it out yet.
&lt;br /&gt;
&lt;br /&gt;Just as undeniable, though, is the fact that HOM-based code can do things that blocks can't do, and is frequently even more concise and readable, giving you even better abstraction abilities than blocks do without some of the inherent drawbacks, such as a strong incentivizing of very, very badly structured code.
&lt;br /&gt;
&lt;br /&gt;And of course the typing issues are purely a factor of HOM implementations to date not having any compiler support, they would be solvable with a fraction of the infrastructure required by the block implementation.
&lt;br /&gt;
&lt;br /&gt;For more details, see:
&lt;br /&gt;&lt;a href="http://www.metaobject.com/papers/Higher_Order_Messaging_OOPSLA_2005.pdf"&gt;http://www.metaobject.com/papers/Higher_Order_Messaging_OOPSLA_2005.pdf&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">992491278d6a2ac137fa53aae06a9901</guid><pubDate>Wed, 31 Dec 2008 16:57:21 GMT</pubDate></item><item><title>Jens Alfke - 2008-12-29 02:41:37</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>@Rolf: I think your claim (about closures being a type of feature that is "an utter disaster for real world software engineering projects") has long since been disproven. Modern web frameworks like Ruby On Rails and Django use the block/closure features of the underlying Ruby/Python languages pretty heavily, and these systems have definitely proven themselves in real-world use.
&lt;br /&gt;
&lt;br /&gt;(Back in the mid-'80s I was working on productivity apps in Smalltalk-80, one of the ancestor languages of both Ruby and Objective-C, and it definitely made for very quick and readable code.)
&lt;br /&gt;
&lt;br /&gt;Consider that any language feature you're not used to will seem confusing and hard to read at first. That's just the nature of learning. I can assure you that blocks/closures are quite readable, and lead to extremely clear and concise code if they're used correctly. Of course you can do crazy stuff with them (and there are a few APIs in Rails that I think go too far that direction) but that's true of anything powerful...</description><guid isPermaLink="true">69ecc422a5c9cdf5415b4e6de5854a95</guid><pubDate>Mon, 29 Dec 2008 02:41:37 GMT</pubDate></item><item><title>mikeash - 2008-12-29 00:19:09</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;b&gt;David Stewart Zink:&lt;/b&gt; Like virtually any language feature, blocks will certainly be open to abuse. I don't think that, by itself, is reason to fear it. The question is whether it &lt;i&gt;will&lt;/i&gt; be "abused" by a lot of people (or in other words, will there be wide-scale disagreement over where they are appropriate and where they are not) and whether the utility outweighs that. I see a lot of utility and not a lot of potential for abuse. Other languages which have closures, inline functions, and anonymous functions don't tend to suffer from too much abuse, although certainly you do see it from time to time.
&lt;br /&gt;
&lt;br /&gt;As for your question with the qsort example, I'm not sure I understand what you're asking that hasn't already been answered several times in the comments above. If you mean literal qsort, which takes a function pointer rather than a block, then the answer is no, you cannot do this. Block pointers are conceptually similar to function pointers but implementation-wise are completely different. You couldn't pass a block to the built-in qsort function. What you could do is write an adapter, say qsort_block, which would then call through to the built-in qsort_r with a comparator that calls through to your block. Then your example would work, using qsort_block instead of qsort.
&lt;br /&gt;
&lt;br /&gt;As for type inference, if Apple is smart they are requiring &lt;i&gt;identical&lt;/i&gt; return types, not merely compatible ones, and are erroring out (or at least putting up a very loud warning) if you have multiple return statements which don't match. If you want to return different types and have them be converted, you should either have to declare an explicit return type (the inference thing is optional) or explicitly cast enough of your return statements to make them all match. I don't know if that's how it works but that is how it ought to work.</description><guid isPermaLink="true">9e1405f1a8a99465052483feb1b4dfb1</guid><pubDate>Mon, 29 Dec 2008 00:19:09 GMT</pubDate></item><item><title>David Stewart Zink - 2008-12-28 16:26:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>I see a few things here, to split off the first one: "anonymous functions".
&lt;br /&gt;
&lt;br /&gt;I.e.
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;^{ return 1; }
&lt;br /&gt;versus
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;static int one() { return 1; }
&lt;br /&gt;
&lt;br /&gt;Great for hacking, perhaps nice when stuffed inside fancy header files, but in general it means a great deal more ad-hoc code that probably ought to be reusable and reused but isn't. In a way it's the equivalent of using a number instead of a manifest constant.
&lt;br /&gt;
&lt;br /&gt;more interesting: the closure thing, using variables from enclosing scope.  Is there an easy way to do more real closures, i.e. the equivalent of:
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;qsort(base, nel, width, ^(const void *l, const void *r) { return memcmp(l, r, width); });
&lt;br /&gt;like you would get with some languages:
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;qsort(base, nel, width, memcmp(,,width));
&lt;br /&gt;
&lt;br /&gt;I'm a bit worried about the "infers type of function)" thing. Obviously, it's usually passed as a function pointer to something that defines what type it takes, so the compiler just has to confirm that the anonymous function matches the prototype. But there are weird corner cases I suspect it's hard to reason about with conviction.
&lt;br /&gt;
&lt;br /&gt;enum Alignment { Short, Integer, Long };
&lt;br /&gt;static short shortArr[10];
&lt;br /&gt;static int intArr[10];
&lt;br /&gt;static long longArr[10];
&lt;br /&gt;
&lt;br /&gt;x = ^(Alignment a) { switch(a) { case Short: return shortArr; case Integer: return intArr; case Long: return longArr; } return 0; }
&lt;br /&gt;
&lt;br /&gt;arguably x returns void* and casts the 0 to NULL, but my real question is: how smart is the compiler? How smart do we want?
&lt;br /&gt;
&lt;br /&gt;int * getInts() { return x(Integer); }
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">510689f3c57335d68de3bde65d8fa2a3</guid><pubDate>Sun, 28 Dec 2008 16:26:27 GMT</pubDate></item><item><title>mikeash - 2008-12-28 13:04:15</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;b&gt;Rolf Howarth:&lt;/b&gt; I don't buy your argument, because unless you program using raw machine code, it is self-defeating. "Clever hacks" like assembly language, high-level programming languages, and object-oriented programming have driven the industry. A modern programmer is vastly more productive than one who had to work purely in machine code precisely because of the tools he is able to use.
&lt;br /&gt;
&lt;br /&gt;The expressiveness of a language is &lt;i&gt;extremely&lt;/i&gt; important. When you can do more work and express more meaning with less code that means that you can spend more time thinking about what your program does and less about the boring details of how it does it. Programming is all about automating boring tasks to make people more productive. If we want to make ourselves more productive, then getting the machine to automate &lt;i&gt;our&lt;/i&gt; boring tasks is the way to do it.
&lt;br /&gt;
&lt;br /&gt;I understand if you don't think closures are important. Opinions differ. But a wholesale rejection of all language additions and features as being only for academics and people who don't write real software is an idea which I reject in the strongest possible terms!
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Anonymous:&lt;/b&gt; Good point mentioning HOM. HOM is essentially a poor man's substitute for blocks/closures/whatever. (The guy who invented HOM will disagree with me and say that HOM is often better, but we're all entitled to our opinions.) HOM is fairly limiting and in Objective-C doubly so due to the primitive/object type disconnect, and blocks pretty much completely remove the need for HOM by providing a more generalized solution that enables even more and better capabilities.</description><guid isPermaLink="true">1dec124c7423b8559be4db7b1bfe1b03</guid><pubDate>Sun, 28 Dec 2008 13:04:15 GMT</pubDate></item><item><title>Rolf Howarth - 2008-12-28 08:12:56</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>@David: Well, I do know what a closure is, and I know there are problems for which they're a very elegant solution, but a lot of bitter experience over the years has taught me that it's often best not to try to be too clever! :-)
&lt;br /&gt;I don't have anything specifically against closures as such, it's the general tendency of people to keep trying to invent clever hacks and extensions that I'm suspicious of. If you introduce a new framework or bit of technology to save you 5 minutes' work and then need to spend a week fixing some obscure deployment issue or memory leak as a result then it's not a sensible trade off!</description><guid isPermaLink="true">59674c25181a9f4c6251e2a819de55d8</guid><pubDate>Sun, 28 Dec 2008 08:12:56 GMT</pubDate></item><item><title>Anonymous - 2008-12-28 07:13:42</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>@Karsten
&lt;br /&gt;
&lt;br /&gt;Thinking of Objective-C variables as separate from C isn't exactly accurate. Essentially "id" variables (or Objects) are just C pointers, and as such can be passed around just like a float, int, or char*, et al.</description><guid isPermaLink="true">9df94b992769103ab0ea9289d0439b57</guid><pubDate>Sun, 28 Dec 2008 07:13:42 GMT</pubDate></item><item><title>Chuck - 2008-12-28 06:53:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>@Karsten:
&lt;br /&gt;
&lt;br /&gt;Earlier in the comments, Johannes Fortmann mentioned that as currently implemented, blocks behave as objects in Objective-C, but only respond to -copy and -release. You already can tell a block to execute with certain arguments, though:
&lt;br /&gt;
&lt;br /&gt;multiplyByFive = ^(int toMultiply){return toMultiply * 5};
&lt;br /&gt;int theNumber = multiplyByFive(10); // and theNumber is 50!</description><guid isPermaLink="true">944eb98cb7f9acdd8addbcc62c996b83</guid><pubDate>Sun, 28 Dec 2008 06:53:44 GMT</pubDate></item><item><title>Karsten - 2008-12-28 06:38:19</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>What i've forgotten to mention when i replied yesterday: are there Objective-C blocks? Or only c-blocks? The reason I ask is that it'd be nice to have a block as an object, so that you can send messages to it.  Like telling blocks to evaluate with a certain set of arguments or something.
&lt;br /&gt;
&lt;br /&gt;Will there be a reflection api for blocks? Like asking blocks for there number of arguments etc?</description><guid isPermaLink="true">4090983f655e8557049a2380491cc36d</guid><pubDate>Sun, 28 Dec 2008 06:38:19 GMT</pubDate></item><item><title>Anonymous - 2008-12-28 05:35:02</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>This can do a lot to reduce LOC without straying from the "every line tells" philosophy of Cocoa/ObjC, and that will be wonderful.
&lt;br /&gt;
&lt;br /&gt;But even more importantly, as Mike mentioned, this allows for clearer code to be written. Specifically, when reading this article, I was reminded of KBCollectionExtensions, a very nifty HOM implementation for Cocoa written in February by Guy English (yet another amoebian).
&lt;br /&gt;
&lt;br /&gt;Using KBCollectionExtensions is nifty because it cleans up code clutter without sacrificing the "every line tells" idea. Specifically, having taken this example right off of Guy's blog, this would be the code to enumerate an array named allEmployees and return the names of any employees who have been idle for more than 5 minutes:
&lt;br /&gt;
&lt;br /&gt;NSArray *names = [allEmployees valueForKeyPath: @"[collect].{idleTime&amp;gt;5}.name"];
&lt;br /&gt;
&lt;br /&gt;This is a nifty implementation, but can be redone in blocks without swizzling out the NSObject class and overriding -valueForKeyPath: which to me, is very exciting!</description><guid isPermaLink="true">abf4962d25cd63d9a265c609ca503244</guid><pubDate>Sun, 28 Dec 2008 05:35:02 GMT</pubDate></item><item><title>David Smith - 2008-12-28 05:33:20</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Rolf: as requested: you're a luddite ;)
&lt;br /&gt;
&lt;br /&gt;Closures are not a loop replacement. If that's all they were then you'd be right. Read the rest of the examples, there's a ton of stuff there besides loops.
&lt;br /&gt;
&lt;br /&gt;Also I don't know what you mean by the questions you ask. Closures *avoid* that by putting the code inline, so you *don't* need to go hunting around for definitions.
&lt;br /&gt;
&lt;br /&gt;Calling it a "new" feature is also a bit silly; closures are decades old, and almost every higher level language has them these days (ruby, python, javascript, any functional language, C#, java is getting them, etc...).</description><guid isPermaLink="true">bf7b07e623566e2a1a2869518543ae9b</guid><pubDate>Sun, 28 Dec 2008 05:33:20 GMT</pubDate></item><item><title>Rolf Howarth - 2008-12-28 04:32:20</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Hmm, call me a Luddite if you like, but I'm far from convinced that adding clever new features and syntax to a language is a good way to improve either programmer productivity or code reliability.
&lt;br /&gt;
&lt;br /&gt;The important thing is code legibility - being able to look at a line of code and know immediately and unambiguously exactly what it's going to do. If you need to keep asking yourself questions like "what does that extension do", "where's that defined", or "was the behaviour of this construct that I understand overridden in some other file to do something completely different here" then that introduces so many obscure and difficult to track down bugs that it far, far outweighs any benefit it might bring in the short term.
&lt;br /&gt;
&lt;br /&gt;Things like this are great for academic computer scientists and people trying to prove how clever they are, but an utter disaster for real world software engineering projects with a steady stream of different people joining and leaving the team.
&lt;br /&gt;
&lt;br /&gt;There are lots of things that limit my productivity as a developer but the extra typing time it takes to write out a loop long hand sure isn't one of them!</description><guid isPermaLink="true">c502821882c76a1d1ccd6f6e879f14c4</guid><pubDate>Sun, 28 Dec 2008 04:32:20 GMT</pubDate></item><item><title>mikeash - 2008-12-28 02:11:06</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;b&gt;raffy:&lt;/b&gt; From what the mailing list post says, that code will not compile, because it's not legal to mutate auto variables from the enclosing context. However if you rewrote your variable declaration like so:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;__block int t = t0;&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;Then your code would compile and would print 10 followed by 11.
&lt;br /&gt;
&lt;br /&gt;This requirement for an extra type decorator is kind of annoying but it seems that it's done for efficiency reasons, as it sounds like block-mutatable variables are considerably more expensive than const-copied ones.</description><guid isPermaLink="true">5cf47e2e15afcbc1566cf5619b227ebc</guid><pubDate>Sun, 28 Dec 2008 02:11:06 GMT</pubDate></item><item><title>raffy - 2008-12-28 01:46:51</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>are the closure environments mutable? 
&lt;br /&gt;
&lt;br /&gt;(int (^)) newCounter(int t0) {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;int t = t0;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;return ^{ return t++; };
&lt;br /&gt;}
&lt;br /&gt;
&lt;br /&gt;x = newCounter(10);
&lt;br /&gt;printf("%d", x()); // 10?
&lt;br /&gt;printf("%d", x()); // 10 or 11?</description><guid isPermaLink="true">fd522de4e76d5e377468cb01a3fa8431</guid><pubDate>Sun, 28 Dec 2008 01:46:51 GMT</pubDate></item><item><title>mikeash - 2008-12-28 00:17:34</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;b&gt;iphone dev:&lt;/b&gt; I'm afraid I still don't understand what you're asking. Are you asking if we can pass a block to a method which takes a SEL/id pair? If so, then no, we can't. A method must be explicitly written to take a block.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Grady:&lt;/b&gt; No, why would I use NSApplication? The method I'm using is an instance method, not a class method. Using NSApplication would result in a compiler warning and a runtime error because I'm trying to send this message to the class. And no, the method name is exactly what I want it to be. Perhaps you're reading in the documentation and they mention a callback method called "sheetDidEnd:", but that's just a model. The whole point of the SEL argument is to be able to specify a method of your choice.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;tedge:&lt;/b&gt; The copy/release is not an omission on my part, because it would happen inside Cocoa. Any API which is going to keep a block past the current function call is going to copy it internally, rather than force callers to copy it. As for retaining objects, I'd say you're right about that except that the next post claims that the runtime does this for you, which is neat. If that's true than my code will work 100% as-is, assuming an appropriately written NSApplication method of that particular name.</description><guid isPermaLink="true">4004f50183f8862766e851e75fc88a11</guid><pubDate>Sun, 28 Dec 2008 00:17:34 GMT</pubDate></item><item><title>Johannes Fortmann - 2008-12-27 21:02:55</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>The llvm-gcc source already contains an (in-flux) block implementation; so it's possible to answer many of these questions: 
&lt;br /&gt;- the type of a block is like the type of a corresponding function pointer, but with the * replaced by a ^. So (id (*)(id)) (a function taking an id and returning an id becomes (id (^)(id)).
&lt;br /&gt;wtd's type would be (void (^)(void))
&lt;br /&gt;- in Objective-C, the type of a block is also id. That means you can send it messages (but only -copy and -release).
&lt;br /&gt;- if you want to keep a block that's been passed to you, you'll have to send it a -copy message. That's like any other Objective-C object.
&lt;br /&gt;- The block knows which objects are accessed in it, and will retain/release them in its -copy/-dealloc method.
&lt;br /&gt;- function-local blocks start out as light-weight stack objects and get promoted to regular heap objects on -copy. Global blocks (i.e. those assigned to global variables) remain global; they're like static NSStrings in that regard.
&lt;br /&gt;- variables accessed from within a block have pass-by-value semantics normally, and pass-by-reference semantics if declared with __block. That means that all instances of the block as well as the current stack scope share the same variable; it will be transparently moved to the heap if one of the blocks survives the current stack scope.</description><guid isPermaLink="true">ea75653e36abcd2e624bd4e8dd87dc51</guid><pubDate>Sat, 27 Dec 2008 21:02:55 GMT</pubDate></item><item><title>tedge - 2008-12-27 19:03:30</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Thanks for the informative post on blocks! One minor issue: If blocks were somehow able to be used in place of callback methods, it seems they'd be a bit more complex than what's shown in the beginSheet example.
&lt;br /&gt;
&lt;br /&gt;First, the callback block most likely won't get called until after the stack frame where it's defined has been released. In this case (according to Lattner's post), the block needs to be saved to a global using _Block_copy() and later released using _Block_release().
&lt;br /&gt;
&lt;br /&gt;Second, any local objects the block will access (NSString* bar in the example) need to be retained, since the block is unlikely to be called before the autorelease pool is refreshed.</description><guid isPermaLink="true">d0efcf5d8b1be721ae2349975eb4548b</guid><pubDate>Sat, 27 Dec 2008 19:03:30 GMT</pubDate></item><item><title>wtd - 2008-12-27 17:34:23</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>One question remains in my mind: what is the type of "x" in the following?
&lt;br /&gt;
&lt;br /&gt;x = ^{ printf("a block called x.\n"); };</description><guid isPermaLink="true">04917cc161e07646f5bd7365b4e9f0c1</guid><pubDate>Sat, 27 Dec 2008 17:34:23 GMT</pubDate></item><item><title>Grady - 2008-12-27 14:26:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Mike: "NSApplication", not "NSApp" as the article says.
&lt;br /&gt;
&lt;br /&gt;And methodSheetDidEnd:returnCode:contextInfo: should be sheetDidEnd:returnCode:contextInfo:, right? Just wanting to make sure I understand this correctly.</description><guid isPermaLink="true">91cbdae445604693476fffc5f4c5ad93</guid><pubDate>Sat, 27 Dec 2008 14:26:10 GMT</pubDate></item><item><title>iphone dev - 2008-12-27 13:20:37</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>we can pass arguments to a selector method by either (id) sender or setRepresentedObject: , so i believe if we need a more flexible selector method e.g. sorting using different criteria, we can pass the different sorting 'block'  by setting them as the representedObject -- can we ?</description><guid isPermaLink="true">856f221319eb2f87f9e0ceb95222da47</guid><pubDate>Sat, 27 Dec 2008 13:20:37 GMT</pubDate></item><item><title>mikeash - 2008-12-27 12:18:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;b&gt;Foo:&lt;/b&gt; Actually it's quite clear what that would do, if you read the mailing list message linked at the bottom of my post. Your example will print "a is 42 and b is fork!" twice. While many details are incomplete or in flux, the fact of local variable capture is pretty clearly explained in that post.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;iphone dev:&lt;/b&gt; No idea what you mean by "pass a block as an argument to a selector", I'm afraid. A selector is just a way to identify the name of a message in a fast way. It doesn't have arguments. Did you mean can you pass a block as an argument to a method? If so, I'd hope that my examples make it abundantly clear that you can. Otherwise if you can rephrase your question I will do my best to answer it.</description><guid isPermaLink="true">3d617e4c14ca2ce506887f8fea17c7d6</guid><pubDate>Sat, 27 Dec 2008 12:18:40 GMT</pubDate></item><item><title>iphone dev - 2008-12-27 12:02:24</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Thanks for introducing the blocks to objective-c community in a bit more detailed way. The "map" method example greatly simplifies the concept. Can we pass a 'block' as an argument to a selector ?</description><guid isPermaLink="true">f68c2e0044ef08794eeeb07cc735b860</guid><pubDate>Sat, 27 Dec 2008 12:02:24 GMT</pubDate></item><item><title>Foo - 2008-12-27 11:53:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;
&lt;br /&gt;sitharus, how are they not true closures?
&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;It's not clear what this would do:
&lt;br /&gt;
&lt;br /&gt;void foo()
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int a = 42;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char *b = "fork!";
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x = ^{ printf("a is %d and b is %s", a, b); }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;store(x);
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;
&lt;br /&gt;void bar()
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a = 9;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char *b = "if you see this, it's not a closure";
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x();
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;
&lt;br /&gt;void baz()
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x();  // will this bomb if a and b aren't on the stack?
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;
&lt;br /&gt;foo();  bar();  baz();
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;Awesome post, and it really shows what we obj-c guys have been missing for so long that all the ruby boys have had for years.&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;Or that Lisp has been having for over half a century.  Here's a dime kid.  Go get yourself a better programming language.
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">e483356856f1d59412620e61203d6285</guid><pubDate>Sat, 27 Dec 2008 11:53:10 GMT</pubDate></item><item><title>mikeash - 2008-12-27 11:49:47</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Great response this week, wow!
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Karsten:&lt;/b&gt; The return statement only returns an object from the block. In this respect, the block fails to work exactly like a built-in control construct. It's impossible to return from the enclosing method from block code. This is unfortunate but, in my opinion, not particularly limiting. It's something you'll have to be aware of and ensure you work with in your code.
&lt;br /&gt;
&lt;br /&gt;Given the way blocks work, I think you can see that it must be this way. You can pass a block off and it can get copied and invoked later, potentially multiple times. What would it mean to return from the enclosing method from inside a block, when the block is executing ten minutes after the enclosing method finished executing? They're more general purpose, so ironically they lose this capability.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;charles:&lt;/b&gt; Thanks very much for your praise and your typo-finder. I've fixed it.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Jonathan:&lt;/b&gt; The reason I didn't mention closures is because I don't really fully understand what sets apart a closure from all the other stuff we can have, and I was sure that the moment I mentioned the idea I'd get people like &lt;b&gt;sitharus&lt;/b&gt; coming in and telling me that they aren't really closures. I have no idea which one is right. Honestly I don't care. I just want to know how they work and what I can do with them. What the theoretical construct is called is less interesting.
&lt;br /&gt;
&lt;br /&gt;To everyone else, thanks much for writing. Don't forget to keep those suggestions coming, This stuff has sparked such great conversation that I want to be sure to keep it going! I have material for a few more already, but more is always better.</description><guid isPermaLink="true">e41a1c251c2a7bf1dc0df3899584159a</guid><pubDate>Sat, 27 Dec 2008 11:49:47 GMT</pubDate></item><item><title>Joachim Bengtsson - 2008-12-27 07:12:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Oh god, I'm giddy like a child on christmas eve! I could hardly believe my ears when I heard it the first time, and I feel the same way every time I hear or read it again; finally! Blocks/closures were the final thing missing from ObjC to make it the perfect low-level language, imo. Blocks are what make Ruby such a wonderful language, and I miss them every day when I code ObjC. A proper -map: and -reduce:, for example, would be so very useful.
&lt;br /&gt;
&lt;br /&gt;Blocks go so well together with Cocoa, too! Almost every place where we today use a delegate or callback, a block would do just as nicely or even more so. They'll also make for some beautiful parallel code, as you touch on with -doParallelized:.
&lt;br /&gt;
&lt;br /&gt;sitharus: They *are* true closures. They're doing some very fancy magic.
&lt;br /&gt;
&lt;br /&gt;One note though, blocks aren't an ObjC feature; they can be used in .c files as well, afaik.</description><guid isPermaLink="true">9bf7c9a5c0e875c5a2b34a16263f8939</guid><pubDate>Sat, 27 Dec 2008 07:12:44 GMT</pubDate></item><item><title>cc - 2008-12-27 07:10:39</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>sitharus, how are they not true closures?</description><guid isPermaLink="true">e389cb1fcbc3c7735576de54041b3b65</guid><pubDate>Sat, 27 Dec 2008 07:10:39 GMT</pubDate></item><item><title>Steven W Riggins - 2008-12-27 06:43:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>For those more curious about blocks and want to play now, check out Squeak, a Mac Smalltalk at &lt;a href="http://www.squeak.org/"&gt;http://www.squeak.org/&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;Paste the smalltalk below into a workspace (command k), select an example (all 3-4 lines each) and press command-d to "do it" (which by the way was the original OK button in Mac OS but people read it as 'dolt' so they changed it to OK)
&lt;br /&gt;
&lt;br /&gt;Blocks are wrapped in brackets [].  "[:value" defines a parameter for the block named value, then a | to separate the parameters from the code.
&lt;br /&gt;
&lt;br /&gt;"Begin Smalltalk"
&lt;br /&gt;
&lt;br /&gt;"Example 1: Pass block to do: method of any collection"
&lt;br /&gt;"This rocks because you can pass any block of code around and never write an iteration loop again"
&lt;br /&gt;total := 0.
&lt;br /&gt;{1. 2. 3. 4. 5.} do:[:value | total := total + value].
&lt;br /&gt;total inspect.
&lt;br /&gt;
&lt;br /&gt;"Example 2: get the value of a block"
&lt;br /&gt;blockExample := ['hello ','world'].
&lt;br /&gt;blockExample value inspect.
&lt;br /&gt;
&lt;br /&gt;"Example 3: Use a block to detect an object in a collection.  Can resuse block with different values for a scoped local variable"
&lt;br /&gt;detectString := 'hello world'.
&lt;br /&gt;detectExample := [:value | value = detectString].
&lt;br /&gt;detected := {'oh my'. 'wow!'. 'hello world'} detect: detectExample.
&lt;br /&gt;detected inspect.
&lt;br /&gt;
&lt;br /&gt;"Now this will cause an error because no match was found.  (detect: ifNone: is how you handle this case"
&lt;br /&gt;detectString := 'hello there'.
&lt;br /&gt;detected := {'oh my'. 'wow!'. 'hello world'} detect: detectExample.
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">56fcf9e6a094a6d0b22665e2ec2138c8</guid><pubDate>Sat, 27 Dec 2008 06:43:40 GMT</pubDate></item><item><title>Karsten - 2008-12-27 06:35:39</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>If you consider the result of the last statement of a block as the (implicit) return value, then you don't need to write the return statement explicitly, except for when you really mean to return from the function.
&lt;br /&gt;If blocks in c are infact just anonymous functions then it'll take away a bit of the dynamic aspect of blocks, but it's still better than nothing.
&lt;br /&gt;
&lt;br /&gt;meh i already see the many compiler warnings i'll get when I keep forgetting the return statement at the end of a block :-)
&lt;br /&gt;
&lt;br /&gt;anyway, it's great seeing objective-c becoming an even more smalltalkish c :-)...but then... there's already f-script :-D</description><guid isPermaLink="true">b17d98637ef82441a74688dc6ae63769</guid><pubDate>Sat, 27 Dec 2008 06:35:39 GMT</pubDate></item><item><title>Tristan O'Tierney - 2008-12-27 06:05:13</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Awesome post, and it really shows what we obj-c guys have been missing for so long that all the ruby boys have had for years :(  I've always loved both languages, and pretty soon we're going to have a major advantage of ruby in a language that has native linking with c/c++.  Great times ahead!</description><guid isPermaLink="true">0f01a64621e2b608aa4198623c3d7932</guid><pubDate>Sat, 27 Dec 2008 06:05:13 GMT</pubDate></item><item><title>Jonathan - 2008-12-27 05:25:16</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>It might help readers to mention that the "access to local variables" you are describing is more commonly called a Closure.  
&lt;br /&gt;
&lt;br /&gt;All of the great reasons to use closures in other languages that support them applies to Objective C.  It's about time we get more truly dynamic programming constructs.
&lt;br /&gt;
&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Closure_"&gt;http://en.wikipedia.org/wiki/Closure_&lt;/a&gt;(computer_science) [WikiPedia]
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">7bc8eb35ab8597b5cb52aeffce388420</guid><pubDate>Sat, 27 Dec 2008 05:25:16 GMT</pubDate></item><item><title>sitharus - 2008-12-27 05:20:06</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>Karsten: Think of blocks as anonymous functions, just with different variable scope, so return returns the value from the block to the caller.
&lt;br /&gt;
&lt;br /&gt;Pity they're just blocks, not true closures, but that'd be a bit harder to jam on to C ;)</description><guid isPermaLink="true">8e3cd3db1d59e702267ee4fc2dba5c65</guid><pubDate>Sat, 27 Dec 2008 05:20:06 GMT</pubDate></item><item><title>charles - 2008-12-27 05:11:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>"But since I manly want to talk". That's the way to talk, dude!
&lt;br /&gt;
&lt;br /&gt;Typo apart, great piece, thanks!</description><guid isPermaLink="true">dcce33e70cd6f439b8390069cedb0503</guid><pubDate>Sat, 27 Dec 2008 05:11:27 GMT</pubDate></item><item><title>Karsten - 2008-12-27 03:41:43</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html#comments</link><description>I'm totally looking forward to finally seeing blocks in ObjC and C, but from your examples i'm a bit confused about the "return" statements. Does a return inside a block mean that the block itself returns this value to its caller or does it make the method that declares the block return some value? that would change the semantics of your mapping example dramatically:
&lt;br /&gt;
&lt;br /&gt;newArray = [existingArray map:^(id obj){ return [obj stringByAppendingString:@"suffix"]; }];
&lt;br /&gt;
&lt;br /&gt;if return would make the calling method return, this wouldn't assign anything, it would just return the first object of the block.
&lt;br /&gt;
&lt;br /&gt;If you consider a call like:
&lt;br /&gt;
&lt;br /&gt;myObject = [someObject doSomething:^{...} onErrorDo:^{return nil}]; this return is ment to make the method return nil instead of assigning nil to myObject. How do c-blocks distinguish one return from the other? Do c-blocks have implicit return values? I'm guess they don't, but how could you make a block return from a method?
&lt;br /&gt;
&lt;br /&gt;Karsten</description><guid isPermaLink="true">16a282409f330a77f1d9e3ce08bc189c</guid><pubDate>Sat, 27 Dec 2008 03:41:43 GMT</pubDate></item></channel></rss>
