I don't understand Python's Asyncio - <AUTHOR> http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/ <comment><USER3> I think I've made the point a few times that I don't like this style of programming at all, because the coroutine layer turns into an Inner Platform [1] replicating all the control-flow structures the original language has, which then has to integrate with the original language which causes more than twice the complexity to emerge. But it's hard to bash together an example of how that happens in a comment, when it's all faked up and easy to dismiss. This is a great example of the complexity that can emerge. Some of that is incidental and will be fixed in future releases, but some of that is pretty fundamental, such as the initial list of all the sorts of things you need to learn about to use asyncio. Languages like Erlang or Go that have the event loop simply embedded into the language from day one have a much shorter list of such things you have to know, and it does all the things that this complicated list of asyncio concepts do.

But I will also admit some of this complexity is definitely Python-specific. I've been using Python since 1.5.2 was still the version you'd be most likely to encounter and I've liked it as a language for a while, but one release at a time, the language has been getting more and more complicated. By the time asyncio came around, the language was quite complicated, and sticking asyncio on top while integrating it with everything else is really a mess. Python has too darned many features at this point. I don't know exactly when it jumped the shark feature-wise, because individually they all make sense, but the sum total has gotten quite unwieldy. Watching new programmers try to learn Python, a language I used to suggest to such people as a good language to start with, has been a bit dispiriting lately.

