closures and objects are isomorphic on some level: a closure is just an object that merely implements one method, "apply." In principle, a compiler/runtime could implement closures on top of OOP or OOP on top of closures. LISP has the CLOS, Common Lisp Object System, and various attempts in Scheme. They probably don't feel a lot like what C++/Java programmers are accustomed to.
How does this relate to garbage collection? "In a garbage collected environment, closures can (a) capture variables from the lexical scope of the function they are nested within, and then (b) escape, granting those variables a longer lifespan than they would otherwise have had. So, it becomes an object that goes on the heap.
So, when he says "long lived closures" he actually means "I want to
hide state behind this garbage collected callback object that acts like
a function, pass it to somebody else who will migrate it wherever, and
then forget about it"
Like a slob.
Is that how LISP does it? I guess I'm not understanding this well
enough because I'm imagining stuff that would be better handled by
putting it on the stack.
I don't know (or at least remember) the internals of lisp, but you have to get out of the mindset of code actually translating to assembly and start thinking of it as a language that implements concepts. Of course the compiler and the running performance takes the hit, but imagine thinking of a program in a way that solves problems rather than one that translates to the hardware you know about.
Personally, I can't do that, I'm too buried in the know-how of my machine, but I accept that there are people who actually thingk in language and want to accomplish true objective problem solving not problem-solving-the-computer's-way.
I also think it's a little stupid since the hardware really is a real problem to be dealt with, but that's me. I'm sure those people think what I do is stupid. And that's fine.
The idea of a closure or any kind of free floating object-in-space sounds great from a language point of view, but I'd never want to actually use one knowing what the compiler is going to have to do to make it work.
Adding it to languages just makes the language suck more just like opererator overloads, but again that's me.
How does this relate to garbage collection? In a garbage collected
environment, closures can (a) capture variables from the lexical scope
of the function they are nested within, and then (b) escape, granting
those variables a longer lifespan than they would otherwise have had.
And it just seems so disgusting to me. It's like taking the structure of your nicely structured program and ripping it out and throwing it on the floor and letting it writhe there until the garbage collector happens to notice it, and meanwhile there's a big fucking void of a hole in the middle of your program where that object used to be.
Just rubs me the wrong way.
Well, the funny thing is, when you start implementing certain patterns (like using the Ropes library instead of a strings class) then you will be forced to either manually implement reference counting, or rely on GC.; certain data structures simply can't work without one or the other. And there some sound reasons to prefer GC over reference counting; one of those is performance (although it's a time/space tradeoff for sure.)
sounds great from a language point of view, but I'd never want to
actually use one knowing what the compiler is going to have to do to
make it work.
Well the bad news is, you're using Java, so you're already using that crap whether you like it or not... the worse news is, Java has all this runtime devirtualization crap that is basically there to work around the fact that the language leads you towards writing every method as a virtual method. But basically the state of the art in that regard is something called a Polymorphic Inline Cache or PIC. In the HotSpot client VM it really sucks - virtual method call performance runs from 5x to 14x slower than what you should be able to achieve if the call was fully inlined the way you want it. It's much better in HotSpot server; the runtime is able to fully inline your crap, reliably. But only if each call site can only have 1 or 2 receivers. More than that, and the runtime falls back on plain old dynamic dispatch.
Purportedly Project Lambda (the add-closures-to-Java project) is actually going to fix this, and fix it in a way that seems to me to be actually novel, there might not actually be any prior art for it. Fixing the polymorphic inlining problem by allowing curried functions (sorry for the LISPism, go Google it) to be inlined in many more cases.
It took many years for me to be sold on the idea that higher level languages are a better deal than pure assembly, and it will likewise take many years for me to drink the garbage collection koolaid, although sadly I think I see it in my distant future.
On the downside java has made me lazy and sloppy and it sucks.
Either way though, I'm not there yet.
It's not one of those obviously this-is-the-right-answer kinda things. It does justify the the-computer-is-the-tool argument though.
It's not one of those obviously this-is-the-right-answer kinda
things. It does justify the the-computer-is-the-tool argument though.
Basically, the lazy GC versus reference-counting-for-every-object-in-the-system debate boils down to, if you defer the GC work until later instead of tracking it on every pointer update, for typical code you have less work to do, by the time you actually do it. And the "make it a first class language feature" argument boils down to, "never repeat yourself."
Obviously there are tradeoffs involved and when you need every ounce of performance, manual might be king, but I'd start with the "premature optimization" premise.
i'm still a big fan of no-GC. I don't even like smart pointers.
Since one has to learn how to do it anyways, i'd rather let valgrind tell me that my code structure was wrong and something was still accessed after freed, or not freed at all, than having to figure out why the GC doesn't do its job or drags down performance under certain circumstances...
I know as soon as you have to share data that stops working but by and large, most of your stuff (at least in my experience) can be handled without reference counting, and just making sure everybody knows who owns what.
I'd rather run boehm-gc in debug mode than valgrind ;)
When I was in sanfrancisco I noticed that I understodd the trolley system. It was simple enough that I understood every little bit of it, and if had to make a transit system, that's probably the level of technology of what I'd come up with.
I mean I dreamt up a wonderful rotary engine concept, but I couldn't actually design it right or build it.
Same thing with programming. I get all these high minded concepts (think about starting in assembly, objects are a pretty high minded concepts) but I would never have thought of them myself, I'd have just written a java sized library of everything I'd ever have need to do, and it would work and I wouldn't have to worry about garbage collecting or closures or anything like that.
now thats a cute list:
but the boehm-gc debug won't show you uninitialized variable access as valgrind does for free while searching leaks.
valgrind slows your code down. it's a useful tool that has its place in the toolbox, to be sure.
yea, java performance for testing & development is ok, but at realtime its just fast and slink.
We don't have a phone call we just email what's going on
. I have sent 110 emails so far since 8am.
Sometimes, I amaze myself.