5 ms·
Apple adds closures to C family of programming languages
- asimjalis 17y agoBrilliant. Can't wait to try this out.
- limmeau 17y agoThis seems to be relevant: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002670.html http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/00267... In short: per default, you get copies of captured variables, but you can mark variables to be writable from blocks. In order to be able to call a block after the function call where it was created has ended, closures may be copied to the heap (with refcounting).
- onedognight 17y agoThe syntax for this is quite nice. call_me(^int (int x, int y) { return x + y; }); I like it quite a bit better than the proposed c++ lambda syntax. [](int x, int y) -> int { return x + y; } The ^ is very ananogous to *. You could declare the above function call_me() with something like this void call_me(int (^fun)(int x, int y)) { fun(fun(4,5), fun(3,6)); } which is quite "C like".
- tumult 17y agoThis sounds cool, but I think I will just make a jumble if I try to actually use it. What I like most about closures in most languages is how quickly it lets you work. In C, I don't want to work quickly. I need to be methodical and pay close attention to detail -- this usually means I'm going to keep track of what I'm doing both in my head, in notes I'm taking, and in the actual C code. Passing pointers along with the callbacks (for example) isn't such a big deal when I'm already doing all of this extra work. I mean, I'm writing C in the first place since I'm doing something low-level, something that needs careful optimization, implementing some kind of base system for something else, etc. Otherwise I'd just use a higher level language. In the context of Obj-C it makes more sense, though, since you're already writing C while working with a higher-level language, too. You use obj-c objects if you need refcounting or GC at the moment; I can definitely see the usefulness of having closures in C. I know lots of people will probably use it just fine, but for me, I think I would just make a hash of my own code. Or maybe when I give it a shot it'll work out fine. Ok done with rant :)
- invisible 17y agoI think this will be a neat feature for Obj-C, but it'd be a neat concept (not in this implementation) for C/C++. Closures/lambdas aren't greatly leaving the strict language world, but they ease development vastly. I'd like to see closures being added/removed as if they were an array/vector/something in C/C++.
- hypermatt 17y agoRead the comments on the blog, actually a lot more insightful then his post
- mustpax 17y agoI think the distinction between a lambda and a closure is especially important. Closures maintain references to the local stack and I shudder to think the kind of bugs and unsafe memory operations that can result to writing to bad places in the stack. Buffer overflows anyone?
- bitwize 17y agoNo. Closures, if implemented properly, may contain references to variables in the enclosing lexical environment where the closure was defined. Whether they live on the stack or in the heap is an implementation detail, and may have everything to do with the provable dynamic extent of the closure (e.g., downward funargs can point back onto the stack whereas upward funargs must be heap-allocated).
- cousin_it 17y agoIn lambda calculus, where the term "lambda" comes from, lambda expressions can close over free variables. http://en.wikipedia.org/wiki/Lambda_expression http://en.wikipedia.org/wiki/Lambda_expression I think about it as a three-way distinction rather than dichotomy. Here goes: 1) Anonymous functions that don't close over variables in their scope. Example: summing a list by passing "plus" to "fold". Doesn't require much runtime support beyond C, only a syntactic extension. 2) Anonymous functions that close over their environment but can only be passed down the stack - "downward funargs". Example: enveloping calls, like Ruby's File#open. Basically we encapsulate file I/O in a function that works thus: open the file, pass the file descriptor to an anonymous function received as argument, then after it completes work (or upon any exception) close the file. 3) Full closures that can outlive the context they were created in. Example: an event handler that we attach to a button in JavaScript. This case often requires that stack frames reside on the heap and be subject to garbage collection. Re buffer overflows: if the language support is implemented properly, a closure created in a certain scope has exactly the same potential for buffer overflows etc. as regular code executed in that scope. EDIT: see the comment by limmeau nearby.
- alexgartrell 17y agoThe optimist in me sees this getting used to greatly reduce the amount of code required for many repetitive things that are often done in C. Partial Application could be really powerful in such a verbose language, and MACRO tricks to accomplish similar results are hard to debug and pretty ugly. The pessimist in me sees a lot of very poor design decisions resulting from this feature, because everyone will be excited to play with the new toy. The realist in me does not expect to see this in ANSI C any time soon.