[1]: [https://en.wikipedia.org/wiki/Inner- platform_effect](https://en.wikipedia.org/wiki/Inner-platform_effect)

<comment><USER4> Why can't Python have something like [http://libmill.org](http://libmill.org) ?

If it's doable in C, why not in Python?

<comment><USER5> It has those. It as the greenlet library and used by eventlet and gevent. Many use those, and they've been there for many years. But Guido and others decided that is not acceptable. So we've gone the Twisted route (because everyone know Twisted is easy and fun) and now we have yields, co-routines, futures, awaits and all the other mess.

<comment><USER6> Lots of conversation between Armin and a few others about these approaches in reddit's /r/python thread for this article. I happen to think that gevent got a _ton_ right, and the consensus seems to be that this 'new' approach is sort of half-baked, at least vis-a-vis python implementation.

[https://www.reddit.com/r/Python/comments/5a6gmv/i_dont_under...](https://www.reddit.com/r/Python/comments/5a6gmv/i_dont_understand_pythons_asyncio_armin_ronachers/)

</comment></comment></comment></comment><comment><USER7> I've been a gevent user for a long time and Python's decision to "bless" twisted by adopting it's patterns was a watershed moment for me, and basically was the beginning of the end of my belief that I'd ever adopt Python 3.

User jerf's comment that asyncio "more than [doubles] the complexity" is absolutely correct. Watch this video of Guido talking about tulip...or struggling to talk about tulip, rather. It's clear the dude is out of his depth and my god the recent changes to the language show that the inmates are now running the asylum... Seems like Python, in it's effort to chase the latest fads, is no longer the language I would endorse to someone new to programming. Whether you think that's a meaningful litmus test or not, the staggering amount of _crap_ that's infiltrated the language now completely flies in the face of the zen of python's statement that there should be one and preferably only one way of doing things. Fuck. I'm going to go code some lua now.

[https://www.youtube.com/watch?v=1coLC- MUCJc](https://www.youtube.com/watch?v=1coLC-MUCJc)

<comment><USER8> Oh come on. Hyperbole much? You're acting as if it's impossible to write any sort of meaningful code in 3.x without embracing asyncio. A few 2to3-ish language changes excepted, you can punch the exact same code into the Python 3.x interpreter that you have been for the past 15 years.

<comment><USER9> Not much.

I agree with coleifer (and others) that Python 3 is losing "the zen". The new f-string stuff is a perfect example: a bad, retrogressive idea that never should have been approved.

I have no plans to adopt or use Python 3.

<comment><USER10> I have mixed feelings about f strings. Having the string literal bound to the variable name feels kind of backwards -- that one could break interpolated strings inadvertently by refactoring a variable name. On the other the str.format syntax is a bit verbose, even in shorthand notation.

That said, I use Python 3 every day for almost everything without need to use every shiny new feature.

<comment><USER11> It's Python we are talking about right? Refactoring a variable name in a non type safe language has always been prone to break something. If you trust your IDE to do refactoring on that level I would also trust it would rename inside the string.

</comment></comment></comment></comment></comment><comment><USER12> The general sentiment in this thread seems to be that Guido et al "blessed" the Twisted way, it's a pity and now using asyncio and friends is the only way to suspend a Python stack in a concurrent program besides using OS-level threads.

This is not correct. Green threads, as a programming paradigm, are just a sub- optimal (but cheaper) way of doing preemptive multitasking. Yes, switch is explicit, but user code can't know what will switch. So you are not supposed to treat green threads any differently from OS threads. ie you still need your mutexes, semaphores etc. if you want to avoid race conditions. Again, that's because the caller doesn't know whether a function will yield execution to the next queued task at some point. Guido explains this point pretty well in one of his PyCon keynotes.

So green threads may be great but they don't bring anything new to the table.

However, Twisted-style concurrency (aka cooperative multitasking) is a different paradigm. In Twisted, you know that you only have one thread running at a time, so you actually don't need any thread synchronization primitives when accessing non-local state. This simplifies things a great deal. Yes, not having to spawn a thread for every single concurrent IO operation has other great benefits, but that's not the reason why CPython now has a blessed event loop -- it's cooperative-multitasking-the-paradigm.

Before asyncio, there was no standard way of doing cooperative multitasking. Now there is and it's baked right into the language. Use it if you like it. If not, the old ways of doing things work just fine in Python 3.

I'll admit that the concurrency model in Python 3.4 was not perfect. However, what we have with Python 3.5 and up looks quite polished.

<comment><USER13> I disagree that the code can't know what will switch with green threads. They switch on I/O and when explicitly requested. An example of using this to get rid of concurrency control: [http://www.underengineering.com/2014/05/22/DIY- NoSql/](http://www.underengineering.com/2014/05/22/DIY-NoSql/)

If you want to make sure that there are no context switching in certain part of your code, you can do it ASSERT-style, something like:

        # enable this only if you use atomic, so a new module that should be imported before gevent
        in_transaction = False
        if __debug__:
            import greenlet
            old_switch=greenlet.greenlet.switch
            class _greenlet(greenlet.greenlet):
                def switch(*args, **kwargs):
                    if in_transaction:
                        raise Exception('Switching context during / atomic')
                    old_switch(*args, **kwargs)
            setattr(greenlet, 'greenlet', _greenlet)

        @contextmanager
        def atomic():
            """
                Ensure that a function or a block of code is atomic, raise exception if it's not

                Usage:

                @atomic()
                def myTransaction(...):
                    ...

                or

                with atomic():
                    ...
            """
            global in_transaction
            in_transaction = True
            yield
            in_transaction = False

<comment><USER12> And how is this not a mutex?

<comment><USER13> This only runs in the debug version of the code. I hope your mutexes run in production, too.

<comment><USER14> So you rely on hoping your tests exercise all possible paths, because if not you get silent race conditions in prod?

<comment><USER13> If you want you can run it in production, too (this would give you a warning, won't prevent race conditions, but there is almost no performance penalty). The point was this is very different from a mutex.

</comment></comment></comment></comment></comment></comment><comment><USER15> For background, the author founded the Flask project [0] among others, and contributed to many other well-known Python projects.

0\. [http://lucumr.pocoo.org/projects/](http://lucumr.pocoo.org/projects/)

<comment><USER16> Also [https://www.palletsprojects.com/](https://www.palletsprojects.com/)

Btw. does someone know why some things where moved from Pocoo to Pallets?

<comment><USER17> Armin wanted to step back a little from these projects and moved them to pallets in order to make them more community-driven

</comment></comment></comment><comment><USER18> I agree with Armin that Python is becoming burdensomly complicated. Since Python 3.2, the language has started to accumulate a lot of features, Guido seems to be saying yes to everything. Furthermore, the Python 3 fiasco has severely affected Python's popularity. It would be in much greater use now if the clean-up had been done more gradually.

<comment><USER19> I don't quite see why it's being downvoted. Like it or not, but that's what is happening: Python's 2.4-2.7 success was largely due to it's simplicity. It more or less did correspond to values defined in `import this`. It wasn't particularly performant nor "safe/foolproof", it wasn't even that powerful as a language. It lacked (and still lacks) good error reporting system. But it was lean, easy to get started with, agile enough, expressive enough. It was always possible to make something unintelligible using reflection and magic methods, but it is easily distinguishable form "how stuff should be written" and otherwise you could be quite sure there won't be any surprises.

This is why python is still used for it's purpose. CLI utils, bots/crawlers, tf/pandas/scikit-learn, REST-APIs on top of flask.

Then hard times came. First, many year long story (still not concluded) of transition between 2 and 3. Then all this stuff. Sure, there is such thing as progress. Stuff is invented for some purpose. But now, in 2016 and at v3.6 — Python isn't what it has been loved for. Not easy-to-start-with, nor simple. This return/yield fuck up, showed in the article is absolutely huge deal, for example, and it is not about asyncio per se. Async stuff is always complicated, it wouldn't be that bad if it was all it's about.

If some 5 years ago one would use Python just because "why not, I just need to get stuff done", now it's quite likely that after struggling with all this micro-nuisances he would go with golang/js/php/whatever instead.

<comment><USER20> The thing about Python is that unlike most other languages, you don't _have_ to deal with that complexity. You can still write Python 2.7 style code, no problem.

This approach to async, though, is just a language feature that's becoming mainstream right now. C# has it, ES7 has it, C++ has a working paper on it etc. Python actually had the benefit of watching how things work out elsewhere before implementing it all.

<comment><USER21> The idea that complexity doesn't matter if you don't use it sets Python on the path to becoming the next C++. Pick the subset of the language that you like. Then carefully watch your libraries, because if they use a different subset, you still have to deal with what's in there (and Python is a library heavy language!). It goes against everything Python stands (stood) for. Definitely not what I'm looking for.

<comment><USER20> This is not at all a new problem for Python. In fact, it's possibly more of a problem for Python than it is for C++, because Python's dynamic nature and exposure of many internal mechanisms makes it possible to do some pretty crazy stuff in the libraries.

For example, speaking of async - even 2.7 already has Twisted, and an ecosystem of libraries around it.

The only two ways I can see it being solved is either by making it more of a toy language (which is great if you're just writing short scripts, but it's not really what it's supposed to be about); or by having a very centralized "best practices" enforcement that basically forces libraries to conform through peer pressure, like Java - which has its own disadvantages aplenty.

</comment></comment></comment></comment></comment><comment><USER22> I just got started on Python's asyncio. It took me a long time to understand how to get things done, but after about a week of doing small example projects in the evenings, it finally 'clicked'. For the record, I never worked with gevent before, and have only done a small webserver with Tornado a long time ago, so I can't comment on how it compares to other solutions. One thing that made me wait for asyncio is the fact that, despite being experimental, it has a lot more of an "official" feeling to it.

I'm trying to stay away entirely of the Python 3.4 way with coroutine decorators, and am using only await and async in Python 3.5. The async code I wrote has to live in parallel with regular synchronous Python code in a large scientific code base, but migrating our custom database adapter to an asynchronous codebase without breaking old synchronous code was surprisingly easy.

Debugging is, in my opinion, a pain. Stacktraces can be extremely long and very hard to understand. The only profiler that seemed to give useful results was pprofile (in sampling mode). I also still don't fully understand why there's both Futures and Tasks - I probably didn't spend enough time understanding the difference, but that just means the author of this blog post is right. Mixing asyncio with threads and/or processes, however, is surprisingly easy and elegant.

I hope the Python developers will have the courage to break backward compatibility in the asyncio module, and will remove the old yield from and @coroutine way of doing things. That would probably help a lot in reducing confusion. There's still not a lot of information about asyncio when you google for it, so the amount of existing code and examples that that would invalidate would not be too high.

All in all, we are very happy with asyncio. We use it mainly to add concurrency to small sections of our code base. By default, all our code is synchronous, with some heavy I/O-bound functions exposing async versions, too. asyncio allows us to parallelise these sections without the use of a thread pool, and thanks to Futures/Tasks and queues, it's actually very easy to do this in a "streaming" fashion if the order of processing of the outcome of your concurrent tasks matters. Add to that the executors which allow you to run stuff in sub-processes when you're CPU-bound (instead of I/O), and it makes for a fairly solid tool.

<comment><USER23> > I also still don't fully understand why there's both Futures and Tasks - <USER2> > probably didn't spend enough time understanding the difference, but that > just means the author of this blog post is right.

Because they are essentially the same.

Task is just extending Future and adds extra functionality (like for example keeping track of tasks schedule in given event loop).

It is created when you call ensure_future() or loop.create_task(). You are not supposed to create it directly, so if you're wondering whether you should use Future or Task you should use Future.

</comment></comment><comment><USER24> So I'm not the only one. I wrote larger-ish project while using asyncio and it is pain. The syntax is very unfamiliar (especially in 3.5 with async/await), the documentation is confusing and it's very hard to debug it in general. Also it's very hard to combine/stack multiple IO heavy events (make 5 calls to these URLs and whichever is done and returns these task run them in parallel).

<comment><USER25> That last part is exactly what my webcrawler does with asyncio plus threads: [https://github.com/cocrawler/cocrawler](https://github.com/cocrawler/cocrawler)

This is the part that sends work to a thread: [https://github.com/cocrawler/cocrawler/blob/master/cocrawler...](https://github.com/cocrawler/cocrawler/blob/master/cocrawler/burner.py)

I agree that this was confusing in the docs. Docs can be improved. It really helped that this isn't my first crawler written using cooperative multitasking.

</comment></comment><comment><USER26> There are a few new concepts that need to be learned when beginning work with asyncio as well as some confusing naming choices (who would expect that a coroutine is not the same as a coroutine function?). Some of the tooling is also lacking. Armin points out, no doubt with a look at server frameworks, that there is no elegant way to access the context of a task.

That being said, as someone who started working with asyncio in Python 3.5 none of it feels particularly difficult to understand. Asyncio needs more work, sure, but the API so far is relatively straightforward.

The overloading of iterators/generators is a bit odd. But the same approach that was taken with JavaScript -- and it's nothing anyone working with Python 3.5 or above will be exposed to. If I recall correctly, Python 3.6 will even feature async generators. Any developers diving into this using that release won't have to ask themselves why they can't 'yield' from within an 'async' function.

<comment><USER27> I don't find it hard to write asyncio code but I find it hard to generically interface with other people's asyncio code and that is lacking basic support like a context object or logical call contexts or just the lack of agreed upon usage patterns.

It does not help that asyncio evolves in the stdlib and changes with every major Python version. It might be less of an issue if this was pip installable I suppose. Right now writing utility code for asyncio is targeting many things.

<comment><USER28> I was talking with David Beazley and he had some of the same confusions around asyncio. I think it would be nice to revisit it with a round table and fix it in 3.7.

<comment><USER29> This should definitely happen, if at all possible.

</comment></comment></comment></comment><comment><USER30> From what I learned through youtube videos and meetups it seems to solve a problem that doesn't exist (getting all these patterns into python) and in return doesn't solve the problem people hope it would solve (multiprocessing made easy and pythonic). That's why people who want to pretend to be smart (like me a few years back) find this totally attractive, king's new clothes style. Nobody really understands it so they can act like they really do something meaningful with it.

How do I get to this painful conclusion? Well, as I said, I was (and probably still am to some degree) just like that. And to me it looks nearly irresistably interesting. But at the same time I also don't know what I would use it for, what it would actually improve for me. And since the need to pay my rent forced me to use my time more practically I didn't get around to looking at asyncio more in depth. Both these things together make me believe it's not really solving a real problem.

<comment><USER31> The name "asyncio" includes the substring "io" and is clearly about asynchronous I/O, so it's hard to see why anyone would think its purpose was "multiprocessing made easy."

</comment></comment><comment><USER32> Python core developer Brett Cannon wrote a nice(and long) post about understanding it a couple of months ago[1], that might help. After reading that I felt like I could use it, but never got the chance to try.

[1] [http://www.snarky.ca/how-the-heck-does-async-await-work- in-p...](http://www.snarky.ca/how-the-heck-does-async-await-work-in- python-3-5)

</comment><comment><USER33> I'm working on some Asyncio stuff right now. Asynchronous programming seems pretty natural to me, but other people do struggle to wrap their heads around somewhat confusing terminology: tasks, co-routines, awaitables, event loops. Underneath the terminology the theory is pretty simple.

And boy is it powerful. If you ever find yourself doing network requests in a loop (for url in list: requests.get(url)) then a small bit of refactoring and a sprinkling of asyncio will speed this up immensely.

But it's not just for network calls, you can `await` on threads and processes. It's a joy and I think it's one of the best things in Python right now.

<comment><USER34> Have you tried comparing the performance of asyncio based network requests versus multithreaded requests? And also compared the relative complexity of the code?

I have never used asyncio in Python, mainly because the very use case you described is solved with multitheading, but that doesn't mean it's solved best that way of course.

<comment><USER35> Python's multithreading is insanely inefficient, because of the Guido von Rossum Memorial Boat Anchor. Anything in Python can mess with the innards of anything else at any time, including stuff in other threads. (See "setattr()"). There's no such thing as thread-local data in Python. This implies locking on everything. CPython has one big lock, the infamous Global Interpreter Lock. Some other implementations have more fine-grained locks, but still spend too much time locking and unlocking things. One Python program can thus use at most one CPU, no matter how many threads it has.

This basic problem has led to a pile of workarounds. First was "multiprocessing", which is a way to call subprocesses in a reasonably convenient fashion. A subprocess has far more overhead than a thread; it has its own Python interpreter (some code may be shared, but the data isn't) and a copy of all the compiled Python code. Launching a subprocess is expensive. So it's not a good way to handle, say, 10,000 remote connections.

Now there's "asyncio", which is the descendant of "Twisted Python". That was mostly used as a way for one Python instance to service many low-traffic network connections. The new "asyncio" is apparently more general, but hammering it into the language seems to have created a mess.

After the Python 3.x debacle, which essentially forked the language, we don't need this.

<comment><USER27> > There's no such thing as thread-local data in Python.

There is. threading.local in all aspects is thread local data.

> Now there's "asyncio", which is the descendant of "Twisted Python". That was > mostly used as a way for one Python instance to service many low-traffic > network connections. The new "asyncio" is apparently more general, but > hammering it into the language seems to have created a mess.

I think the mess was created before 3.5. Had the whole thing started out with the async keywords we might have been spared `yield from` which is a beast in itself and a lot of the hacky machinery for legacy coroutines. I do think however we can still undo that damage.

<comment><USER35> _threading.local in all aspects is thread local data._

You can still pass data attached to threading.local to another thread. Another thread may be able to get at threading.local data with setattr(). There's no isolation, so all the locking is still needed.

This is a hard problem. There's real thread-local data in C and C++, but it's not safe. If you pass a pointer to something on the stack to another thread, the address is invalid and the thread will probably crash trying to access it. C++ tries to prevent you from creating a reference to the stack, but the protection isn't airtight. In Rust, the compiler knows what's thread-local, as a consequence of the ownership system. Go kind of punts; data can be shared between coroutines, but the memory allocation system is mostly thread-safe. Mostly. Go's dicts are not thread-safe, and there's an exploit involving slice descriptor race conditions.

<comment><USER27> > You can still pass data attached to threading.local to another thread.

You can in most languages. Only rust I know has enough information to prevent that.

</comment></comment></comment></comment></comment></comment><comment><USER36> At home-assistant.io we just migrated our core from being based on threads + locks to use asyncio. We managed to keep a full backwards compatible API available so we can slowly migrate other parts of the system over to async.

Asyncio has a steep initial learning curve (especially in our hybrid setup) but it's well worth it. We target low resource computers like Raspberry Pi and using async over threads has speed up things a lot.

The biggest catch is that while writing code you have to think about every function that you use. Is it doing I/O, is it a coroutine or is it callback/async friendly.

<comment><USER37> ... why do you need locks in threads and not in asyncio ?

<comment><USER27> You need locks in asyncio as well.

<comment><USER38> Only if you have multiple threads/processes/coroutines sharing resources.

<comment><USER39> "Only"? You need locks in exactly the same scenarios as you do when you use multiple threads.

<comment><USER38> Good point. I should have said that asyncio allows patterns that use fewer shared resources.

Actually... I take that back. Asyncio is solving a different problem than the locking of shared resources.

</comment></comment></comment></comment></comment></comment><comment><USER40> Maybe I'm not the intended audience for this article, but I don't really have a problem with a lot of the warts of asyncio. It really is pretty simple to use if you don't have your mind hard set to a different way of thinking. It wasn't as simple in Python 3.4, but then the async/await keywords became part of the language in Python 3.5 and simplified things. Understanding asyncio took me a few days to understand the complexities: the event loop usage and how this works with async/await, how an async function is different than a normal function, and a few other things. Once I understood those complexities (which I don't mind because it is a new part of the language) it was easy. Granted, I feel like it's easier to just work around issues rather than complain about them but I didn't find particularly many issues about asyncio.

As an aside, not to pick on Armin but he was also complaining about Python 3 about things that may have been valid, but were more that he didn't like the way that Python 3 worked because he liked Python 2 more, and hid that fact by writing lengthy blog articles about how he doesn't like certain Python 3 things. I do find it a little strange that he does complain about these things publicly rather than trying to fix the things he doesn't like (if they are fixable), especially given his reputation in the community and his Python projects like Flask, because it makes him seem whiny and solves none of the issues that he's presenting.

<comment><USER27> > I do find it a little strange that he does complain about these things > publicly rather than trying to fix the things he doesn't like (if they are > fixable), especially given his reputation in the community and his Python > projects like Flask, because it makes him seem whiny and solves none of the > issues that he's presenting.

It's easy write code, it's harder to write specs and design systems and it's hardest to convince others. I'm very bad at the last part. My only real attempt to improve python 3 that went anywhere was to get the u prefix back. My suggestions for bytestrings were not very popular for instance.

<comment><USER40> Okay, fair enough, it's harder to think about a problem than write the solution to the problem in general, at least for software development. But it would be better if you did try to talk to the Python developers in a constructive manner and try to get whatever you feel is wrong with Python fixed. Writing blog posts is fine, and I'm not saying that voicing your opinion is bad, but there is a threshold between voicing an opinion and actually doing something about it, and while I feel you do contribute to the Python community, you don't contribute to Python itself even if you have the ability to and after years of blog posts you've crossed that threshold. The reasons that you don't attempt to contribute I'm not sure -- lack of patience for the process, unable to convince others, designing a system that fixes the issues you're finding. The biggest thing is that if you want something fixed and have the ability to fix it (which I feel you would have) don't just sit around and complain -- do something about it. The best way to convince a developer is to write code to prove your point.

</comment></comment></comment><comment><USER41> The post mentions in passing David Beazley's curio[1] project. Is anyone using curio for async programming instead of asyncio?

The curio docs are fun to read through and didn't leave me feeling lost. They're also full of understandable examples of using the new async/await syntax.

I've made some simple scripts with curio but have found I keep hesitating take on the asyncio docs to learn it "the real way". Any thoughts on whether curio might be a plausible alternative to asyncio?

[1] [http://curio.readthedocs.io/en/latest/tutorial.html](http://curio.readthedocs.io/en/latest/tutorial.html)

<comment><USER42> Since it's polling for I/O events and doesn't use threads [1], it does indeed sound like a plausible alternative for doing non-blocking I/O.

I think I'm going to take a stab at using it, since asyncio doesn't have a mature ecosystem around it anyway.

[1] [http://curio.readthedocs.io/en/latest/index.html#under- the-c...](http://curio.readthedocs.io/en/latest/index.html#under-the-covers)

</comment></comment><comment><USER43> I had a similar experience with python 3's asyncio. I have worked with gevent, which has an arguably less "elegant" interface (with monkey patching, for instance), but with which it is so much easier to be productive. I was frustated for having dificulties understanding and using asyncio. The author is a better python programmer than I am, so I supposed there is really a problem there.

</comment><comment><USER44> The one thing that I think is absolutely lovely is the syntax:

        async def spam(eggs):
            ...

It can't get much better than that.

My hope is that the implementation will become:

A) simpler

B) more optimized

C) out of the box functional (e.g., no need to manage event loops and other things yourself)

D) unified (e.g., the zen of python even states that there should be one way to do something)

I also strongly agree with the comment @RodericDay made herein, pertaining the new typing syntax and the addition of yet another string formatting syntax (a dangerously unexplicit one).

<comment><USER45> Have a look at the way C# does it. I think it comes pretty close.

</comment></comment><comment><USER46> I find that Armin's blog posts about Python 3 are generally destructive, not constructive. A constructive way would be to post suggestions on python-ideas and python-dev mailing lists or report bugs and feature requests on issue tracker.

Python is open-source project and there is not a single core developer working full-time on the language unlike his beloved Rust.

<comment><USER47> I've always found Armin's posts to be intellectually honest and thought provoking. And unlike your ad-hominem comment, he itemizes his concerns and provides details (such as the performance comparison with David Beazley's curio project).

At the very least, it is a warning sign that a notable and highly experienced Python expert is having a hard time grappling with the best practices (or even workable practices) for a significant new feature set: "I know at least that I don't understand asyncio enough to feel confident about giving people advice about how to structure code for it."

As far as I can tell, not a single respondent to this thread has indicated that to the contrary, they have been able to say that they do feel confident enough to give people advice on how to structure code with asyncio.

At the very least, that means that we have a documentation and communication problem which is either intrinsic to the new API or something that will work itself out over the next few years.

<comment><USER48> For what it's worth, I read Armin's critiques, but I take them with a grain of salt; it's clear that what he wants from a language, and what other people want from Python, diverged a while back and are probably irreconcilable at this point. That doesn't mean he doesn't have good points, but does mean that I read his articles through a lens of "the language he really wants probably is never going to be Python again".

<comment><USER27> > I read his articles through a lens of "the language he really wants probably > is never going to be Python again"

I always had that opinion that what I would like Python to be like is never going to happen. This is not something new with Python 3.

</comment></comment></comment></comment><comment><USER49> I wrote a fast tcp port scanner using Python 3.5 and concurrent.futures.ThreadPoolExecutor.

See lines 123-124:

[https://github.com/jftuga/universe/blob/master/tcpscan.py](https://github.com/jftuga/universe/blob/master/tcpscan.py)

I have used this under Linux, OSX and Windows. It's cool to add the Thread Count field in Task Manager and then see something I wrote use so many threads! I am more of a sys admin, so this code could be better - but it seems to work very well. :-)

<comment><USER50> quick github tip: if you click the line number on the left you can get a link directly to the line you are referring to.

extra tip: after clicking the line, press 'y' on your keyboard and you'll get a link to the file in it's state at the current commit so future commits won't break your old hyperlinks.

<comment><USER49> cool, thanks

</comment></comment></comment><comment><USER51> The Fluent Python book has a nice set of chapters on coroutines, futures, and async.io. They present not the whole of what it does but one way to do it, which helps.

</comment><comment><USER52> Armin criticism of Python 3 is nothing new.

He is the author of several popular projects including the web framework "Flask". This makes him a person very respected in the Python community - personally I love his taste for interface design.

I wish he could interact better with the core team, because some of his rants are not as constructive as they might be.

<comment><USER7> Whoa... Armin has never, to my recollection, been malicious in his criticisms of Python 3. He simply disagrees with some of the core team's decisions. And he's far from the only one.

It's not Armin's duty to interact in any way with the core team. Hell, the core team should be working to please Armin if you ask me. He's your target user, and he's disappointed with your product, it's not his fault.

I think Armin does a wonderful job providing a voice for those of us who are increasingly disenchanted with Python 3.

<comment><USER53> We know it's you Armin!

</comment></comment></comment><comment><USER54> I still prefer Twisted, it feels more natural to me. But this is something that one cannot say aloud in many Python circles.

<comment><USER55> >"But this is something that one cannot say aloud in many Python circles"

Can you explain why this is? What's the central issue?

<comment><USER56> Twisted ROCKED. I remember when it came out everyone I knew thought it was pretty kick ass, at least those who developed in Python.

Did something happen that it's now fallen out of favor?

<comment><USER57> By now, people expect libraries to have thorough documentation on the Web, not just an O'Reilly book.

The fact that the port of Twisted to Python 3 is slow-going, and far from complete, also gives the suggestion that there are corners of the code that developers don't even understand anymore.

</comment></comment></comment></comment><comment><USER58> What's missing from the asyncio docs, IMHO, is a section on common asyncio idioms and patterns. I understand the pieces individually, but I struggle to get a more global, Gestalt understanding of the system.

<comment><USER27> The problem there is that not everybody who develops asyncjo/tulip agrees on the patterns.

<comment><USER58> You're probably right! I just (for once!) wish a few opinionated people would tell me what they think!

</comment></comment></comment><comment><USER59> > _Since I 'm not clever enough to actually propose anything better I just > figured I share my thoughts about what confuses me instead so that others > might be able to use that in some capacity to understand it._

Coming from a well known Python developer, this gives a somewhat passive- aggressive vibe (which might not be meant at all, just sayin').

</comment><comment><USER60> I didn't need to understand everything about asyncio to use it successfully. It's definitely a lifesaver when it comes to making lots of requests; hours of waiting turn into seconds.

</comment><comment><USER61> Actually using asyncio tools is quite easy and straighforward. However, writting an asyncio lib, or god saves you, an asyncio framework, is really, really hard.

</comment><comment><USER62> The complexity is the reason why I came back to gevent, especially since it now supports Python 3...

Gevent monkey patching isn't perfect but it works and gets you closer to how an event loop should be used with standard libs IMO, closer to Go.

</comment><comment><USER63> No one has to use this stuff if they don't want to.

Another complexity in Python is metaclasses. I've written meta classes which generate data descriptors, and was greatful that that was there when I needed it, but I also needed to look at the data model reference constantly and wrote 200% coverage tests.

</comment><comment><USER9> Coroutines are goto.

That's not a joke or anything, the semantics of coroutines are the semantics of goto statements. All this async business is just the old spaghetti sneaking back in while people are distracted by the nomenclature.

<comment><USER64> Then for-loops are goto as well.

<comment><USER65> A for loop is localized. I've seen Python code bases that use so many interdependent _iterators_ that the code is non-refactorable and the developers just pray that it does the right thing.

That's plain iterators. Now people throw in coroutines.

</comment></comment></comment><comment><USER66> It's too late to complain now.

I did like gevent/greenlet a lot, but the wider community, for many years, was unforthcoming to it.

Now asyncio is in the stdlib, including the language changes for coroutines, better than the status-quo.

</comment><comment><USER67> From early on in the article

> asyncio.get_event_loop() returns the thread bound event loop, it does not > return the currently running event loop.

How can these be different objects? In order to ask for the thread-bound event loop, you must be in the thread, right? When/why would you expect anything else?

fyi, I don't have any background with asyncio/twisted.

</comment><comment><USER68> If people would like some more illustrative examples for using asyncio there's [https://asyncio.readthedocs.io](https://asyncio.readthedocs.io)

</comment><comment><USER37> So I guess it's ok for now at least to stay with gevent ? Does asyncio has any pros (except that it's explicit) compared to gevent ?

<comment><USER57> People don't write articles named "I don't understand gevent" because nobody expects to understand gevent.

Armin's complaints are for library writers. You will do much better using an async framework with support from the core language (asyncio) than a monkeypatch.

</comment></comment><comment><USER69> I'm not really that well versed in Python, but wasn't it supposed to be a language for beginners?

<comment><USER70> _> wasn't it supposed to be a language for beginners?_

No. It was supposed to be a language in which programmers at widely different skill levels, from beginner to expert, could be productive. Easy to pick up the basics, but also easy to use more advanced techniques when you find you need them.

</comment></comment><comment><USER71> This is what happens when coders are rushing to code without real understanding what they are doing and why. What is worse - they borrow "features" without understanding from amateur JavaScript projects or C#.

What a bloated mess. This is clearly the second system syndrome, described in the Mystical Man-month.

In good old times futures were macros on top of delay and force special forms, and explicit message passing a-la Erlang would do the job.

<comment><USER33> What a confused comment. You're saying its bad because it's borrowed hastily from other languages, and a better solution is... borrowing features from Erlang?

<comment><USER71> Not at all. Erlang's approach to concurrency has been well-researched and validated (Akka).

Async, await and friends are mere standardized kludges - popular syntactic sugar without clear semantics and real world connection (explicit message passing mimics how biological systems do self-regulation).

So called enterprise languages, especially C++ are full of similar stuff (kludges).

<comment><USER33> > popular syntactic sugar without clear semantics and real world connection

Uhh... the point of them is that its as close to the semantics of synchronous code as possible. That's the 'real world connection' \- your single threaded code can become asynchonous with just a few keyword changes. Rather than "sendRequest()" you do "await sendRequest()".

</comment></comment></comment></comment><comment><USER72> I consider A.Ronacher as a very very competent guy. I felt really bad not mastering asyncio; now I'm laughing green.</comment>


Ask HN: Can anyone solve this puzzle without an algorithm? - <AUTHOR>

I made this game called Ten Large.
From my limited understanding of theoretical computer science, it's considered a Non-deterministic Polynomial-time hard problem (someone please correct me if I am wrong in this assessment).
I am wondering if anyone can solve it without the use of an algorithm?
https://itunes.apple.com/app/id959811502 <comment><USER2> Looks like we'd have to install it and play it to know how the gameplay works. Is it based on a well-known puzzle that's already described online somewhere?

</comment><comment><USER3> I choose not to click or work with anything Apple related. _Ignores Apple url_. The previous sentence leads to a much more positive outlook of the future of Technology.</comment>


Show HN: Wordy.io website translation and localization - <AUTHOR> https://wordy.io <comment><AUTHOR> Hi everyone, I made this to scratch my own itch. I was having a hard time finding something that would allow me to easily translate my site into multiple languages with a clear and affordable pricing structure. I'm looking for any feedback you may have and I would be happy to answer any questions. Thanks!</comment>


Amit's Thoughts on Grids - <AUTHOR> http://www-cs-students.stanford.edu/~amitp/game-programming/grids/

<comment><USER2> Is it it just me, or is the font, clarity of writing, color combination and diagram presentation extraordinarily clean on that site. There is a small bug with word wrapping beside some diagrams on my iPad, but everything else pulled me into about 25 minutes of awesome reading on grids.

<comment><USER3> I agree that it is above average. Subtle little touches (like the highlight gradients and thoughtfully padded section texts) really add to the readability. And, of course, the content. It's a good blog in general - unpretentious and informative.

</comment></comment><comment><USER4> I don't like the way he does coordinates for triangles and hexagons, having hexes with the same y-coordinate slope up to the right. I prefer having hexes with the same y-coordinate stay as close to horizontal as possible, meaning that even hexes will be shifted up or down by half a hex compared to odd hexes.

I found that keeping the hex coordinates as close as possible to the square coordinates that your GUI library uses makes things easier.

</comment><comment><USER5> I'm not exactly sure what's new on this page, but his articles about game design and path finding were huge help to me when I was starting out in game development.

</comment><comment><USER6> Regarding implementation, he says "All the algorithms are straightforward. How might you implement them? You'll first want to choose data structures for each of the three coordinate systems. I recommend keeping it very simple and transparent. All the coordinate systems I listed have an integer u and an integer v, and some of them have an annotation like L or W ; in Java use a class with public fields; The next step is to implement the algorithms you need. The simplest thing to do is to write functions (or methods) that take A and return a list of B. "

Atleast in Java ( and therefore in Scala, Clojure etc), the data-structure of choice is a general path, and all of those algorithms have built-in implementations, mostly on Path2D or other concretes. Also, instead of dealing with squares, hexagons & triangles separately... a square is just 2 isosceles triangles, and a hex is 6 equilateral triangles. So if you have a Triangle2D class extending Path2D, you get all of the algorithms and the you can handle all 3 face types. The transformation between cooordinate systems is handled by affine transforms

Path2D: [http://docs.oracle.com/javase/6/docs/api/java/awt/geom/Path2...](http://docs.oracle.com/javase/6/docs/api/java/awt/geom/Path2D.html)

AffineTransform: [http://docs.oracle.com/javase/6/docs/api/java/awt/geom/Affin...](http://docs.oracle.com/javase/6/docs/api/java/awt/geom/AffineTransform.html)

</comment><comment><USER7> Love it, I have had to design 2d and 3d grids before now and the information you gave on faces for polygonal grids has been really helpful and will help me to break the square mold, so to speak.

</comment><comment><USER8> For some background, Amit Patel is likely best known for an old BBS game called Solar Realms Elite.

<comment><USER9> I'd say he's likely best known for this very website on game programming. It's been around for a long time by Internet reckoning. In the olden days, it was where you went to learn about A* path finding for games.

<comment><USER10> I remember using it ~10 ago.

</comment></comment></comment><comment><USER11> That's a very nice talk especially if you are interested in 3D mobile games development (like I was once in the past). I wish I'd knew all these before. Thanks for the post.</comment>


OpenSolaris is dead - <AUTHOR> http://blogs.everycity.co.uk/alasdair/2010/08/opensolaris-is-now-officially-dead-rip/ <comment><USER2> Everyone seems to have missed - or be ignoring - the fundamentals of Oracle. They aren't in this game to change the world (ala Sun), or improve the lives of developers, they're in this to make _bucket loads of cash_ if products they acquire will not make them money - they will ruthlessly cut it.

They aren't hackers. They aren't designers. They aren't entrepreneurs. They're business men.

Similarly if you _dare_ compete with Oracle, you're going up against a company similar to Microsoft 10 years ago: rich and mean. Look at someone like Google, you think they're evil? Oracle could literally wipe them off the planet if they were inclined. The fact people hate upon Apple or Google, or even Microsoft when Oracle is the towering nemesis is hilarious. At least Oracle doesn't bullshit you. Google? Do no evil? You're a public company.

Vision, for the greater good, wanting to change the world are all well and great, but when the chips are down, you know what counts? Revenues. As Larry Ellison once said about Sun: "Lots and lots of blogs does not replace lots and lots of sales"

and you know what? I _admire_ them for that. I respect that they walk _that_ line. They're a public company, and god dammit, they're going to win. I would rather spend a year working with Larry than Steve Jobs, Bill Gates or the Google guys.

<comment><USER3> The thing is, as someone stated below, Oracle is all about short-term wins. If Oracle wins this patent suit against Google and gets lots and lots of damages from it, that's nice, but it'll scare everyone away from Java. That's not good for Oracle or anyone else. If they'd just cool their jets and let things like this slide while focusing on creating great Java-based products and improving the Java ecosystem, they'd have much better long-term prospects. Even Ellison stated that Java is the most important product Oracle has ever acquired, and he's going to kill it in desperation to milk every last cent of licenses that he can get today.

If Oracle continues with this kind of ruthlessness, they may squeeze several million out of Google et al, but Java is done for. Nobody will want to use that platform anymore because it will be too risky legally. It'd be a huge opening for .NET and other competitors. Java would go the way of COBOL, only running in the darkest abysses of megacorporations that never modernize.

You can be happy that Ellison doesn't play this "good for developers" thing, but what's good for the goose is good for the gander. By promoting software development and Java development specifically, Oracle would be ensuring generations of Java programmers, and lots of Java-related services and licenses from enterprises. If someone without any programming experience learns Java to write code for Dalvik/Android, as they may because Android is a "cool" platform that would attract young programmers, they can and likely will go on to big corporate environments and continue to work in Java.

<comment><USER4> I think they've actually got the long term covered. Everyone in The Enterprise (which is all Oracle cares about anyway) is already using Java. Those people want to buy official looking software with support contracts from someone.

They're going to be doing so for decades to come, either from Oracle itself, or someone who's paying Oracle truckloads of licensing fees to be allowed to publish their own Java implementation.

The _only_ thing that could upset their subscription to money would be some inconvenient little company that decides to make a clean-room Java implementation that could target the same customers. This is what Google has done.

If they can win this in court or force a settlement that pretty much guarantees that anyone thinking of building that business model won't even bother to get off the ground, and Oracle can keep printing money.

It's funny that you should mention COBOL. Java turning into the next COBOL would be _awesome_ for Oracle. IBM still makes billions selling systems to run COBOL[1], that's more than Sun ever made off Java.

1\. <http://news.ycombinator.com/item?id=1567595>

<comment><USER5> Most companies buying mainframes, buy mainframes to run Linux and Java apps on it. The COBOL+mainframe market is not growing (very much). (source: talking with an IBM research director in Böblingen, Germany responsible for mainframe development)

Mainframes promise turnkey-reliability, where the IBM support guy comes in before you notice anything going wrong. The point is that "mainframe" is a strong brand and IBM has the monopoly on it. There are solutions magnitudes cheaper and just as reliable as a mainframe.

</comment></comment></comment></comment><comment><USER6> Having never used OpenSolaris this is no hardship for me. However, it's looking like Oracle is a company that is quite hostile to open source, so this also raises concerns for what will happen to the likes of OpenOffice and VirtualBox. In general it also raises questions about the wisdom of open source developers assigning their copyrights over to a particular company, who may subsequently choose to betray their generosity. If I'd made significant contributions to OpenSolaris I'd probably be feeling as sick as a parrot right now.

<comment><USER7> Don't forget NetBeans, the Rich Client Platform. Lots of applications are built on it (Light Analysis, Energy Consumption Management, Petroleum Engineering App, Swedish Trading Client & Swedish Defense Research App, Open Source Stock Trading Platform, Jewelry Customer Manager -- these are news only from the last 3-4 months), even NASA uses it. It's crucial for Oracle to sustain NetBeans development and not to favour their JDeveloper IDE (cause the latter isn't a platform).

<comment><USER8> Oracle uses NetBeans internally for the development of several applications (mostly from acquisitions), I don't believe you'll see that phased out anytime soon.

</comment></comment></comment><comment><USER9> One thing you have to say for Oracle that you couldn't really automatically say for Sun: they're not chickenshit.

<comment><USER10> No, they definitely leave out the chicken part.

<comment><USER11> Because they don't want to spend/waste money maintaining certain features of a product that are less profitable? Or …?

<comment><USER12> Because they prefer spending money on sales, marketing, and lawsuits than maintaining / improving their products, even their most profitable ones.

<comment><USER11> Surely if that is true, which I seriously doubt, this is partially on the buyer for not choosing products based on which is the best, and therefore not giving Oracle any incentive to spend on improving their products.

</comment></comment></comment></comment></comment><comment><USER7> OpenSolaris was dead long ago, this only opened the eyes to the people optimistic that things will change and there will be a future OpenSolaris release.

"We will determine a simple, cost-effective means of getting enterprise users of prior OpenSolaris binary releases to migrate to S11 Express." -- Says enough.

"We will continue to grow a vibrant developer and system administrator community for Solaris." -- I really wonder how.

<comment><USER13> _"We will continue to grow a vibrant developer and system administrator community for Solaris." -- I really wonder how._

They really killed the wrong Solaris. If they embraced the GNU userland (as OpenSolaris did) they would have had a much better shot at getting more raised-on-Linux admins and developers to embrace their OS. As it is, the current BSD flavored Solaris tools are so crufty and incompatible it leaves many Linux users with a distinct loathing for the OS.

<comment><USER14> Did OpenSolaris use GNU userland? Or are you confusing the official branch with on of the forks? BSD isn't dead, and is different but not in bad ways. Don't bad mouth something (BSD) because you don't use it.

Companies are much less likely to embrace GNU anything, GNU just doesn't fly that way. BSD license is much more permissive, and therefore much more attractive to companies.

<comment><USER15> OpenSolaris had a GNU userland. The BSD ancestry of the Solaris userland isn't the problem. The problem was the senseless defaults and cryptic command structures ("shutdown -g0 -i5 -y" instead of "shutdown")

<comment><USER13> Here is a barbaric and senseless default. Do a crontab -e without $EDITOR set and you'll be dropped into ed. I realize that it's the "standard editor" but the joke stopped being funny when I needed to edit a file with it.

</comment></comment></comment></comment></comment><comment><USER16> Note that this is _not_ the end of source code releases of Solaris:

 _We will continue to use the CDDL license statement in nearly all Solaris source code files. We will not remove the CDDL from any files in Solaris to which it already applies, and new source code files that are created will follow the current policy regarding applying the CDDL (simply, that usr/src files will have the CDDL, and the very small minority of files in usr/closed might not have it). Use of other open licenses in non-ON consolidations (e.g. GPL in the Desktop area) will also continue. As before, requests to change the license associated with source code are case-by-case decisions._

 _We will distribute updates to approved CDDL or other open source- licensed code following full releases of our enterprise Solaris operating system. In this manner, new technology innovations will show up in our releases before anywhere else. We will no longer distribute source code for the entirety of the Solaris operating system in real-time while it is developed, on a nightly basis._

In other words, the Solaris development process is becoming more closed, but you'll still be able to see the source code for any given release. Or at least, that's how I interpret the above.

I'm not in touch enough with Solaris development to know how much of a practical impact this will have--how many non-Sun/Oracle people work on OpenSolaris?

<comment><USER17> It was the nightly basis that allowed a lot of other products (Nexenta) to work well, and get updates faster. It was out of these nightly code drops that OpenSolaris was created ...

</comment></comment><comment><USER18> Since the slogan "don't be evil" is already in use, I'm guessing Oracle is going for "be evil" instead?

<comment><USER19> Sometimes, I admire Oracle more than the supposed do-gooders at Google.

Oracle is a for-profit entity, they will take any legal or tactical advantage they can get (e.g., lawsuit over Java in Android), and they make no bones about it.

I don't like everything they do, but you know what you get with them.

Google says "don't be evil", yet they back off that principle when it's inconvenient (e.g., caving in to Chinese censorship demands, deal with Verizon over net neutrality, etc.).

<comment><USER3> The problem with "Don't be evil" is that it's subjective. Google isn't a hardcore idealist because people that refuse to cooperate unless all of their demands are met never really get anywhere (see RMS). Compromise is a fact of life for everyone. Principles shouldn't be compromised, and you have to draw the line, but you also have to cooperate with people who have a different perspective than yourself.

I don't see either censorship in China or the net neutrality proposal (which I don't know much about) as bonafide "evil". You may disagree, but it's hard to say that they are evil or done with evil intent.

Oracle, on the other hand, is pretty easy to call evil because they act out of cruel self-interest practically exclusively. Oracle is always taking cheap shots.

<comment><USER12> >because people that refuse to cooperate unless all of their demands are met never really get anywhere (see RMS).

RMS would be a clear counterexample. (See Linux, GNU utils, the recent GPLv3 release of Castle Wolfenstein, and many many other victories.) It's a curious sort of logic that says a hardline stance is ineffective because 100% of his goals aren't meant.

Not that moderates don't also serve a purpose, but the radicals are an absolute necessity.

<comment><USER3> I agree that radicals are important and that RMS particularly is useful because he pushes the dialogue forward and keeps new ideas on the table. It's a good goalpost.

But nobody takes RMS's advice as practical. It's just too extreme. Most people don't believe as RMS stated in his recent Reddit interview that the only way to ethically use a pacemaker or other life-saving device that relies on proprietary software would be to start developing an open-source replacement.

RMS has been somewhat successful, but I think much less than he would have been if he hadn't poured so many resources into the silly points that should have easily been let go, like "GNU/Linux".

<comment><USER12> I don't see how "go ahead and use the pacemaker but try and create an alternative solution" is an unrealistic or impractical stance.

</comment></comment></comment></comment></comment></comment><comment><USER20> Oracle will become the most hated company in the world (after mircosoft) when they kill java (because of ineptitude), kill mysql (because they can) and kill opensolaris (oops, they just did it)

<comment><USER2> and oracle will not care, and will continue to make billions of dollars.

(does Oracle have any fans presently?)

</comment></comment><comment><USER21> I thought it was interesting that Linux was completely absent from all of the market position talk.

<comment><USER22> I think everyone who read 'Solaris is the #1 Enterprise Operating System', raised an eyebrow, then read 'We have more than twice the application base of AIX and HP-UX combined' and chuckled.

<comment><USER23> I read that to say 'Solaris is the #1 (SysV-based) Enterprise Operating System'

<comment><USER14> Linux IS SysV-based, though

<comment><USER17> Eh, what? <http://en.wikipedia.org/wiki/UNIX_System_V>

No, Linux is not SysV based.

<comment><USER14> I didn't mean that it was based off of the original UNIX code base, I know my UNIX history better than that. As nailer said, this can be taken two ways and I meant it in the latter. Linux has elements of SysV - it has run levels and the like, unlike BSD's.

</comment></comment></comment></comment></comment></comment><comment><USER24> <sarcasm> Hi, I'm a beginner programmer. I'm interested in learning to program Java and MySQL on Solaris, where should I begin to learn this free and open platform? </sarcasm>

</comment><comment><USER25> hmm... The world is moving to be a more open society. It's not the place where evil can survive. Previously, dictatorship[corp] were allow to live peacefully because they control the media, and pretty much had control of their images. The landscape has changed and everybody is the media. I think it's to google's competitive advantage to be seen as good. I don't think a lot of companies have notice the landscape has changed, so they conduct business as normal.

The game still is survival of the fittest, but for this landscape, the fittest are good.

Without a doubt Google has the popular vote. I constantly hear people compare SUN to Google. Sun died, when? lol

Conceive a scenario where Google died tomorrow; now compare that to when Sun passed[it really did?]. It's not the same thing. "Google" is the most frequently used noun on HN, with almost 3 times the frequency of "Apple" [[http://chegra.posterous.com/word-frequencies-in-front- page-h...](http://chegra.posterous.com/word-frequencies-in-front-page-hn- titles)]

Sun might be good for hackers, but Google takes it to a further extent and brought it to everybody.

Certain companies, besides their shareholders nobody cares if they live or die; nobody is super excited about their product. Nobody is saying they want to go work for them. The only reason why they exist is because they were best of the first movers.

It's common practice when a company gets big in order to innovate it purchases smaller companies. You don't innovate you die. All the big companies employ this strategy(really, when last Apple bought somebody-NeXT?). As an entrepreneur or a Hacker and being aware of the current situation, I think if you were going to sell your company you will stay away from Oracle; they will kill your culture. Also, given their business nature, they might even undercut you; it's more to your advantage to do business with someone who is good. And this is where I think Oracle has lost its advantage, it wouldn't be able to innovate.

</comment><comment><USER26> Honestly, it was the SUN who killed themselves, not ORACLE. ORACLE is just the catalyst.

</comment><comment><USER27> If at least ZFS can be salvaged from the wreck...

<comment><USER28> No way. NetApp will rabidly chase and kill whoever dares trying building commercial ZFS applications based upon OpenSolaris or *BSD (CDDL doesn't cover you against patents infringements, remember?).

I know a well-known privately-held extremely-high-end storage company who just canned its OpenSolaris/ZFS projects because they won't take the risk to be sued by NetApp.

ZFS as open-source is cold dead. Sad, but true.

<comment><USER29> The only exposure that ZFS has is Patent Based. Some of the interesting ones are expiring in the next four to five years:

[http://www.google.com/patents?as_q&num=10&btnG=Googl...](http://www.google.com/patents?as_q&num=10&btnG=Google%20Search&as_epq&as_oq&as_eq&as_pnum&as_vt&as_pinvent&as_pasgnee=%22Network%20Appliance%22&scoring=2)

They'll all expire eventually. ZFS (like) file systems will eventually be very succesful.

<comment><USER28> > They'll all expire eventually. ZFS (like) file systems will eventually be > very succesful.

Yes, that's all in the "like". In 4 or 5 years, btrfs and others will mature and ZFS will look less exceptional. That, and ZFS has a major culprit which will become more annoying with time : it's not cluster-aware.

</comment></comment></comment></comment><comment><USER30> Isn't the good part of being open-source, that you can fork it at any point?

If there is any interest in OpenSolaris, someone will fork it and continue the development.

<comment><USER30> the fork: <http://www.illumos.org/>

</comment></comment><comment><USER31> <http://www.youtube.com/watch?v=djZFHTa6TfA>

</comment><comment><USER32> Uh, opensolaris has been dead ever since linux 1.4.x</comment>


Ask HN: What does a living room not centered on a TV look like? - <AUTHOR>

Almost all of the living rooms I have ever seen are centered on a TV. The TV holds the most prominent and visible place in the room. There's a couch facing the TV and all of the remaining stuff - chairs, tables, lamps, plants - supports watching TV.<p>What does a living room that is not centered on watching TV look like? <comment><USER2> We have two sofas facing one-another with a table in-between, window to one side of the table.

In houses here in Norway living rooms are often divided into 2 or 3 sections, where there is a dining area, a sofa(s) & chairs around a table area and a TV 'corner' with what I believe Americans call a 'lazy-boy' (a reclining, swivel chair?) pointing at a TV. In our house we don't have the TV area because computers have replaced the TV but this is considered very poor by some people who think watching on anything smaller than 50" is like washing dishes in a filthy stream.

</comment><comment><USER3> My best interior design skills would tell me to have part of the room with seating facing inward, maybe toward a fireplace, for conversation. And then maybe a more open area, with a coffee table perhaps?

You don't want all the seating to be in a big circle around the room. I'd break it up into groups of seating focused on different parts of the room.

</comment><comment> xkcd-sucks Almost all of the living rooms I have ever seen are centered around a table. The table holds the central place in the room. There's couches surrounding the table and all of the remaining stuff - speakers, lamps, plants, crap on the table - supports doing drugs.

</comment><comment><USER4> Our living room is centered around the fireplace. In our last home—which didn't have a fireplace—the (very small) living room had furniture arranged in a semi-circle, opening toward the doorways.</comment>