<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ck4NSX87fip7ImA9WxFUFUk.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882</id><updated>2010-06-26T10:29:58.106+02:00</updated><title>Wardrobe strength</title><subtitle type="html">Good enough thoughts</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://journal.thobe.org/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://journal.thobe.org/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Tobias</name><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/thobe/wardrobe" /><feedburner:info uri="thobe/wardrobe" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CE4BSXY5fyp7ImA9WxBTGE4.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-4827710697353096411</id><published>2009-12-15T00:22:00.000+01:00</published><updated>2009-12-15T00:22:38.827+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-15T00:22:38.827+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Django" /><category scheme="http://www.blogger.com/atom/ns#" term="neo4j" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Seamless Neo4j integration in Django</title><content type="html">&lt;p&gt;
About a year ago I gave a &lt;a href="http://www.parleys.com/display/PARLEYS/Home#slide=1;title=Jython;talk=30375937"&gt;presentation&lt;/a&gt; at &lt;a href="http://www.devoxx.com/display/JV08/Home"&gt;Devoxx&lt;/a&gt; where I showed off how easy it was to use any Java library with Django in Jython. The library I demonstrated this with was of course &lt;a href="http://www.neo4j.org/"&gt;Neo4j&lt;/a&gt;. I had written some code for using Neo4j to define models for Django, and now it is ready to be released for you to use it.
&lt;/p&gt;
&lt;!-- TODO: get in 'how': Integrates on a model layer, replacing the ORM, like what google did to integrate bigtable with django for appengine - Not a DB-engine from the Django perspective, since there is no SQL. --&gt;
&lt;p&gt;
The way that the integration between Django and Neo4j is implemented is in the Model layer. Since Neo4j does not have a SQL engine it would not have been efficient or practical to implement the support as a database layer for Django. Google did their implementation in the same way when they integrated BigTable with Django for App Engine. This means that there will be some minor modifications needed in your code compared to using &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt; or &lt;a href="http://www.mysql.com/"&gt;MySQL&lt;/a&gt;. Just as with BigTable on App Engine, you will have to use a special library for defining your models when working with Neo4j, but the model definition is &lt;i&gt;very&lt;/i&gt; similar to Djangos built in ORM. With persistence systems that integrate on the database layer the only difference is in configuration, but that requires the database to fit the mold of a SQL database.
&lt;/p&gt;
&lt;h2&gt;Why the **** has this taken a year to finish?&lt;/h2&gt;
&lt;p&gt;&lt;i&gt;Short answer:&lt;/i&gt; &lt;a href="http://pragprog.com/titles/tpp/the-pragmatic-programmer"&gt;&lt;abbr title="The Pragmatic Programmer, page 2"&gt;The cat ate my source code&lt;/abbr&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
A mess of symlinks that stemmed from the fact that Jython didn't have good support for &lt;a href="http://pypi.python.org/pypi/setuptools"&gt;setuptools&lt;/a&gt; when I started writing this code actually lead to the complete loss of my source code. But to be honest the code wasn't that good anyways. I wanted to add support for &lt;a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/"&gt;Django's administration interface&lt;/a&gt;, and I knew that undertaking would require a complete rewrite of my code. A complete rewrite is done and now it will be possible for me to support the administrative interface of Django in the next release. So why not until now, a year after the first prototype? I was working on other things, it's that simple.
&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;
While the demonstration I gave a year ago was geared towards Jython, since that was the topic of the presentation, the &lt;a href="http://components.neo4j.org/neo4j.py/"&gt;Python bindings for Neo4j&lt;/a&gt; work equally well with CPython. That is all you need, Neo4j and Django, the Python bindings for Neo4j comes with a Django integration layer built in as of the most recent revisions in the repository. The source distribution also contains a few sample applications for demonstrating how the integration works. The Django integration is still in a very early stage of development, but the base is pretty solid, so new features should be much easier to add now. Since the state is pre-alpha, installation from source is the only option at the moment. Let me walk you through how to get things up and running:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set up and activate a &lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt; for your development. This isn't strictly necessary, but it's &lt;b&gt;so&lt;/b&gt; nice to know that you will not destroy your system Python installation if you mess up. Since we got Jython to support virtualenv I use it for everything. If you use CPython your virtualenv will contain a &lt;code&gt;python&lt;/code&gt; executable, and if you use Jython it will contain a &lt;code&gt;jython&lt;/code&gt; executable, I will refer to either simply as &lt;i&gt;&lt;code&gt;python&lt;/code&gt;&lt;/i&gt; from here on, but substitute for that for &lt;code&gt;jython&lt;/code&gt; if you, like me, prefer that implementation.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;If you are using CPython:&lt;/i&gt; Install &lt;a href="http://sourceforge.net/projects/jpype/files/"&gt;JPype&lt;/a&gt;, it is currently a dependency for accessing the JVM-based core of Neo4j from CPython:&lt;pre&gt;
$ unzip &lt;abbr title="JPype 0.5.4.1 is the most recent release at the time of writing"&gt;JPype-0.5.4.1.zip&lt;/abbr&gt;
$ cd &lt;abbr title="JPype 0.5.4.1 is the most recent release at the time of writing"&gt;JPype-0.5.4.1&lt;/abbr&gt;
$ python setup.py install
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Check out the source code for the Python bindings for Neo4j, and install it:&lt;pre&gt;
$ svn co https://svn.neo4j.org/components/neo4j.py/trunk neo4j-python
$ cd neo4j-python
$ python setup.py install
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Install Django:&lt;pre&gt;
$ easy_install django
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Create a new Django project:&lt;pre&gt;
$ django-admin.py startproject neo4django
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Create a new app in your Django project:&lt;pre&gt;
$ python neo4django/manage.py startapp business
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Set up the configuration parameters for using with Neo4j in Django by adding the following configurations to your &lt;code&gt;settings.py&lt;/code&gt;:&lt;pre name="code" class="python"&gt;
NEO4J_RESOURCE_URI = '/var/neo4j/neo4django'
# NEO4J_RESOURCE_URI should be the path to where
#    you want to store the Neo4j database.

NEO4J_OPTIONS = {
    # this is optional and can be used to specify
    # extra startup parameters for Neo4j, such as
    # the classpath to load Neo4j from.
}
&lt;/pre&gt;You can ignore the default Django configurations for RDBMS connections if you only plan to use Neo4j, but if you want to use Djangos built in Admin interface (not supported with Neo4j quite yet) or authentication module you will need to configure this.&lt;/li&gt;
&lt;li&gt;You are now ready to create your first Neo4j backed domain objects for your Django application, by editing &lt;code&gt;business/models.py&lt;/code&gt;. Let's create a simple model for companies with owners and employees:&lt;pre name="code" class="python"&gt;
from neo4j.model import django_model as model

class Person(model.NodeModel):
    first_name = model.Property()
    last_name = model.Property()
    def __unicode__(self):
        return u"%s %s" % (self.first_name, self.last_name)

class Company(model.NodeModel):
    name = model.Property(indexed=True)
    owners = model.Relationship(Person,
        type=model.Outgoing.OWNED_BY,
        related_name="owns",
    )
    employees = model.Relationship(Person,
        type=model.Incoming.WORKS_AT,
        related_name="employer",
        related_single=True, # Only allow Persons to work at one Company
    )
    def __unicode__(self):
        return self.name
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;That's it, you've created your first Django domain model using Neo4j, let's try it out:&lt;pre&gt;
$ python neo4django/manage.py shell
&gt;&gt;&gt; from neo4django.business import models
&gt;&gt;&gt; seven_eleven = models.Company.objects.create(name="Seven Eleven")
&gt;&gt;&gt; seven_eleven.employees.add(
...     models.Person.objects.create(
...         first_name="Sally", last_name="Getitdone"),
...     models.Person.objects.create(
...         first_name="John", last_name="Workerbee"))
&gt;&gt;&gt; seven_eleven.save() # store the newly created relationships
&gt;&gt;&gt; people = list(seven_eleven.employees.all())
&gt;&gt;&gt; someone = people[0]
&gt;&gt;&gt; print someone, "works at", someone.employer
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Notice how the model objects are compatible with model objects created using Djangos built in ORM, making it easy to port your existing applications to a Neo4j backend, all you need to change is the model definitions. For more examples, see the example directory in the repository:
&lt;a href="https://svn.neo4j.org/components/neo4j.py/trunk/src/examples/python/"&gt;https://svn.neo4j.org/components/neo4j.py/trunk/src/examples/python/&lt;/a&gt;.
&lt;/p&gt;
&lt;h2&gt;Future evolution&lt;/h2&gt;
&lt;p&gt;
There is still more work to be done. As this is the first release, there are likely to be bugs, and I know about a few things (mainly involving querying) that I have not implemented support for yet. I also have a list of (slightly bigger) features that I am going to add as well, to keep you interested, I'll list them with a brief explanation:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Add support for the Django admin interface.&lt;/i&gt; You should be able to manage your Neo4j entities in the Django administration interface, just as you manage ORM entities. To do this I need to dig further into the internals of the admin source code, to find out what it expects from the model objects to be able to pick up on them and manage them. The hardest part with this is that the admin system has a policy of silent failure, meaning that it will not tell me how my code violates its expectations.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Add support for Relationship models.&lt;/i&gt; Currently you can only assign properties to nodes in the domain modeling API, you should be able to have entities represented by relationships as well. The way you will do this is by extending the &lt;code&gt;Relationship&lt;/code&gt;-class.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Add a few basic property types.&lt;/i&gt; I will add support for creating your own property types by extending the &lt;code&gt;Property&lt;/code&gt;-class (this is implemented already, but not tested, so if it works it's only by accident). I will also add a few basic subtypes of &lt;code&gt;Property&lt;/code&gt;, a &lt;a href="http://docs.python.org/library/datetime.html"&gt;&lt;code&gt;datetime&lt;/code&gt;&lt;/a&gt; type at the very least. I will also add support for choosing what kind of index to use with each indexed property, in the case of &lt;code&gt;datetime&lt;/code&gt; a &lt;a href="http://components.neo4j.org/index-util/apidocs/org/neo4j/util/timeline/TimelineIndex.html"&gt;&lt;code&gt;Timeline&lt;/code&gt;-index&lt;/a&gt; seems quite natural for example... Supporting enumerated values for Properties is also planned, i.e. limiting the set of allowed values to an enumerated set of values.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Tapping in to the power of Neo4j.&lt;/i&gt; By adding support for methods that do arbitrary operations on the graph (such as &lt;a href="http://components.neo4j.org/neo4j.py/apidoc/traverse.html"&gt;traversals&lt;/a&gt;), and where the returned nodes are then automatically converted to entity objects. I think this will be a really cool and powerful feature, but I have not worked out the details of the API yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Report any bugs you encounter to either the &lt;a href="https://trac.neo4j.org/"&gt;Neo4j bug tracker&lt;/a&gt;, or on the &lt;a href="https://lists.neo4j.org/mailman/listinfo/user"&gt;Neo4j mailing list&lt;/a&gt;. Suggestions for improvements and other ideas are also welcome on the mailing list, to me personally, or why not as a comment on this blog.
&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;b&gt;Happy Hacking&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-4827710697353096411?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ajbbc0V6sNc:b6sXhN8HZa4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ajbbc0V6sNc:b6sXhN8HZa4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ajbbc0V6sNc:b6sXhN8HZa4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ajbbc0V6sNc:b6sXhN8HZa4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ajbbc0V6sNc:b6sXhN8HZa4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ajbbc0V6sNc:b6sXhN8HZa4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ajbbc0V6sNc:b6sXhN8HZa4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/ajbbc0V6sNc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/4827710697353096411/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=4827710697353096411" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4827710697353096411?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4827710697353096411?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/ajbbc0V6sNc/seamless-neo4j-integration-in-django.html" title="Seamless Neo4j integration in Django" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>6</thr:total><feedburner:origLink>http://journal.thobe.org/2009/12/seamless-neo4j-integration-in-django.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MDRXczfCp7ImA9WxJaFk0.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5663045085418801164</id><published>2009-08-07T01:28:00.001+02:00</published><updated>2009-08-07T01:31:14.984+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-07T01:31:14.984+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="integration" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Java integration in future Jython</title><content type="html">&lt;p&gt;
I've &lt;a href="http://fiber-space.de/wordpress/?p=858"&gt;seen&lt;/a&gt; &lt;a href="http://fiber-space.de/wordpress/?p=908"&gt;a lot&lt;/a&gt; &lt;a href="http://fiber-space.de/wordpress/?p=1047"&gt;of this&lt;/a&gt; &lt;a href="http://fiber-space.de/wordpress/?p=1059"&gt;lately&lt;/a&gt;, so I thought that it was time for an actual Jython developer (myself) to share some ideas on how Java integration in Jython could be improved. At the same time I'd like to propose some changes that could make the different Python implementations more unified, and even could lead to a common Java integration API in all of them.
&lt;/p&gt;
&lt;p&gt;
The most basic part of the Java integration in Jython is the ability to import and use Java classes. This is impossible for other Python implementations to do in the same way, and thus breaks compatibility fundamentally. I therefore propose that we remove this functionality as it is in Jython today (!). Instead we should look at how IronPython enables using CLR (.NET) classes. In IronPython you first need to &lt;code&gt;import clr&lt;/code&gt; before you can access any of the CLR types. The same is done in other languages on the JVM as well, for example JRuby where you need to &lt;code&gt;require 'java'&lt;/code&gt; before using any Java libraries. I propose we require something similar in Jython, and what better package to require you to import than &lt;code&gt;java&lt;/code&gt;?
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;An observation:&lt;/i&gt; The &lt;code&gt;java&lt;/code&gt; package in Java does not contain any classes, only sub-packages. Furthermore all the sub-packages of the &lt;code&gt;java&lt;/code&gt; package follow the Java naming conventions, i.e. They all start with a lowercase letter. This gives us a name space to play with: anything under the &lt;code&gt;java&lt;/code&gt; package that starts with an uppercase letter.
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;What happens when you &lt;code&gt;import java&lt;/code&gt;?&lt;/i&gt; The &lt;code&gt;java&lt;/code&gt; Python module is a "magic module" that registers a Python import hook. This import hook will then enable you to import real Java packages and classes. In Jython many of the builtin libraries will of course &lt;code&gt;import java&lt;/code&gt;, which means that this will be enabled by default in Jython. But writing code that is compatible across Python implementations would now be possible, by simply ensuring that you &lt;code&gt;import java&lt;/code&gt; before any other Java packages.
&lt;/p&gt;
&lt;h2&gt;The content of the &lt;code&gt;java&lt;/code&gt; module&lt;/h2&gt;
&lt;p&gt;
Most if not all of what is needed to utilize Java classes from Python code is provided by the import hook that the &lt;code&gt;java&lt;/code&gt; module registers when it is loaded. This means that the content of the &lt;code&gt;java&lt;/code&gt; module needs to deal with the other direction of the interfacing: defining and implementing APIs in Python that Java code can utilize. I propose that the Python &lt;code&gt;java&lt;/code&gt; module contain the following:
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;JavaClass&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;A class decorator that exposes the decorated class as a class that can be accessed from Java. Accepts a &lt;code&gt;package&lt;/code&gt; keyword argument for defining the Java package to define the class in, if omitted it is derived from the __module__ attribute of the class.&lt;br /&gt;Possibly &lt;code&gt;JavaClass&lt;/code&gt; should also be the Python type of imported Java classes.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;Field&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;An object for defining Java fields in classes. Takes a single argument, the type of the field. Example usage:&lt;pre name="code" class="python"&gt;@java.JavaClass
class WithAField:
    data = java.Field(java.lang.String)
&lt;/pre&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;An object for defining Java arrays. This is used to define Java array types. Examples:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Array[java.Primitive.int]&lt;/code&gt; corresponds to the Java type &lt;code&gt;int[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array[java.lang.String]&lt;/code&gt; corresponds to the Java type &lt;code&gt;java.lang.String[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array&lt;/code&gt; corresponds to the Java type &lt;code&gt;java.lang.Object[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array[Array[java.lang.String]]&lt;/code&gt; corresponds to the Java type &lt;code&gt;java.lang.String[][]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;Access&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;A set of Java access definition decorators. Contains:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access.public&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access.package&lt;/code&gt; - this needs to be explicitly available since it does not make sense as the default in Python code.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access.protected&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access.module&lt;/code&gt; - for the new access modifier in the upcoming module system (a.k.a. Project Jigsaw) for Java.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access.private&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The default access modifier should either be &lt;code&gt;public&lt;/code&gt; or the absence of an access modifier decorator would mean that the method is not exposed in the Java class at all. This needs further discussion.&lt;/li&gt;
&lt;/ul&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;Primitive&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;The set of primitive types in Java:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Primitive.void&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.boolean&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.byte&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.char&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.short&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.long&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.float&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Primitive.double&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;These can be used as type parameters for &lt;code&gt;Array&lt;/code&gt; but not for Generic types (Since primitives are not allowed as generic type parameters in Java).&lt;/li&gt;
&lt;/ul&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;Overload&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;Used to implement (and define) overloaded methods, several different methods with the same name, but different type signatures. Example usage:&lt;code&gt;&lt;pre name="code" class="python"&gt;
@java.JavaClass
class WithOverloadedMethod:
    @java.Access.public
    def method(self, value:java.lang.String) -&gt; java.util.List[java.lang.String]:
        ...
    @java.Overload(method)
    @java.Access.public
    def method(self, value:java.lang.Integer) -&gt; java.lang.String:
        ...
    @java.Overload(method)
    @java.Access.public
    def method(self, value:java.lang.Iterable[java.lang.String]) -&gt; java.Primitive.void:
        ...
&lt;/pre&gt;&lt;/code&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;
Java classes and interfaces, when imported, are Pythonized in such a way that they can be used as bases for Python classes. Generics are specified by subscripting the generic Java class. Java annotations are Pythonized in a way that turns them into decorators that add a special attribute to the decorated element: &lt;code&gt;__java_annotations__&lt;/code&gt;. Annotations on imported Java classes and methods would also be exposed through the &lt;code&gt;__java_annotations__&lt;/code&gt; property for consistency. &lt;code&gt;Access&lt;/code&gt; modifiers would similarly add a &lt;code&gt;__java_access__&lt;/code&gt; property to the object they decorate.
&lt;/p&gt;
&lt;p&gt;
Kay Schluer also suggested allowing &lt;a href="http://fiber-space.de/wordpress/?p=1047"&gt;decorators on assignments&lt;/a&gt;, to be able to support annotations on fields. I don't really have an opinion on this. Since I don't think fields should be exported in any public API anyway it's a bit useless, and for the the cases where fields are used (such as dependency injection systems) I think it suffices to have it all in the same assignment: &lt;code&gt;dependency = javax.inject.Inject(java.Access.private(java.Field(JavaClassIDependOn)))&lt;/code&gt;, the name will be extracted to be "&lt;code&gt;dependency&lt;/code&gt;" when the class is processed by the &lt;code&gt;JavaClass&lt;/code&gt; class decorator. But if others find assignment decorators useful, I am not opposed to them. If assignment decorators are added to Python, it might be worth considering having a slightly different signature for these decorator function, so that the name of the target variable is passed as a parameter as well. Then my example could look like this:
&lt;/p&gt;
&lt;code&gt;&lt;pre name="code" class="python"&gt;
@java.JavaClass
class WithInjectedDependency:
    @javax.inject.Inject # This is &lt;a href="http://jcp.org/en/jsr/detail?id=330"&gt;JSR 330&lt;/a&gt; by the way
    @java.Access.private
    @java.Field
    dependency = JavaClassIDependOn
    # could expand to: dependency = javax.inject.Inject(
    #     "dependency", java.Access.private(
    #         "dependency", java.Field(
    #             "dependency", JavaClassIDependOn)))
    # or to the same thing as above, depending on how
    # assignment decorators were implemented...
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
When defining methods in Java integration classes we use Python 3 function annotations to define the method signatures. These can be omitted, the default types in that case would of course be &lt;code&gt;java.lang.Object&lt;/code&gt;. It is important that we support exposing classes that don't have any Java integration added to them from Jython, since we want to enable importing existing Python libraries into Java projects and use them without having to port them. These classes will not have the &lt;code&gt;JavaClass&lt;/code&gt; decorator applied to them. Instead this will be done automatically by Jython at the point when the Python class first need to expose a class to Java. This is not something that the &lt;code&gt;java&lt;/code&gt; module need to deal with, since it doesn't fit with other Python implementations.
&lt;/p&gt;
&lt;h2&gt;Outstanding issues&lt;/h2&gt;
&lt;p&gt;
There are still a few Java integration issues that I have not dealt with, because I have not found a solution that I feel good about yet.
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Defining Java interfaces&lt;/dt&gt;&lt;dd&gt;Is this something we need to be able to do? If so, the proper approach is probably to add a &lt;code&gt;JavaInterface&lt;/code&gt; decorator to the &lt;code&gt;java&lt;/code&gt; module, similar to the &lt;code&gt;JavaClass&lt;/code&gt; decorator.&lt;/dd&gt;
&lt;dt&gt;Defining Java enums&lt;/dt&gt;&lt;dd&gt;This might be something that we want to support. I can think of two options for how to declare the class. Either we add a &lt;code&gt;JavaEnum&lt;/code&gt; decorator to the &lt;code&gt;java&lt;/code&gt; module, or we add special case treatment for when a class extends &lt;code&gt;java.lang.Enum&lt;/code&gt; (I am leaning towards this approach). Then we need to have some way to define the enum instances. Perhaps something like this:&lt;code&gt;&lt;pre name="code" class="python"&gt;
@java.JavaClass
class MyEnum(java.lang.Enum):
    ONE = java.EnumInstance(1)
    TWO = java.EnumInstance(2, True)
    THREE = java.EnumInstance(3, True)
    FOUR = java.EnumInstance(4)
    def __init__(self, number, is_prime=False):
        self.number = number
        self.is_prime = is_prime
    def __str__(self):
        return self.name()
    class SEVENTEEN(java.EnumInstance):
        """This is an enum instance with specialized behavior.
        Will extend MyEnum, but there will only be one instance."""
        def __init__(self):
            """This class gets automatically instantiated
            by the __metaclass__ of Enum."""
            self.number = 17
            self.is_prime = True
        def __str__(self):
            return "The most random number there is."
&lt;/pre&gt;&lt;/code&gt;&lt;/dd&gt;
&lt;dt&gt;Defining generic types&lt;/dt&gt;&lt;dd&gt;I have discussed how to specify type parameters for generic types, but how would you &lt;i&gt;define&lt;/i&gt; a generic Java type in Python? How about something like this:&lt;code&gt;&lt;pre name="code" class="python"&gt;
@java.JavaClass
class GenericClass:
    T = java.TypeParameter() # default is "extends=java.lang.Object"
    C = java.TypeParameter(extends=java.util.concurrent.Callable)
&lt;/pre&gt;&lt;/code&gt;This gets complicated when wanting to support self references in the type parameters, but the same is true for implemented interfaces, such as:&lt;code&gt;&lt;pre name="code" class="java"&gt;
class Something implements Comparable&amp;lt;? extends Something&amp;gt; {
    ...
}
&lt;/pre&gt;&lt;/code&gt;&lt;/dd&gt;
&lt;dt&gt;Defining Java annotations&lt;/dt&gt;&lt;dd&gt;I have dealt with supporting the use of Java annotations, but what about defining them? I highly doubt that defining Java annotations in Python is going to be useful, but I prefer to not underestimate what developers might want to do. I do however think we could get far without the ability to define Java annotations in Python, but if we were to support it, what would it look like? Defining the class would probably be a lot like how enums are defined, either by special casing &lt;code&gt;java.lang.annotation.Annotation&lt;/code&gt; or providing a special &lt;code&gt;java.Annotation&lt;/code&gt; decorator.&lt;code&gt;&lt;pre name="code" class="python"&gt;
@java.JavaInterface
class MyAnnotation(java.lang.annotation.Annotation):
    name = java.AnnotationParameter(java.lang.String)
    description = java.AnnotationParameter(java.lang.String, default="")
&lt;/pre&gt;&lt;/code&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2&gt;&lt;code&gt;java&lt;/code&gt; for other Python implementations&lt;/h2&gt;
&lt;p&gt;
I mentioned that requiring the user to explicitly &lt;code&gt;import java&lt;/code&gt; to make use of Java classes would make it possible for other Python implementations to support the same Java integration API. So what would the default implementation of the &lt;code&gt;java&lt;/code&gt; module look like? There is a very nice standardized API for integrating with Java from other external programming languages: JNI. The default &lt;code&gt;java&lt;/code&gt; module would simply implement the same functionality as the Jython counterpart by interacting with JNI using &lt;code&gt;ctypes&lt;/code&gt;. Since &lt;code&gt;ctypes&lt;/code&gt; is supported by all Python implementations (Jython support is under development) the &lt;code&gt;java&lt;/code&gt; integration module would work across all Python implementations without additional effort. Right there is a major advantage over JPype and JCC (the two major Java integration modules for CPython today).
&lt;/p&gt;
&lt;h2&gt;Integration from the Java perspective&lt;/h2&gt;
&lt;p&gt;
I have not given as much thought to the area of utilizing Python code from Java. Still this is one of the most important tasks for Jython to fulfill. This section is therefore just going to be some ideas of what I want to be able to do.
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Use Python for application scripting&lt;/dt&gt;&lt;dd&gt;This is possible today, and a quite simple case, but I still think that it can be improved. Specifically the problem with Jython today is that there is no good API for doing so. Or to be frank, there is hardly an API at all. This is being improved upon though, the next update of Jython will include an updated implementation of the Java Scripting API, and the next release will introduce a first draft of a proper Jython API, something that we will support long term after a few iterations, and that you can build your applications against.&lt;/dd&gt;
&lt;dt&gt;Use Jython to implement parts of your application&lt;/dt&gt;&lt;dd&gt;We want to be able to write an polyglot applications, where parts of it is implemented in Python. This is more than just scripting the application. Applications generally work without scripts. We want to be able to write the implementation of parts of an application in Python with Jython. This is possible today, but a bit awkward without an official Jython API. This is being worked on in a separate project called &lt;a href="http://kenai.com/projects/plyjy"&gt;PlyJy&lt;/a&gt;, where we are experimenting with an API for creating object factories for Jython. Jython object factories are objects that call into a Python module, instantiate a Python class, conforms it to a Java interface and returns it. So far this project is looking good and there is a good possibility that this will get included in the Jython API.&lt;/dd&gt;
&lt;dt&gt;Directly link (Java) applications to Python code&lt;/dt&gt;&lt;dd&gt;This is where things are starting to get advanced. It would be nice if you could write a library in Python (or import an existing one) and link your Java code with the classes and functions defined in that library directly. This would require Jython to generate Java proxies, actual Java classes where the methods correspond to the actual signatures, with proper constructors and the things you would need to use it like any other Java code, while hiding away the dynamic aspects that make it Python. This could either be done through a compilation step, where some Jython proxy compiler generates the proxies that the Java code can link with, or through utilizing a &lt;code&gt;ClassLoader&lt;/code&gt; that loads a Python module and inspects the content, automatically generating the required proxies. With the &lt;code&gt;ClassLoader&lt;/code&gt; approach javac would need to know about and use it to load signatures from Python code. This is of course where the Java integration decorators described above fits in.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2&gt;What do you think?&lt;/h2&gt;
&lt;p&gt;
I would love to get feedback on these ideas. Either through comments to this entry, via &lt;a href="http://twitter.com/thobe"&gt;Twitter&lt;/a&gt; or on the &lt;a href="https://lists.sourceforge.net/lists/listinfo/jython-dev"&gt;Jython-dev mailing list&lt;/a&gt;.
&lt;/p&gt;
&lt;p style="color: red;"&gt;Please note that the ideas presented in this blog post are my own and does not reflect any current effort in the Jython project.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5663045085418801164?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=GC5AtOMn0lU:xt_F4c8V62A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=GC5AtOMn0lU:xt_F4c8V62A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=GC5AtOMn0lU:xt_F4c8V62A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=GC5AtOMn0lU:xt_F4c8V62A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=GC5AtOMn0lU:xt_F4c8V62A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=GC5AtOMn0lU:xt_F4c8V62A:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=GC5AtOMn0lU:xt_F4c8V62A:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/GC5AtOMn0lU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5663045085418801164/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5663045085418801164" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5663045085418801164?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5663045085418801164?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/GC5AtOMn0lU/java-integration-in-future-jython.html" title="Java integration in future Jython" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>6</thr:total><feedburner:origLink>http://journal.thobe.org/2009/08/java-integration-in-future-jython.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEGR3Y6eSp7ImA9WxJaEE4.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-6510546654023857807</id><published>2009-07-31T13:10:00.000+02:00</published><updated>2009-07-31T13:10:26.811+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-31T13:10:26.811+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rant" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>"Social networking" killed productivity</title><content type="html">&lt;p&gt;
&lt;a href="http://srtsolutions.com/blogs/diannemarsh/archive/2009/07/29/funny-thing-happened-to-twitter.aspx"&gt;Twitter has become work&lt;/a&gt;. Not &lt;i&gt;acceptable for work&lt;/i&gt;, i.e. something that is not frowned upon to do at work, but actual work, something you are &lt;i&gt;required to do&lt;/i&gt; at work. At least this is the case if you are involved somewhere where the development team is the marketing team, like a startup or an open source project. For the record my involvement in &lt;a href="http://neo4j.org"&gt;Neo4j&lt;/a&gt; qualify to both categories, and &lt;a href="http://jython.org"&gt;Jython&lt;/a&gt; is most certainly an open source project, and quite a high profile such as well.
&lt;/p&gt;
&lt;p&gt;
In order to stay on top of things in this situation you easily find yourself with push based twitter notification or at least reading a lot of material on a regular basis. I for example get about 150 to 200 tweets per day from the people I follow. Combine this with the expectation to stay on top of email (yet again yo go for push), and you've got a constant stream of interrupts, and this really kills productivity.
&lt;/p&gt;
&lt;p&gt;
Just the other day I read the &lt;i&gt;&lt;a href="http://www.aaronsw.com/weblog/offline2"&gt;Life Offline&lt;/a&gt;&lt;/i&gt; posts by Aaron Swartz, and found that very much recognize myself in &lt;a href="http://www.aaronsw.com/weblog/offline"&gt;how he describes&lt;/a&gt; the problems of the constant online presence. It would be wonderful if I, like he was able to do, could take a long stretch of time away from being connected, but I don't think that is possible, at least not now or in a near future. The problem stands though, I am not being productive. And some things don't get done in time. And this is a problem.
&lt;/p&gt;
&lt;p&gt;
I've tried shifting my email and twitter use to only do processing of these things once per day, but it still takes two hours or more from my day to simply process the incoming stream. By processing I mean:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read all the email and define actions.&lt;/li&gt;
&lt;li&gt;Read all tweets, open tabs for links that seem interesting, skim those pages and define actions.&lt;/li&gt;
&lt;li&gt;Read feeds and define actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
That takes two hours. Then I still have to &lt;i&gt;perform&lt;/i&gt; the actions that I have defined. Which could take up to the rest of the day.
&lt;/p&gt;
&lt;p&gt;
I noticed already about twelve years ago how destructive online communities and social networks could be, and how much time they consume. I have thus tried to stay away from them, which is why I don't use my facebook account. But when social networking has become part of work it is much harder to avoid. In the case of Twitter it is also difficult to ignore because of how hugely influential it is. Twitter is the de facto way to find out about new things and interesting articles.
&lt;/p&gt;
&lt;p&gt;
I am starting to believe that perhaps Donald Knuth made a wise decision in &lt;a href="http://www-cs-staff.stanford.edu/~uno/email.html"&gt;not having an email address&lt;/a&gt;, but as he points out having an email address is for people who need to be on top of things, and that he does not have an email address because he does not have to be on top of things anymore. I will agree with that, Donald Knuth has contributed a lot to the field of computer science, but he is definitely not on top of things anymore. So how do you cope with both being on top of things while still being productive? Is it possible? I would love to get any insight into the secrets that I am obviously unaware of.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-6510546654023857807?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=5SXB91LOA4I:BDwPW9xe4Bs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=5SXB91LOA4I:BDwPW9xe4Bs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=5SXB91LOA4I:BDwPW9xe4Bs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=5SXB91LOA4I:BDwPW9xe4Bs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=5SXB91LOA4I:BDwPW9xe4Bs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=5SXB91LOA4I:BDwPW9xe4Bs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=5SXB91LOA4I:BDwPW9xe4Bs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/5SXB91LOA4I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/6510546654023857807/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=6510546654023857807" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/6510546654023857807?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/6510546654023857807?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/5SXB91LOA4I/social-networking-killed-productivity.html" title="&quot;Social networking&quot; killed productivity" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>3</thr:total><feedburner:origLink>http://journal.thobe.org/2009/07/social-networking-killed-productivity.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ABSHs8cCp7ImA9WxJUFkw.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5603364101570872589</id><published>2009-07-15T01:55:00.000+02:00</published><updated>2009-07-15T01:55:59.578+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-15T01:55:59.578+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>Improving performance in Jython</title><content type="html">&lt;p&gt;
About two weeks ago I published a writeup about my findings about the &lt;a href="http://journal.thobe.org/2009/06/performance-of-synchronization.html"&gt;performance of synchronization primitives in Jython&lt;/a&gt; from my &lt;a href="http://journal.thobe.org/2009/06/javaone-2009-from-my-perspective.html"&gt;presentation at JavaOne&lt;/a&gt;. During the presentation I said that these performance issues were something that I was going to work on, and improve. And indeed I did. I cannot take full credit for this, &lt;a href="http://zyasoft.com/pythoneering/"&gt;Jim Baker&lt;/a&gt; played a substantial part in this work as well. The end result is still something I'm &lt;i&gt;very proud&lt;/i&gt; of since we managed to improve the performance of this benchmark as much as &lt;b&gt;50 times&lt;/b&gt;.
&lt;/p&gt;
&lt;h2&gt;The benchmarks&lt;/h2&gt;
&lt;p&gt;
The comparisons were performed based on the execution of this benchmark script invoked with:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JAVA_HOME=$JAVA_6_HOME jython synchbench.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JAVA_HOME=$JAVA_6_HOME jython -J-server synchbench.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre name="code" class="python"&gt;# -*- coding: utf-8 -*-
from __future__ import with_statement, division

from java.lang.System import nanoTime
from java.util.concurrent import Executors, Callable
from java.util.concurrent.atomic import AtomicInteger

from functools import wraps
from threading import Lock

def adder(a, b):
    return a+b


count = 0
def counting_adder(a, b):
    global count
    count += 1 # NOT SYNCHRONIZED!
    return a+b


lock = Lock()
sync_count = 0
def synchronized_counting_adder(a, b):
    global sync_count
    with lock:
        sync_count += 1
    return a+b


atomic_count = AtomicInteger()
def atomic_counting_adder(a,b):
    atomic_count.incrementAndGet()
    return a+b


class Task(Callable):
    def __init__(self, func):
        self.call = func

def callit(function):
    @Task
    @wraps(function)
    def callable():
        timings = []
        for x in xrange(5):
            start = nanoTime()
            for x in xrange(10000):
                function(5,10)
            timings.append((nanoTime() - start)/1000000.0)
        return min(timings)
    return callable

def timeit(function):
    futures = []
    for i in xrange(40):
        futures.append(pool.submit(function))
    sum = 0
    for future in futures:
        sum += future.get()
    print sum

all = (adder,counting_adder,synchronized_counting_adder,atomic_counting_adder)
all = [callit(f) for f in all]

WARMUP = 20000
print "&amp;lt;WARMUP&amp;gt;"
for function in all:
    function.call()
for function in all:
    for x in xrange(WARMUP):
        function.call()
print "&amp;lt;/WARMUP&amp;gt;"

pool = Executors.newFixedThreadPool(3)

for function in all:
    print
    print function.call.__name__
    timeit(function)
pool.shutdown()

glob = list(globals())
for name in glob:
    if name.endswith('count'):
        print name, globals()[name]
&lt;/pre&gt;
&lt;p&gt;
And the JRuby equivalent for comparison:
&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'java'
import java.lang.System
import java.util.concurrent.Executors
require 'thread'

def adder(a,b)
  a+b
end

class Counting
  def initialize
    @count = 0
  end
  def count
    @count
  end
  def adder(a,b)
    @count = @count + 1
    a+b
  end
end

class Synchronized
  def initialize
    @mutex = Mutex.new
    @count = 0
  end
  def count
    @count
  end
  def adder(a,b)
    @mutex.synchronize {
      @count = @count + 1
    }
    a + b
  end
end

counting = Counting.new
synchronized = Synchronized.new

puts "&amp;lt;WARMUP&amp;gt;"
10.times do
  10000.times do
    adder 5, 10
    counting.adder 5, 10
    synchronized.adder 5, 10
  end
end
puts "&amp;lt;/WARMUP&amp;gt;"

class Body
  def initialize
    @pool = Executors.newFixedThreadPool(3)
  end
  def timeit(name)
    puts
    puts name
    result = []
    40.times do
      result &lt;&lt; @pool.submit do
        times = []
        5.times do
          t = System.nanoTime
          10000.times do
            yield
          end
          times &amp;lt;&amp;lt; (System.nanoTime - t) / 1000000.0
        end
        times.min
      end
    end
    result.each {|future| puts future.get()}
  end
  def done
    @pool.shutdown
  end
end

body = Body.new

body.timeit("adder") {adder 5, 10}
body.timeit("counting adder") {counting.adder 5, 10}
body.timeit("synchronized adder") {synchronized.adder 5, 10}

body.done
&lt;/pre&gt;
&lt;h2&gt;Where we started&lt;/h2&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a style="margin-left: 1em; margin-right: 1em;" imageanchor="1" href="http://1.bp.blogspot.com/_AqkFfcwHF4M/SkN3PyWUW_I/AAAAAAAAAKI/UOdczu0SEOo/s1600-h/DynaLangConcurrency-Counter.png"&gt;
&lt;img border="0" src="http://1.bp.blogspot.com/_AqkFfcwHF4M/SkN3PyWUW_I/AAAAAAAAAKI/UOdczu0SEOo/s320/DynaLangConcurrency-Counter.png"/&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;
A week ago the performance of this Jython benchmark was bad. Compared to the equivalent code in JRuby, Jython required over 10 times as much time to complete.
&lt;/p&gt;
&lt;p&gt;
When I analyzed the code that Jython and JRuby generated and executed, I  came to the conclusion that the reason Jython performed so badly was that the call path from the running code to the actual &lt;code&gt;lock&lt;/code&gt;/&lt;code&gt;unlock&lt;/code&gt; instructions introduced too much overhead for the JVM to have any chance at analyzing and optimizing the lock. I published this analysis in &lt;a href="http://journal.thobe.org/2009/06/performance-of-synchronization.html"&gt;my writeup on the problem&lt;/a&gt;. It would of course be possible to lower this overhead by importing and utilizing the pure Java classes for synchronization instead of using the Jython threading module, but &lt;i&gt;we like how the &lt;code&gt;with&lt;/code&gt;-statement reads&lt;/i&gt; for synchronization:
&lt;/p&gt;
&lt;pre name="code" class="python"&gt;
with lock:
    counter += 1
&lt;/pre&gt;
&lt;h2&gt;Getting better&lt;/h2&gt;
&lt;p&gt;
Based on my analysis of the how the &lt;code&gt;with&lt;/code&gt;-statement compiles and the way that this introduces overhead I worked out the following redesign of the &lt;code&gt;with&lt;/code&gt;-statement context manager interaction that would allow us to get closer to the metal, while remaining compatible with &lt;a href="http://www.python.org/dev/peps/pep-0343/"&gt;PEP 434&lt;/a&gt;:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When entering the &lt;code&gt;with&lt;/code&gt;-block we transform the object that constitutes the context manager to a &lt;a href="http://fisheye3.atlassian.com/browse/~raw,r=6535/jython/trunk/jython/src/org/python/core/ContextManager.java"&gt;&lt;code&gt;ContextManager&lt;/code&gt;&lt;/a&gt;-object.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;If&lt;/b&gt; the object that constitutes the context manager implements the &lt;code&gt;ContextManager&lt;/code&gt; interface it is simply returned. This is where context managers written in Java get their huge benefit by getting really close to the metal.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Otherwise&lt;/b&gt; a default implementation of the &lt;code&gt;ContextManager&lt;/code&gt; is returned. This object is created by retrieving the &lt;code&gt;__exit__&lt;/code&gt; method and invoking the &lt;code&gt;__enter__&lt;/code&gt; method of the context manager object.&lt;/li&gt;
&lt;li&gt;The compiled code of the &lt;code&gt;with&lt;/code&gt;-statement then only invokes the &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt; methods of the returned &lt;code&gt;ContextManager&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;This has the added benefit that even for context managers written in pure Python the &lt;code&gt;ContextManager&lt;/code&gt; could be optimized and cached when we implement call site caching.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
This specification was &lt;a href="http://fisheye3.atlassian.com/browse/~raw,r=6535/jython/trunk/jython/src/org/python/core/ContextGuard.java"&gt;easily implemented&lt;/a&gt; by &lt;a href="http://twitter.com/jimbaker"&gt;Jim&lt;/a&gt; and then he could rewrite the threading module in Java to let the lock implementation take direct benefit of the rewritten &lt;code&gt;with&lt;/code&gt;-statement and thereby get the actual code really close to the locking and unlocking. The result were instantaneous and beyond expectation:
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_AqkFfcwHF4M/Slzk6oaBErI/AAAAAAAAAK0/AWiN9MWvIaI/s1600-h/Old-vs-JRuby-vs-New.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_AqkFfcwHF4M/Slzk6oaBErI/AAAAAAAAAK0/AWiN9MWvIaI/s320/Old-vs-JRuby-vs-New.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;p&gt;
Not only did we improve performance, but we passed the performance of the JRuby equivalent! Even using the client compiler, with no warm up we perform almost two times better than JRuby. Turn on the server compiler and let the JIT warm up and perform all it's compilation and we end up with a speedup of slightly more than &lt;b&gt;50 times&lt;/b&gt;.
&lt;/p&gt;
&lt;p&gt;
A disclaimer is appropriate here. With the first benchmark (before this was optimized) I didn't have time to wait for a full warmup. This because of the fact that the benchmark was so incredibly slow at that point and the fact that I was doing the benchmarks quite late before the presentation and didn't have time to leave it running over the night. Instead I turned down the compilation threshold of the Hotspot server compiler and ran just a few warmup iterations. It is possible that the JVM could have optimized the previous code slightly better given (a lot) more time. The actual speedup might be closer to the speedup from the first code to the new code using the client compiler and no warmup. But this is still a speedup of almost 20 times, which is still something I'm very proud of. There is also the possibility that I didn't run/implement the JRuby version in the best possible way, meaning that there might be ways of making the JRuby version run faster that I don't know about. The new figures are still very nice, much nicer than the old ones for sure.
&lt;/p&gt;
&lt;h2&gt;The current state of performance of Jython synchronization primitives&lt;/h2&gt;
&lt;p&gt;
It is also interesting to compare how the current implementation compares to the other versions in Jython that I included in my presentation:
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/_AqkFfcwHF4M/Slzk_ZV8QfI/AAAAAAAAAK8/PkYPcr8Xjzg/s1600-h/NewClient-vs-NewServer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_AqkFfcwHF4M/Slzk_ZV8QfI/AAAAAAAAAK8/PkYPcr8Xjzg/s320/NewClient-vs-NewServer.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Without synchronization the code runs about three times as fast as with synchronization, but the counter does not return the correct result here due to race conditions. It's interesting from the point of view of analyzing the overhead added by synchronization but not for an actual implementation. Two times overhead is quite good in my opinion. What is more interesting to see is that the fastest version from the presentation, the one using &lt;code&gt;AtomicInteger&lt;/code&gt;, is now suffering from the overhead of reflection required for the method invocations compared to the synchronized version. In a system with more hardware threads (commonly referred to as "cores") the implementation based on &lt;code&gt;AtomicInteger&lt;/code&gt; could still be faster though.
&lt;/p&gt;
&lt;h2&gt;Where do we proceed from here?&lt;/h2&gt;
&lt;p&gt;
Now that we have proven that it was possible to get a nice speedup from this redesign of the code paths the next step is to provide the same kind of optimizations for code written in pure Python. Providing a better version of &lt;a href="http://docs.python.org/library/contextlib.html#contextlib.contextmanager"&gt;&lt;code&gt;contextlib.contextmanager&lt;/code&gt;&lt;/a&gt; that exploits these faster code paths should be the easiest way to improve context managers written in Python. Then there are of course a wide range of other areas in Python where performance could be improved through the same kind of thorough analysis. I don't know at this point what we will focus on next, but you can look forward to many more performance improvements in Jython in the time to come.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5603364101570872589?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=4Xr4bLeGUy4:52rtzsY1DHw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=4Xr4bLeGUy4:52rtzsY1DHw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=4Xr4bLeGUy4:52rtzsY1DHw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=4Xr4bLeGUy4:52rtzsY1DHw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=4Xr4bLeGUy4:52rtzsY1DHw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=4Xr4bLeGUy4:52rtzsY1DHw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=4Xr4bLeGUy4:52rtzsY1DHw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/4Xr4bLeGUy4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5603364101570872589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5603364101570872589" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5603364101570872589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5603364101570872589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/4Xr4bLeGUy4/improving-performance-in-jython.html" title="Improving performance in Jython" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_AqkFfcwHF4M/SkN3PyWUW_I/AAAAAAAAAKI/UOdczu0SEOo/s72-c/DynaLangConcurrency-Counter.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2009/07/improving-performance-in-jython.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cCQXo7eCp7ImA9WxJVGEU.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-3257139503520874782</id><published>2009-07-06T13:51:00.000+02:00</published><updated>2009-07-06T13:51:00.400+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-06T13:51:00.400+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>My view of EuroPython 2009</title><content type="html">&lt;p&gt;
I was not very enthusiastic going to &lt;a href="http://www.europython.eu/"&gt;EuroPython&lt;/a&gt; this year. I don't like it when all I do is fly in, give a talk then fly out again, but that was all I could afford to do for EuroPython. I go to a few conferences in a year, and all of them can be filed under expenses for me, since I don't have an employer that pays for my conference trips. With EuroPython being in Birmingham and the UK not being the cheapest country there is there was no chance for the to afford staying more than two days.
&lt;/p&gt;
&lt;p&gt;
My plane landed Tuesday at lunch time, and my talk was the first talk after the afternoon keynote. I arrived to the venue with about two and a half hours to take care of registration and payment. I had requested to not pay when I registered online and was told that the best solution would be to pay when I arrived. My reason was of course that I didn't have any money when they required my online registration, freelance open source development does not pay every month. The only problem with this was that when I arrived there was no one there to take care of registration, it was only open in the morning. I tried asking a few guys in staff t-shirts, but they were not very helpful, and seemed like they just wanted me to go away. I decided to wait until the next day with my registration and went to see the keynote.
&lt;/p&gt;
&lt;p&gt;
It was nice to get to see Cory Doctorow in person. His keynote was about the copyright war and why it matters to us as developers. Scary stuff. The world that the media industry is forcing on us is all but pleasant. He could even provide examples of actual cases that have already happened where large music publishers have forced open source developers working on projects they didn't like to change profession or face millions of dollars in fines. Not on the basis of the software being illegal (it wasn't), but with a lawsuit on copyright infringement from downloaded MP3 files. He also talked about how the media industry seem to prefer the entire internet to be illegal, along with open source software all together, something that Reinout van Rees has a &lt;a href="http://reinout.vanrees.org/weblog/2009/06/30/europython-cory-doctorow.html"&gt;more complete summary of&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
My presentation on what would make Jython &lt;a href="http://www.slideshare.net/thobe/a-better-python-for-the-jvm-1686090"&gt;a better Python for the JVM&lt;/a&gt; felt like the best presentation I have given to this day. The material was an updated version of &lt;a href="http://www.slideshare.net/thobe/a-better-python-for-the-jvm"&gt;the talk I gave at PyCon&lt;/a&gt; earlier this year. Experience really does make you a better speaker and this was the 11th presentation of my speaker career so far (in less than two years). It really feels good to stand in front of people and talk when a large number of people are nodding and smiling at what you are saying throughout most of the presentation. And the audience was great here, they asked a lot of good questions, both during the presentation and afterwards. I didn't go through all of my slides but I covered all of my material. Some things came more natural with other slides with this crowd, so I altered the talk slightly while doing it. This was a scenario I had prepared for, I was prepared to use the slides in either way, and with this audience I felt more comfortable doing it this way. The only negative aspect of the presentation was the room, it was laid out in such a way that if I stood by my computer I would block parts of the projected screen. I had to switch to my remote control and step away from the computer to allow everyone to see the material, which meant that I could not read my speaker notes on my screen. Fortunately I knew my material well enough.
&lt;/p&gt;
&lt;p&gt;
The rest of the day I went around to a few different talks in the venue, still without badge. Then me and the rest of the Jython team that were there rounded off the day at a chinese restaurant with &lt;a href="http://www.voidspace.org.uk/"&gt;Michael Foord&lt;/a&gt; and some fifteen other attendees, followed by a pint at an outdoor bar before me and Frank headed to our hotel. The food and beer was great but the conference venue and the hotel were not. As I mentioned the venue had a problem with the room I presented in, but being in the basement of the Birmingham Conservatoire it was dark and small, with corridors to all the presentation rooms. Not an ideal place for a conference. The hotel (Premier Inn) was probably the worst I've experienced at a conference so far. When we checked in they were out of twin rooms even though that was what we had ordered, so we had to share a queen size bed. There were not enough towels, no AC, breakfast not included, and only one of our key cards worked. When showering one could choose between scolding hot drizzle, freezing cold shower, or loudly howling pipes. All of this at a rate of £65 per night.
&lt;/p&gt;
&lt;p&gt;
The next morning I made a new attempt at registering. This failed again, this time due to the fact that my registration had not been paid. At this point I felt rather put off by the conference, I had payed for the plane and the hotel, and was expected to pay for entrance to a conference where my talk had been the only rewarding thing. I sent an e-mail to the organizers expressing my disappointment and asking them if they wanted my money and what I should do in order to give it to them. In the response I got they said that if I was not happy then maybe I should not have proposed a talk. How was I supposed to know that I was going to be unhappy about the conference before I got there? EuroPython 2008 in Vilnius was great, I had no reason to expect it to not be good in Birmingham 2009. It took me until the afternoon before I was able to track down the organizers, pay for my registration and get my badge. I did not get a t-shirt since they had made a mess of them and were unable to find a shirt in the size I had ordered.
&lt;/p&gt;
&lt;p&gt;
Now that I was finally registered and all I felt that I had earned the EuroPython dinner that night. This was a very nice addition to the conference, a purely social event with the other attendees. After dinner and a pint at a nice pub I got about four hours of sleep before I headed to the airport. My plane took off at 6:30 am, so I got to the train station at 4 am to catch a sufficiently early train to the airport only to find out that the first train of the day left at 5:30. I had to run when I arrived at the airport with only 20 minutes until final boarding call. With check in luggage I would have never made it, but since I like to travel lightly and only had a small backpack I made it to the gate just after priority boarding had finished. It still would have been much better if the flight had departed an hour or so later, because I had to wait 160 minutes for the bus after I landed in Sweden.
&lt;/p&gt;
&lt;p&gt;
Despite all the problems I think it was worth my time and money to go to EuroPython, the community is great, I love the Python people! But I don't think I'll attend next year unless I get the entire conference payed for. When it's not in Birmingham anymore I'll be more interested in attending again. There were also a number of interesting talks that I will now summarize.
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;a href="http://fwierzbicki.blogspot.com/"&gt;Frank Wierzbicki&lt;/a&gt;'s talk about web frameworks and Jython&lt;/dt&gt;
&lt;dd&gt;Franks talk was right after mine, in the same room. Frank has also become a much better speaker in the past year, and I enjoyed seeing all the web frameworks that we now support with Jython. And the fact stands that for normal applications Jython performs about the same as CPython, which is nice for all of these web frameworks. I tend to forget this since I spend most of my time looking at the places where Jython performance should improve.&lt;/dd&gt;
&lt;dt&gt;&lt;a href="http://www.dcs.gla.ac.uk/~marks/"&gt;Mark Shannon&lt;/a&gt;'s talk about his Python VM "HotPy"&lt;/dt&gt;
&lt;dd&gt;Python is now starting to see the phenomenon that &lt;a href="http://blog.headius.com/"&gt;Charles Nutter&lt;/a&gt; has been &lt;a href="http://blog.headius.com/2009/03/on-benchmarking.html"&gt;talking about&lt;/a&gt; in the Ruby community: a number of new implementations and VMs are popping up and claiming to have better performance on a lot of things for different reasons. HotPy is a research Python VM that builds on a research VM toolkit by Mark Shannon from University of Glasgow. It is not complete but has a good approach to optimization, optimizing the code yields better result than compiling it.&lt;/dd&gt;
&lt;dt&gt;&lt;a href="http://www.tismer.com/Home.html"&gt;Christian Tismer&lt;/a&gt;'s talk about the status of Psyco&lt;/dt&gt;
&lt;dd&gt;This was really impressive to me. Psyco V2 is being released this weekend. An heroic upgrading effort done by Christian alone. Everything about Psyco V2 is impressive. It yields enormous performance boosts to Python, to the point where Christian has started replacing builtin functions that are written in C in CPython with corresponding versions written in Python to improve performance. And properties get about a 100 times speedup with Psyco. I need to look at the source for Psyco and find out which of these optimization techniques we can apply to Jython, and perhaps even in the JVM.&lt;/dd&gt;
&lt;dt&gt;Thursday afternoon keynote about &lt;a href="http://www.bletchleypark.org.uk/"&gt;Bletchley Park&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;a href="http://twitter.com/Dr_Black"&gt;Sue Black&lt;/a&gt; of the &lt;a href="http://www.savingbletchleypark.org/"&gt;Saving Bletchley Park project&lt;/a&gt; and Simon Greenish gave a keynote presentation about Bletchley Park and how they are using social media to attract more visitors. The presentation featured an actual working &lt;a href="http://en.wikipedia.org/wiki/Enigma_machine"&gt;Enigma machine&lt;/a&gt; on stage.&lt;/dd&gt;
&lt;dt&gt;Thursday evening keynote by &lt;a href="http://en.wikipedia.org/wiki/C._A._R._Hoare"&gt;Sir Charles Antony Richard Hoare&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;Tony Hoare talked about the difference between science and engineering. Not the most entertaining talk, I had hoped for some interesting and motivating story on what had been driving his career. It would for example have been great to hear how he came up with the idea for quicksort, or hear about what interesting projects he is working on now. I did like his conclusion that Computer science and Software engineering are still allowed to be imperfect, being a much younger science than for example physics or biology, both of which were just studies of simple observable phenomena when they were at the age that computer science is today. His vision was that at some point in the future software engineering will be the most reliable form of engineering, since software never degrades. I like this vision, but I agree that computer science has to mature and evolve before we can develop zero fault software. Finally his response during Q&amp;A to the question &lt;i&gt;"Is there research that can help marketing come up with specifications so that we engineers can build the software?"&lt;/i&gt; was very entertaining: &lt;i&gt;"That's the engineer's job. Marketing doesn't understand programming. Neither does marketing understand the customers."&lt;/i&gt;.&lt;/dd&gt;
&lt;/dl&gt;
&lt;div style="width:425px;text-align:left" id="__ss_1686090"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/thobe/a-better-python-for-the-jvm-1686090" title="A Better Python for the JVM"&gt;Slideshow - A Better Python for the JVM, EuroPython 2009&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=abetterjython2-090706053440-phpapp02&amp;stripped_title=a-better-python-for-the-jvm-1686090" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=abetterjython2-090706053440-phpapp02&amp;stripped_title=a-better-python-for-the-jvm-1686090" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-3257139503520874782?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=v4924YOtZHc:hI48GRv0qJw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=v4924YOtZHc:hI48GRv0qJw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=v4924YOtZHc:hI48GRv0qJw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=v4924YOtZHc:hI48GRv0qJw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=v4924YOtZHc:hI48GRv0qJw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=v4924YOtZHc:hI48GRv0qJw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=v4924YOtZHc:hI48GRv0qJw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/v4924YOtZHc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/3257139503520874782/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=3257139503520874782" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/3257139503520874782?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/3257139503520874782?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/v4924YOtZHc/my-view-of-europython-2009.html" title="My view of EuroPython 2009" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>1</thr:total><georss:point>52.479442 -1.905189</georss:point><feedburner:origLink>http://journal.thobe.org/2009/07/my-view-of-europython-2009.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AEQn48eCp7ImA9WxJVEUU.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5355216234531009924</id><published>2009-06-28T12:41:00.000+02:00</published><updated>2009-06-28T12:41:43.070+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-28T12:41:43.070+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>Performance of Synchronization primitives in Jython</title><content type="html">&lt;p&gt;
As I pointed out in my &lt;a href="http://journal.thobe.org/2009/06/javaone-2009-from-my-perspective.html"&gt;previous blog post about JavaOne&lt;/a&gt; there are a few points where the performance of Jython is much worse than that of the “competitors”. In this post I provide my analysis of the the performance of Jython in the micro benchmark I used in my presentation. I will compare Jython to JRuby here for three reasons. The first reason is the obvious, Python and Ruby are quite similar languages. This takes us to the second reason, the performance of JRuby and Clojure was not that different in comparison, and it's therefore better to choose the most similar language for comparison. Finally, the third reason, JRuby is a darn good, highly optimized dynamic language implementation. That makes it a good baseline for comparison.
&lt;/p&gt;
&lt;p&gt;
The first diagram shows Jython and JRuby with no contention at all. We can clearly see, as early as in this picture that Jython needs a bit more work in the performance department. I still feel excited about this though. The recent release of Jython, version 2.5, focused heavily on Python compatibility. The next versions will be where we start focusing on performance. The work towards Jython 3.0 is even more exciting here. But that excitement will be saved for a later post.
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_AqkFfcwHF4M/SkN3EnmE5AI/AAAAAAAAAKA/xO8pwKie0fQ/s1600-h/DynaLangConcurrency-NoCounter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_AqkFfcwHF4M/SkN3EnmE5AI/AAAAAAAAAKA/xO8pwKie0fQ/s320/DynaLangConcurrency-NoCounter.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
The second slide shows another version of pretty much the same code, but with a shared, contended resource. Here we find that Jython performs much worse than JRuby. While the JRuby version is about 10 times slower with a contended shared resource, Jython is almost 100 times slower. Why is this?
&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_AqkFfcwHF4M/SkN3PyWUW_I/AAAAAAAAAKI/UOdczu0SEOo/s1600-h/DynaLangConcurrency-Counter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_AqkFfcwHF4M/SkN3PyWUW_I/AAAAAAAAAKI/UOdczu0SEOo/s320/DynaLangConcurrency-Counter.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h2&gt;The effect of the implementation&lt;/h2&gt;
&lt;p&gt;
I have already mentioned the first reason for JRuby performing better than Jython. It applies here as well. The JRuby team has spent more time on performance tuning than the Jython team, this is something we will be able to improve. In fact this plays a bigger part than one might think.
&lt;/p&gt;
&lt;p&gt;
The JRuby Mutex implementation is written in about a page of plain old Java (not that important) that gets compiled to a small number of simple bytecodes (more important). Because a closure or block in JRuby is just an object with a method containing the compiled bytecode (compared to a function that contains argument parsing logic before that), the dispatch from the synchronization code to the guarded code is just a simple virtual call. For the call into the synchronization code there are two VM level calls, since this is a JRuby &lt;i&gt;method&lt;/i&gt;. First there is the call to the dispatch logic and argument parsing, then the call to the actual code for the synchronization code. Much of the work of the first call is cached by JRubys call site cache from the first invocation so that subsequent invocations are much faster.
&lt;/p&gt;
&lt;p&gt;
The Jython implementation on the other hand has no call site caching. So each call does full dispatch and argument parsing. The call structure is also different. A &lt;a href="http://www.python.org/dev/peps/pep-0343/"&gt;&lt;i&gt;with statement&lt;/i&gt;&lt;/a&gt; in Python is just a &lt;code&gt;try/except/finally&lt;/code&gt; block with simplified syntax, where the &lt;i&gt;context manager&lt;/i&gt; (a lock in this case) is called for setup before the block inside the &lt;i&gt;with statement&lt;/i&gt; and then invoked again after the with statement block completes.
&lt;/p&gt;
&lt;p&gt;
In shorter terms: JRuby has much lower call overhead on the VM level. This makes a difference because a call is a call, and even when in-lined it imposes some overhead. It is also important because the JVM is better at making optimizations across few levels of calls than across several. Still, this only explains a small part of the difference seen in the chart.
&lt;/p&gt;

&lt;h2&gt;The incredible benefit of closures&lt;/h2&gt;
&lt;p&gt;
Most JVMs has built in support for analyzing and optimizing locks. In order to be able to do that it needs to have the the entire synchronized region in one compilation unit, i.e. both the lock instruction and the unlock instruction needs to be in the same compilation unit. Due to the fact that code analysis is super-linear there is a limit to how big a compilation unit is allowed to be. Initially a compilation unit corresponds to a Java bytecode method, but may grow as an effect of code in-lining (up to the compilation unit size limit). The key to get good performance from synchronized regions is therefore to either have both the lock and unlock instructions in the same method, or at least in a shallow call hierarchy from the same method.
&lt;/p&gt;
&lt;p&gt;
Compare the two following snippets of pseudo bytecode (indented regions are the body of the invoked methods).
&lt;/p&gt;
&lt;p&gt;JRuby:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lock()
invoke closure_body
    // do stuff...
unlock()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jython:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;invoke __enter__
    Do Jython dispatch
        Do Jython to Java dispatch
            Do Java reflection dispatch
                lock()
// do stuff...
invoke __exit__
    Do Jython dispatch
        Do Jython to Java dispatch
            Do Java reflection dispatch
                unlock()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The key insight here is that in the first code snippet the lock and unlock instructions are in the same compilation unit. In the second example they are in two different call paths. The Jython dispatch logic is three levels of calls, and the Jython to Java dispatch logic is two levels, then there is the reflection dispatch that is a number of calls as well. Not only that, but there is quite a lot of code in those call paths as well: parsing of arguments, setting up call frame reflection objects, and more. Add all this together and there is no chance for the JVM to see both the lock and unlock instructions in the same compilation unit. Compared to the situation in the JRuby implementation where they are in the same compilation unit before any in-lining.
&lt;/p&gt;
&lt;p&gt;
Having un-optimized locks make a huge difference for applications running on the JVM. This together with the fact that JRuby is more optimized in general, accounts for most of the difference in execution time for these examples. If we could fix this, we would get a substantial improvement of performance in Jython.
&lt;/p&gt;

&lt;p&gt;
For further details on &lt;i&gt;how&lt;/i&gt; we intend to improve this situation in Jython, you are very welcome to attend my presentation on "&lt;a href="http://www.europython.eu/talks/talk_abstracts/index.html#talk65"&gt;A better Python for the JVM&lt;/a&gt;" at EuroPython, this &lt;a href="http://www.europython.eu/talks/timetable/#day3"&gt;Tuesday (June 30, 2009) at 15:30&lt;/a&gt;. I will also continue posting here on specific improvements and plans, so &lt;a href="http://twitter.com/thobe"&gt;stay tuned on Twitter&lt;/a&gt; or subscribe to my feed.
&lt;/p&gt;

&lt;p&gt;
&lt;span style="font-style:italic; font-weight: bold; color:red;"&gt;
Disclaimers:
&lt;/span&gt;
The understanding of a JVM in this post is mostly based on the Hotspot JVM. Other JVMs might work slightly different, but the basic understanding should be at least similar.
&lt;br /&gt;
The descriptions of both Jython and JRuby are somewhat simplified, the synchronization in JRuby is for example even slightly better optimized than what I have outlined here, but the full description would make the post overly complicated. The essentials are still the same.
&lt;br /&gt;
In my presentation at JavaOne some numbers suffered from classic micro benchmark errors, ask me if you want to know more about that.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5355216234531009924?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=H_-XdNncPGQ:TxUrrOhlhUw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=H_-XdNncPGQ:TxUrrOhlhUw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=H_-XdNncPGQ:TxUrrOhlhUw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=H_-XdNncPGQ:TxUrrOhlhUw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=H_-XdNncPGQ:TxUrrOhlhUw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=H_-XdNncPGQ:TxUrrOhlhUw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=H_-XdNncPGQ:TxUrrOhlhUw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/H_-XdNncPGQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5355216234531009924/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5355216234531009924" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5355216234531009924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5355216234531009924?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/H_-XdNncPGQ/performance-of-synchronization.html" title="Performance of Synchronization primitives in Jython" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_AqkFfcwHF4M/SkN3EnmE5AI/AAAAAAAAAKA/xO8pwKie0fQ/s72-c/DynaLangConcurrency-NoCounter.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2009/06/performance-of-synchronization.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUARHsyeip7ImA9WxJVEEw.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5879623891748412321</id><published>2009-06-26T12:30:00.000+02:00</published><updated>2009-06-26T12:30:45.592+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-26T12:30:45.592+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="JavaOne" /><category scheme="http://www.blogger.com/atom/ns#" term="nostalgia" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Five years later</title><content type="html">&lt;a href="http://1.bp.blogspot.com/_AqkFfcwHF4M/Sj9Rh1eEw1I/AAAAAAAAAJ4/2n-RwahhX0U/s1600-h/Musketeer.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_AqkFfcwHF4M/Sj9Rh1eEw1I/AAAAAAAAAJ4/2n-RwahhX0U/s320/Musketeer.png" alt="Me with a large beard and a musketeers outfit" title="Me as a musketeer" /&gt;&lt;/a&gt;
&lt;p&gt;
Five years ago I was in a committee responsible for greeting new students in &lt;a href="http://www.d.lintek.liu.se/"&gt;computer science and engineering&lt;/a&gt; at &lt;a href="http://www.liu.se"&gt;my university&lt;/a&gt;. We organized activities and parties, and made sure that the new students got their studies up to a pace that would help them through their education. We did all of this while putting on a theater act lasting throughout the entire greeting period of two weeks, for which I grew a large beard.
&lt;/p&gt;
&lt;p&gt;
At about this time of the year there was a team building exercise where we were supposed to draw a picture of how we imagined our lives five years from then. I drew the view of a city skyline from a high floor hotel room. My description was that I imagined myself traveling a lot for work. That I worked on interesting, cutting edge software projects around the world. And that I made good money doing so, not really spending that much, since I didn't really see anything I needed to spend money on when most of my time would be spent working.
&lt;/p&gt;
&lt;p&gt;
Three weeks ago when I looked out towards the San Francisco bay from my 25th floor hotel room at the &lt;a href="http://www.intercontinentalsanfrancisco.com/"&gt;Intercontinental&lt;/a&gt; where I stayed during &lt;a href="http://journal.thobe.org/2009/06/javaone-2009-from-my-perspective.html"&gt;this years JavaOne&lt;/a&gt;, I remembered that drawing. The view from my room was a lot like the view in the drawing. The more I thought about it, the more I realized that the vision I had five years ago was reality now.
&lt;/p&gt;
&lt;p&gt;
The thing I love the most about this is of course that the part about working on cool, exiting, cutting edge projects is true. Both of the projects that get the main part of my attention fit into this category. &lt;a href="http://neo4j.org"&gt;Neo4j&lt;/a&gt; is an up and coming database where I have the privilege to be doing tool and integration work, as well as advanced data persistence programming. &lt;a href="http://jython.org/"&gt;Jython&lt;/a&gt; gives me an opportunity to work on advanced JVM technology and cutting edge techniques for optimizing code. All together a good mix of technologies, challenges and people.
&lt;/p&gt;
&lt;p&gt;
One part of my vision, I'm sad to say, has yet to come true. I am not making as much money as I expected. In fact trips and conferences are rather expensive. But apart from that I spend about what I expected on other things. This is a minor detail however, I'd much rather work on projects I enjoy than be bored with a high salary.
&lt;/p&gt;
&lt;p&gt;
I also expected that I would be single, since I didn't expect anyone to put up with my traveling, working and being away a lot of the time. I am very happy that I got this prediction wrong. My girlfriend Sara is wonderful, and I am blessed to be sharing my life with her.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5879623891748412321?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=uU4OAiFVPYQ:7hZgfbFYvfQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=uU4OAiFVPYQ:7hZgfbFYvfQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=uU4OAiFVPYQ:7hZgfbFYvfQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=uU4OAiFVPYQ:7hZgfbFYvfQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=uU4OAiFVPYQ:7hZgfbFYvfQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=uU4OAiFVPYQ:7hZgfbFYvfQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=uU4OAiFVPYQ:7hZgfbFYvfQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/uU4OAiFVPYQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5879623891748412321/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5879623891748412321" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5879623891748412321?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5879623891748412321?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/uU4OAiFVPYQ/five-years-later.html" title="Five years later" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_AqkFfcwHF4M/Sj9Rh1eEw1I/AAAAAAAAAJ4/2n-RwahhX0U/s72-c/Musketeer.png" height="72" width="72" /><thr:total>3</thr:total><georss:point>37.7817477 -122.4046111</georss:point><feedburner:origLink>http://journal.thobe.org/2009/06/five-years-later.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QMQXc8fCp7ImA9WxJUFkw.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5232400805746741760</id><published>2009-06-25T20:57:00.002+02:00</published><updated>2009-07-15T01:49:40.974+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-15T01:49:40.974+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="neo4j" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Jython 2.5 - Why you should upgrade</title><content type="html">&lt;p&gt;
Last weekend I spent some time with the rest of the Neo4j team at Neo Technology for our Code Camp weekend. Among the things I worked on was our &lt;a href="http://components.neo4j.org/neo4j.py/"&gt;Python bindings for Neo4j&lt;/a&gt;. They obviously work with the &lt;a href="http://fwierzbicki.blogspot.com/2009/06/jython-250-final-is-out.html"&gt;recently released Jython 2.5&lt;/a&gt;, but also fairly well with CPython 2.5 (or later), with the current caveat that you have to install &lt;a href="http://jpype.sourceforge.net/"&gt;JPype&lt;/a&gt; on your own (I am working on replacing JPype with something that is maintained and more light weight, and works with Python 3.x). I also want these Python bindings to work with the previous version of Jython (2.2), for those who for some reason cannot update. So for the first time in a while I used a version of Jython that was not the very latest. This is my summary of that experience.
&lt;/p&gt;
&lt;p&gt;
When comparing Jython 2.5 with Jython 2.2 it suddenly becomes obvious how much work the Jython team (including myself) have put into making this a fully compatible implementation of the Python programming language. The fact that Jython now runs Django, Pylons, SQLAlchemy, and a ton of other things is genuinely impressive. And I am more than a little proud for the part I played in making this happen, even if it was only a small part. Jython has, with the step from 2.2 to 2.5, graduated from being a system for scripting Java applications with Python to a system on which you can build full applications.
&lt;/p&gt;
&lt;p&gt;
The first thing I missed when testing Neo4j with Jython 2.2 was &lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;. I run so many different unstable applications and libraries on different versions of Python and Jython that it's inevitable to mess up on a daily basis. A lot of these have different dependencies, and dependencies on conflicting versions of the same thing and other horrible constraints. And of course I patch and rebuild my Jython at the same time as well, meaning that all libraries I've installed directly into the Jython dist directory gets wiped (I've lost a lot of work this way). In all these situations virtualenv is a saving angel, and it doesn't work with Jython 2.2. (If you have not tried virtualenv yet, do so now! I was a late user, but it was love at first use.) &lt;i&gt;This is a pain - &lt;b&gt;Upgrade to Jython 2.5&lt;/b&gt;&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
The second thing I was screaming after in Jython &amp;lt; 2.5 was of course easy-install. If not for any other reason to install virtualenv. How about distutils? - Nope. Jython 2.2 has no pleasant way of installing libraries for you - you are on your own. Fail. The same is true for the Python bindings for Neo4j, if you use Jython 2.2 it will still download the required Java libraries for you, and you will be able to use it, but installing it into your &lt;code&gt;sys.path&lt;/code&gt; is up to you. &lt;i&gt;This is a pain - &lt;b&gt;Upgrade to Jython 2.5&lt;/b&gt;&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
I lied before. The first thing I missed was the Python 2.5 syntax. In particular the with statement. This was in fact the reason I joined the Jython project in the first place, to get Python 2.5 syntax support for Jython (and I succeeded in prototyping it during that first Google Summer of Code in 2007). Just consider the following two pieces of code, and I think you will get my point:
&lt;/p&gt;
&lt;pre name="code" class="python"&gt;
with neo.transaction:
    with_node = neo.node(language="Python", feature="with statement")
    example__node = neo.node(language="Python", example="Using the with statement")
    example_node.USES(with_node)
&lt;/pre&gt;
&lt;pre name="code" class="python"&gt;
tx = neo.transaction.begin()
try:
    try:
        try_node = neo.node(language="Python", feature="try block")
        example__node = neo.node(language="Python", example="Not using the with statement")
        example_node.USES(try_node)
    except:
        tx.failure()
        raise
    else:
        tx.success()
finally:
    tx.finish()
&lt;/pre&gt;
&lt;p&gt;
It should be obvious which one is beautiful and which one is not. The with statement is one nice piece of syntactic sugar. &lt;i&gt;Not having it is a pain - &lt;b&gt;Upgrade to Jython 2.5&lt;/b&gt;&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
Ok, so there is still a lot of work to be done on Jython. Mainly on performance. The focus up until now has been compatibility, and we've done a good job at that. In the next major version of Jython you should expect a substantial improvement of performance. Not that performance is bad now. But we know that we can do better. More on that in a later post.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5232400805746741760?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=XMcFhzRAtRA:hkafsnTt7QM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=XMcFhzRAtRA:hkafsnTt7QM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=XMcFhzRAtRA:hkafsnTt7QM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=XMcFhzRAtRA:hkafsnTt7QM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=XMcFhzRAtRA:hkafsnTt7QM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=XMcFhzRAtRA:hkafsnTt7QM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=XMcFhzRAtRA:hkafsnTt7QM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/XMcFhzRAtRA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5232400805746741760/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5232400805746741760" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5232400805746741760?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5232400805746741760?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/XMcFhzRAtRA/jython-25-why-you-should-upgrade.html" title="Jython 2.5 - Why you should upgrade" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><georss:point>55.6121327 13.0016985</georss:point><feedburner:origLink>http://journal.thobe.org/2009/06/jython-25-why-you-should-upgrade.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUABSHY_fSp7ImA9WxJWE0g.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-1016055680163633101</id><published>2009-06-18T22:42:00.000+02:00</published><updated>2009-06-18T22:42:39.845+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-18T22:42:39.845+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="JavaOne" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>JavaOne 2009 from my perspective</title><content type="html">&lt;p&gt;It has been a week since I got back to Sweden after my trip to San Francisco for what I am sad to say was my worst JavaOne so far. Don't get me wrong, JavaOne was good. There were a lot of good sessions, and as always it was nice to meet my friends in the community. But the two previous years were better. Much of it can be blamed on the economy. And the rest can be blamed on me. To a large extent the reason I didn't get the JavaOne experience I would have liked to was because I was too busy. I had a deadline waiting for me on a project at work when I got home, and had to work quite a lot during my JavaOne week. But the fact stands, JavaOne was a lot smaller this year, only about 9000 attendees, and you notice that.&lt;/p&gt;
&lt;p&gt;These are the highlight from the sessions I attended at CommunityOne and then JavaOne:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Beyond impossible: How JRuby has evolved the Java Platform&lt;/b&gt; by &lt;a href="http://blog.headius.com/"&gt;Charles Nutter&lt;/a&gt;. Charles is a kickass developer and has become a really good speaker as well. It's amazing what he has done with JRuby, and this talk was a summary of the highlights from that. Including things such as the fact that the JRuby team have implemented their own regular expressions library and posix layer for doing system calls from the JVM. All of which adds up to making JRuby the fastest complete implementation of Ruby.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Return of the Puzzlers: Schlock and Awe&lt;/b&gt; by Joshua Bloch and Neal Gafter. All I can say is that all the digging around on the low levels of the JVM that I have done has payed off, I had the right answer for 7 out of 7 Puzzlers, much better than the first time I attended a Java Puzzlers session.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Toward a Renaissance VM&lt;/b&gt; by &lt;a href="http://blogs.sun.com/jrose/"&gt;John Rose&lt;/a&gt;. John talked about Invokedynamic and Method Handles. It was all familiar stuff, but a good introduction for the odd people who do not spend most of their time implementing languages for the JVM.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Meet the Java Posse&lt;/b&gt;. I've known the guys of the Java Posse for a while, but this is the first time that I was not doing something completely different during their BoF at JavaOne. Not much to say, &lt;a href="http://javaposse.com/"&gt;listen to the podcast&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSR 292 Cookbook&lt;/b&gt; mostly by John Rose. This is what I think was the eye opening session about Invokedynamic and MethodHandles for most people. Hands on examples, showing all of the JSR 292 goodness in action. More people should have attended. Everyone not familiar with JSR 292 on beforehand that I talked to after the session realized that it is useful for far more things than just implementing languages.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;How to write a distributed garbage collector&lt;/b&gt; by Ari Zilka and Saravanan Subbiah from &lt;a href="http://www.terracotta.org/"&gt;Terracotta&lt;/a&gt;. This was the last session of the last day and probably &lt;i&gt;the best session at JavaOne&lt;/i&gt; this year. Ari and Saravanan talked about how garbage is detected and collected in the distributed environment that is Terracotta when all references to an object could be from a different node. Very interesting stuff, I need to take a deeper look at Terracotta at some point soon.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There were also some noteworthy sessions that I missed while I was working:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Java Platform Concurrency Gotchas&lt;/b&gt; by &lt;a href="http://tech.puredanger.com"&gt;Alex Miller&lt;/a&gt;. A smart guy talking about interesting stuff, too bad I missed that one.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;The Ghost in the Virtual Machine: A Reference to References&lt;/b&gt; by &lt;a href="http://crazybob.org/"&gt;Bob Lee&lt;/a&gt;. I have a feeling that there are still a few things that can be done using Weak, Soft and Phantom references, that I don't know about yet. I would also have liked to hear what he had to say about &lt;a href="http://en.wikipedia.org/wiki/Ephemeron"&gt;Ephemerons&lt;/a&gt;. Are they coming to the JVM soon btw?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then there are the two presentations I gave. A BoF on Interface Injection entitled "Language Interoperability on the JVM Made Simple" and a Technical session entitled "Exploiting Concurrency with Dynamic Languages".&lt;/p&gt;
&lt;h2&gt;Language Interoperability on the JVM Made Simple&lt;/h2&gt;
&lt;p&gt;Since this was a Birds of a Feather session I divided it into two main sections: The first half I gave an introduction to interface injection, the status of the implementation and some ideas as to what you can do with it. The second half of the session was spent on discussions about what people want from interface injection, how they want to use it and how it should work.&lt;/p&gt;
&lt;p&gt;The short summary is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I have implemented the injection mechanism.&lt;/li&gt;
&lt;li&gt;I have designed a proposal API for how the injection process should work on the Java level.&lt;/li&gt;
&lt;li&gt;I have wired up interface injection to invokeinterface, there are still a few more places that would need to be able to call the injection mechanism.&lt;/li&gt;
&lt;li&gt;The Reflection API for injected interfaces is still unspecified.&lt;/li&gt;
&lt;li&gt;A lot of people want only explicit injection of interfaces. That is for interfaces to only be injected when an inject() method is invoked in some API. This can be emulated by setting a flag in the injector when this method is invoked, and unset it at the end of this method.&lt;/li&gt;
&lt;li&gt;There was also some concern about the fact that methods on an injected interface gets implemented automatically by methods with the same name and signature that exist in the target class. I agree that it would be better if interface implementations could be separate for each interface in the class file format. But I don't think this problem will be as big as people might fear since the methods have to match &lt;i&gt;exactly&lt;/i&gt; on return type as well as parameter types.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The staff in room 102/103 was really helpful, they offered to rearrange the chairs and tables to better host the discussion I wanted to encourage about interface injection. This can not be said about the staff in room 104 where I had my second presentation. Although being very friendly, they were not very professional. First of all my session was supposed to be recorded, but after the session I was informed that they had forgotten to record the slides, and transitions. I gave them my slides on a memory stick and they said that they were going to match it to the best of their ability then send it to me for review, I have yet to hear from them. On top of that some members of the staff were constantly talking behind the stage, leaving me very distracted. Highly unprofessional of them. I was so surprised by this that I didn't even tell them to shut up.&lt;/p&gt;
&lt;h2&gt;Exploiting Concurrency with Dynamic Languages&lt;/h2&gt;
&lt;p&gt;I spent too much time at JavaOne preparing for my second talk about how languages other than the Java Programming Language on the JVM lend themselves better to expressing concurrent programs. I really should have prepared the talk much more &lt;i&gt;before&lt;/i&gt; I left Sweden. I believe that I could have done a better presentation. The staff in the room is to blame to a large extent for the fact that I didn't feel satisfied by my performance, but half of the blame is on me. Although, the few reviews that I've heard have been good. Basically that the topic was good, that I had interesting ideas and made good points, but that it was too short, although with good Q&amp;amp;A. A fair review in my opinion, it will be interesting to see the review cards when they get sent out to the speakers.&lt;/p&gt;
&lt;p&gt;What is more interesting however is what I was able to conclude in my talk. It should come as a surprise to no one that closures make it much easier to express concurrent programs, and to encapsulate best practices and patterns in libraries. Other higher level constructs are helpful here as well, please have a look at &lt;a href="http://www.slideshare.net/thobe/exploiting-concurrency-with-dynamic-languages"&gt;my slides&lt;/a&gt; for reference. I also found that Jython has a lot of room for improvement, but more on that in another blog post.&lt;/p&gt;

&lt;div style="width:425px;text-align:left" id="__ss_1605269"&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dynalangconcurrency-090618152804-phpapp01&amp;stripped_title=exploiting-concurrency-with-dynamic-languages" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dynalangconcurrency-090618152804-phpapp01&amp;stripped_title=exploiting-concurrency-with-dynamic-languages" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-1016055680163633101?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=lDd3lVgCte8:mhTfEkGCi5A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=lDd3lVgCte8:mhTfEkGCi5A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=lDd3lVgCte8:mhTfEkGCi5A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=lDd3lVgCte8:mhTfEkGCi5A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=lDd3lVgCte8:mhTfEkGCi5A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=lDd3lVgCte8:mhTfEkGCi5A:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=lDd3lVgCte8:mhTfEkGCi5A:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/lDd3lVgCte8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/1016055680163633101/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=1016055680163633101" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/1016055680163633101?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/1016055680163633101?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/lDd3lVgCte8/javaone-2009-from-my-perspective.html" title="JavaOne 2009 from my perspective" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2009/06/javaone-2009-from-my-perspective.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04EQ3k7eSp7ImA9WxJREkQ.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-4400067948083543998</id><published>2009-05-14T09:19:00.003+02:00</published><updated>2009-05-14T11:05:02.701+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-14T11:05:02.701+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Twitter: #dontfixreplies</title><content type="html">&lt;p&gt;
Recently &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; changed their policy for which messages to show in the regular stream of messages to each user. Previously users could choose if they wanted to see @replies (messages that start with an @ sign followed by a user name) or not. With the recent change this is no longer a configuration option, but all users now &lt;span style="font-style: italic;"&gt;don't&lt;/span&gt; see @replies directed to people they don't follow. The motivation for this is of course that these messages really are directed at someone else, that you are not interested in.&lt;/p&gt;
&lt;p&gt;
A lot of people &lt;a href="http://twitter.com/#search?q=%23fixreplies"&gt;got upset with this&lt;/a&gt;, with the main motivation being that @replies is a good way to find interesting connections and people.&lt;/p&gt;
&lt;p&gt;
I did not notice the change until everyone (yes, everyone) started ranting about wanting it to change back to the old behavior, since I had turned off @replies a long time ago. &lt;span style="font-style: italic;"&gt;Why did I turn it off?&lt;/span&gt; Because a lot of people use Twitter as &lt;span style="font-style: italic;"&gt;yet another IM service&lt;/span&gt;, and those messages have a very low &lt;a href="http://en.wikipedia.org/wiki/Signal-to-noise_ratio"&gt;signal to noise ratio&lt;/a&gt; to me. Before I turned off @replies I got about 3 times as many tweets in my stream, and more than 90% of these were not interesting to me. Even with my current stream without @replies there is more noise than signal, but the ratio is such that I &lt;span style="font-style: italic;"&gt;can find&lt;/span&gt; the tweets I'm interested in.&lt;/p&gt;
&lt;p&gt;
One interesting thing that I noticed with the recent change was that peoples twittering mentality changed (This applies only to the people I follow, a tech heavy crowd. I have not done, nor do I intend to do, forther investigation of the phenomenon). All of the sudden the signal to noise ratio got much better. I was away from twitter for about a day, a little over 20 hours. When I got back I had less than 100 new tweets in my stream. Normally 20 hours yield more than 120 tweets. There were also more interesting links than usual, I have 13 tabs open with things I want to read. I.e. almost 15% of the tweets contained links that looked interesting, compared to the usual 5%. A lot of the other tweets were interesting to, I estimate the noise ratio to be about 30% for this period of time. Interestingly the tweets that fall into the noise category are mostly either rants about how bad it is to not get @replies or from the past few hours when people started add stuff before their @replies to force them to be visible.&lt;/p&gt;
&lt;p&gt;
Conclusion: Twitter, please keep the current behavior for @replies. Or if it changes back, make the current behavior default (I'm not unreasonable).&lt;/p&gt;
&lt;p style="color: rgb(153, 0, 0);"&gt;
&lt;span style="font-weight: bold;"&gt;Disclaimer:&lt;/span&gt; I haven't done the actual statistical calculations for this. It would be interesting to do, and post a few charts, but there are a lot of interesting things to do, and I don't have time to do all of them. Therefore the figures in this post are just from the general feeling I get from my Twitter stream.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-4400067948083543998?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=AXitjWUbAvs:Nn9ySsd8VEk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=AXitjWUbAvs:Nn9ySsd8VEk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=AXitjWUbAvs:Nn9ySsd8VEk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=AXitjWUbAvs:Nn9ySsd8VEk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=AXitjWUbAvs:Nn9ySsd8VEk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=AXitjWUbAvs:Nn9ySsd8VEk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=AXitjWUbAvs:Nn9ySsd8VEk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/AXitjWUbAvs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/4400067948083543998/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=4400067948083543998" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4400067948083543998?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4400067948083543998?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/AXitjWUbAvs/twitter-dontfixreplies.html" title="Twitter: #dontfixreplies" /><author><name>Tobias</name><uri>http://www.blogger.com/profile/11236948439656871689</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="11836775242526299003" /></author><thr:total>1</thr:total><feedburner:origLink>http://journal.thobe.org/2009/05/twitter-dontfixreplies.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQER3s4eCp7ImA9WxJTFE4.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-9111947632824078426</id><published>2009-04-22T17:35:00.005+02:00</published><updated>2009-04-22T22:48:26.530+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-22T22:48:26.530+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Python-style generators in Scheme</title><content type="html">&lt;p&gt;I have finally gotten back to working on interface injection in OpenJDK. As before I get a few breaks when I wait for stuff to compile. These breaks are too long to just sit around and wait, but too short to context switch to another project. So what I end up doing instead are small hacks. And since I, once again, have decided to try and post stuff here more regularly, I decided to write a post about a hack I did yesterday.&lt;/p&gt;&lt;p&gt;A long time ago I tried to implement Python style generators in Scheme, and obviously I am a better programmer now since I was able to just sit down and write it.&lt;/p&gt;&lt;p&gt;The aim is to be able to write code like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-generator&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;iterate&lt;/span&gt; lst)&lt;br /&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;define&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;iter&lt;/span&gt; lst)&lt;br /&gt;    (&lt;span style="color: rgb(0, 0, 153);"&gt;if&lt;/span&gt; (not (null? lst))&lt;br /&gt;        (&lt;span style="color: rgb(0, 0, 153);"&gt;begin&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;yield&lt;/span&gt; (car lst))&lt;br /&gt;               (iter (cdr lst)))))&lt;br /&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;iter&lt;/span&gt; lst))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then use such a generator in a Python-like for-loop, like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (element (iterate '(a b c))&lt;br /&gt;  (&lt;span style="color: rgb(0, 0, 153);"&gt;print&lt;/span&gt; element))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code that enables this is at it's core two syntax definitions. The generator definition syntax, and the for-loop syntax:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-syntax&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;explicit-generator-definition&lt;/span&gt;&lt;br /&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;syntax-rules&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;yield&lt;/span&gt;)&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;explicit-generator-definition&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;yield&lt;/span&gt; exit) params . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; params&lt;br /&gt;     (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (done loop)&lt;br /&gt;       (&lt;span style="color: rgb(0, 0, 153);"&gt;define&lt;/span&gt; (exit . values)&lt;br /&gt;         (&lt;span style="color: rgb(0, 0, 153);"&gt;call/cc&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (next) (&lt;span style="color: rgb(0, 0, 153);"&gt;apply&lt;/span&gt; loop (&lt;span style="color: rgb(0, 0, 153);"&gt;cons&lt;/span&gt; next values)))))&lt;br /&gt;       . body)))))&lt;br /&gt;&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-syntax&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt;&lt;br /&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;syntax-rules&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break continue&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; multiple valued generator version&lt;/span&gt;&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation)&lt;br /&gt;        ((variables ...) generator) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;call/cc&lt;/span&gt;&lt;br /&gt;    (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (breaker) (generator breaker&lt;br /&gt;                                 (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (continuation variables ...)&lt;br /&gt;                                   . body)))))&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; single valued generator version&lt;/span&gt;&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation)&lt;br /&gt;        (variable generator) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;call/cc&lt;/span&gt;&lt;br /&gt;    (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (breaker) (generator breaker&lt;br /&gt;                                 (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (continuation variable)&lt;br /&gt;                                   . body)))))&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; enable ignoring break and continue&lt;/span&gt;&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (target ...) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (target ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (targets ...) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; ignored) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (targets ...) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; ignored) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;targets&lt;/span&gt; ...) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 102, 0);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; _break) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; _continue) (targets ...) . body))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see the loop construct has the ability to break the loop and jump to the next iteration by explicitly naming the break and continue continuations. The fact that these have to be named explicitly is a good thing since it enables you to define different names for the break/continue continuations for different loops when you nest loops. You can of course name them break and continue, respectively, like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;break&lt;/span&gt; break) (&lt;span style="color: rgb(0, 0, 153);"&gt;continue&lt;/span&gt; continue) (element (iterate '(a b c))&lt;br /&gt;  (&lt;span style="color: rgb(0, 0, 153);"&gt;print&lt;/span&gt; element))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The generator definition also needs the yield continuation to be named explicitly. This is usually not what you want, so instead we define a convenience syntax for defining generators in the form of a &amp;quote;unhygienic&amp;quote; macro (this is the syntax used for unhygienic macros by most scheme implementations, PLT scheme that I used for example):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-macro&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;generator&lt;/span&gt; arguments . body)&lt;br /&gt; `(explicit-generator-definition (&lt;span style="color: rgb(0, 0, 153);"&gt;yield&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;yield&lt;/span&gt;) ,arguments ,@body))&lt;br /&gt;&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-macro&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;define-generator&lt;/span&gt; signature . body)&lt;br /&gt; `(define ,(&lt;span style="color: rgb(0, 0, 153);"&gt;car&lt;/span&gt; signature)&lt;br /&gt;   (explicit-generator-definition (&lt;span style="color: rgb(0, 0, 153);"&gt;yield&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;yield&lt;/span&gt;) ,(&lt;span style="color: rgb(0, 0, 153);"&gt;cdr&lt;/span&gt; signature) ,@body)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These macros was what prevented me from completing this when I first tried a few years ago. I started with them, and wanted them to be portable across all Scheme implementations, and unhygienic macros are not defined in the R5RS standard. What I should have done is what I did now, start with the interesting stuff and add just a little implementation dependent code for the final touches.&lt;/p&gt;&lt;p&gt;Now we can use these macros to define a range function that behaves in about the same way as the xrange function in Python:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-generator&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;range&lt;/span&gt; . params)&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;range&lt;/span&gt; start stop step)&lt;br /&gt;  (&lt;span style="color: rgb(0, 0, 153);"&gt;if&lt;/span&gt; (and (&gt; start stop) (&gt; step 0))&lt;br /&gt;      (&lt;span style="color: rgb(0, 0, 153);"&gt;values&lt;/span&gt; start (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (current) (&lt;= current stop)) (- step))&lt;br /&gt;      (&lt;span style="color: rgb(0, 0, 153);"&gt;values&lt;/span&gt; start (lambda (current) (&gt;= current stop)) step)))&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;call-with-values&lt;/span&gt;&lt;br /&gt; &lt;span style="color: rgb(204, 51, 204);"&gt;; parse the variables based on the number of them&lt;/span&gt;&lt;br /&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; () (&lt;span style="color: rgb(0, 0, 153);"&gt;cond&lt;/span&gt;&lt;br /&gt;              &lt;span style="color: rgb(204, 51, 204);"&gt;; 0 arguments -&amp;gt;&lt;/span&gt;&lt;br /&gt;              ((null? params)&lt;br /&gt;               &lt;span style="color: rgb(204, 51, 204);"&gt;; infinite generator from 0&lt;/span&gt;&lt;br /&gt;               (values 0 (lambda (current) #f) 1))&lt;br /&gt;              &lt;span style="color: rgb(204, 51, 204);"&gt;; 1 argument: count -&amp;gt;&lt;/span&gt;&lt;br /&gt;              ((null? (cdr params))&lt;br /&gt;               &lt;span style="color: rgb(204, 51, 204);"&gt;; generator with count elements, starting at 0&lt;/span&gt;&lt;br /&gt;               (range 0 (car params) 1))&lt;br /&gt;              &lt;span style="color: rgb(204, 51, 204);"&gt;; 2 arguments: start and stop -&amp;gt;&lt;/span&gt;&lt;br /&gt;              ((null? (cddr params))&lt;br /&gt;               &lt;span style="color: rgb(204, 51, 204);"&gt;; generator over [start, stop[&lt;/span&gt;&lt;br /&gt;               (range (car params) (cadr params) 1))&lt;br /&gt;              &lt;span style="color: rgb(204, 51, 204);"&gt;; 3 arguments: start, stop and step -&amp;gt;&lt;/span&gt;&lt;br /&gt;              ((null? (cdddr params))&lt;br /&gt;               &lt;span style="color: rgb(204, 51, 204);"&gt;; generator over [start, stop[ with a given step length&lt;/span&gt;&lt;br /&gt;               (range (car params) (cadr params) (caddr params)))&lt;br /&gt;              &lt;span style="color: rgb(204, 51, 204);"&gt;; more arguments - error (by passing too few arguments to internal range&lt;/span&gt;&lt;br /&gt;              (#t (values))))&lt;br /&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (start stop? step)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;do&lt;/span&gt; ((current start (+ current step)))&lt;br /&gt;       ((stop? current))&lt;br /&gt;     (&lt;span style="color: rgb(0, 0, 153);"&gt;yield&lt;/span&gt; current)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As a final touch we add a convenience syntax for nested for-loops as well:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;define-syntax&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt;&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;syntax-rules&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break continue&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; base case - one generator - expands to single for&lt;/span&gt;&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (((&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) targets ...)) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (((&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) targets ...)) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (((&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) targets ...)) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;break&lt;/span&gt; breaker) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (((&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) targets ...)) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 102, 0);"&gt;continue&lt;/span&gt; continuation) (targets ...) . body))&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; ((targets ...)) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 0, 153);"&gt;for&lt;/span&gt; (targets ...) . body))&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; recursive case - more than one generator - expands to nested for*&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; for* is used instead of for to avoid repeating break and continue cases&lt;/span&gt;&lt;br /&gt;  ((&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (first more ...) . body)&lt;br /&gt;   (&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (first) (&lt;span style="color: rgb(0, 102, 0);"&gt;for*&lt;/span&gt; (more ...) . body)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To understand how the generators work let's look at what a generator definition and for-loop construct expands to:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;; A generator expands to a function that accepts the defined parameters&lt;/span&gt;&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; params&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; The generator function, when called, returns a function to which&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; the for-construct passes the break continuation and a closure&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; representing the body of the loop&lt;/span&gt;&lt;br /&gt;  (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (done loop)&lt;br /&gt;    &lt;span style="color: rgb(204, 51, 204);"&gt;; yield is defined as a function that takes arbitrary parameters&lt;/span&gt;&lt;br /&gt;    (&lt;span style="color: rgb(0, 0, 153);"&gt;define&lt;/span&gt; (exit . values)&lt;br /&gt;      &lt;span style="color: rgb(204, 51, 204);"&gt;; when invoked it retrieves the current continuation to be&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(204, 51, 204);"&gt;; able to resume then calls the loop body with the continuation&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(204, 51, 204);"&gt;; and the passed in parameters as arguments&lt;/span&gt;&lt;br /&gt;      (&lt;span style="color: rgb(0, 0, 153);"&gt;call/cc&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (next) (&lt;span style="color: rgb(0, 0, 153);"&gt;apply&lt;/span&gt; loop (&lt;span style="color: rgb(0, 0, 153);"&gt;cons&lt;/span&gt; next values)))))&lt;br /&gt;    &lt;span style="color: rgb(204, 51, 204);"&gt;; The actual body of the generator is defined by the user,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(204, 51, 204);"&gt;; this executes arbitrary code and calls yield.&lt;/span&gt;&lt;br /&gt;    . body))&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;; The for-construct starts by retrieving the current conitunuation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;; this is used for breaking the loop&lt;/span&gt;&lt;br /&gt;(&lt;span style="color: rgb(0, 0, 153);"&gt;call/cc&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; It then calls the generator with two arguments:&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; the break continuation and the body of the loop.&lt;/span&gt;&lt;br /&gt;  (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (breaker) (generator breaker&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; The body of the loop accepts two arguments:&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(204, 51, 204);"&gt;; the continue continuation and the argument that was passed to yield.&lt;/span&gt;&lt;br /&gt;                               (&lt;span style="color: rgb(0, 0, 153);"&gt;lambda&lt;/span&gt; (continuation variable)&lt;br /&gt;                                 &lt;span style="color: rgb(204, 51, 204);"&gt;; All it does is execute the body&lt;/span&gt;&lt;br /&gt;                                 . body))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Happy Hacking!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-9111947632824078426?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ETAvd8vdqOY:QtI0pG7DhsE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ETAvd8vdqOY:QtI0pG7DhsE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ETAvd8vdqOY:QtI0pG7DhsE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ETAvd8vdqOY:QtI0pG7DhsE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ETAvd8vdqOY:QtI0pG7DhsE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=ETAvd8vdqOY:QtI0pG7DhsE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=ETAvd8vdqOY:QtI0pG7DhsE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/ETAvd8vdqOY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/9111947632824078426/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=9111947632824078426" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/9111947632824078426?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/9111947632824078426?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/ETAvd8vdqOY/python-style-generators-in-scheme.html" title="Python-style generators in Scheme" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2009/04/python-style-generators-in-scheme.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIFRHk9fSp7ImA9WxRaGUg.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-7568716031031387538</id><published>2008-12-22T13:15:00.003+01:00</published><updated>2008-12-22T15:01:55.765+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-22T15:01:55.765+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>On Iterator composition in Java</title><content type="html">&lt;p&gt;In &lt;a href="http://journal.thobe.org/2008/12/on-double-checked-locking-in-java.html"&gt;my last blog post&lt;/a&gt; I mentioned that I would like to see library support for manipulating iterators included in the JDK. I for one, and I know that more people than me, have a set of iterator manipulation classes that I bring along from project to project, usually by copy/paste. This post is an elaboration on what the things are that I think should be included in the JDK, all communicated through code (The actual implementation is not as interesting as the API, and thus left as an exercise for the reader):&lt;/p&gt;&lt;code&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;package&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.iter.*&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public final class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt; {&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public&lt;/span&gt; &amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;E&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;E&lt;/span&gt;&amp;gt; empty() { ... }&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public&lt;/span&gt; &amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;S&lt;/span&gt;,&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&gt; convert(&lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;S&lt;/span&gt;&amp;gt; iterable, &lt;span style="color: rgb(0, 102, 0);"&gt;Converter&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;S&lt;/span&gt;,&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; converter) { ... }&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public&lt;/span&gt; &amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; upCast(&lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;?&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;extends&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; iterable) { ... }&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public&lt;/span&gt; &amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; downCast(&lt;span style="color: rgb(0, 102, 0);"&gt;Class&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; target, &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;?&lt;/span&gt;&amp;gt; iterable) { ... }&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public&lt;/span&gt; &amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; append(&lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt;... iterables) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;// These classes should preferably be reused from somewhere.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;package&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.iter&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public interface&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Converter&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;S&lt;/span&gt;,&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; {&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt; convert(&lt;span style="color: rgb(0, 102, 0);"&gt;S&lt;/span&gt; source);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public interface&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Filter&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;E&lt;/span&gt;&amp;gt; {&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;boolean&lt;/span&gt; accept(&lt;span style="color: rgb(0, 102, 0);"&gt;E&lt;/span&gt; element);&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;p&gt;And some sample uses:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;package&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;org.thobe.example&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.Iterators&lt;/span&gt;;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.iter.*&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;UsesIteratorComposition&lt;/span&gt; {&lt;br /&gt;    &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;private class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt; {}&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;private class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;extends&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt; {}&lt;br /&gt;    &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;private class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Target&lt;/span&gt; { Target(&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt; s) {} }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;&amp;gt; source = &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt;.empty();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;void&lt;/span&gt; conversions() {&lt;br /&gt;        &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Target&lt;/span&gt;&amp;gt; target = &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt;.convert(source, &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Converter&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;,&lt;span style="color: rgb(0, 102, 0);"&gt;Target&lt;/span&gt;&amp;gt;() {&lt;br /&gt;            &lt;span style="color: rgb(0, 102, 0);"&gt;Target&lt;/span&gt; convert(&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt; source) {&lt;br /&gt;                &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;return new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Target&lt;/span&gt;(source);&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;void&lt;/span&gt; casts() {&lt;br /&gt;        &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt;&amp;gt; something = &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt;.upCast(source);&lt;br /&gt;        &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;&amp;gt; back = &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt;.downCast(&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;.&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;class&lt;/span&gt;, something);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 102, 0);"&gt;void&lt;/span&gt; append() {&lt;br /&gt;        &lt;span style="color: rgb(0, 102, 0);"&gt;Iterable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;&amp;gt; source = &lt;span style="color: rgb(0, 102, 0);"&gt;Iterators&lt;/span&gt;.append(source, &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;ArrayList&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;&amp;gt;(){&lt;br /&gt;            {&lt;br /&gt;                add(&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;());&lt;br /&gt;                add(&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Source&lt;/span&gt;());&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-7568716031031387538?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=OmNy0edI8DQ:ni7fzkOltv8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=OmNy0edI8DQ:ni7fzkOltv8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=OmNy0edI8DQ:ni7fzkOltv8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=OmNy0edI8DQ:ni7fzkOltv8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=OmNy0edI8DQ:ni7fzkOltv8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=OmNy0edI8DQ:ni7fzkOltv8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=OmNy0edI8DQ:ni7fzkOltv8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/OmNy0edI8DQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/7568716031031387538/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=7568716031031387538" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/7568716031031387538?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/7568716031031387538?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/OmNy0edI8DQ/on-iterator-composition-in-java.html" title="On Iterator composition in Java" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/12/on-iterator-composition-in-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIMSHw4eyp7ImA9WxRaFUw.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-450559876094116816</id><published>2008-12-17T13:16:00.004+01:00</published><updated>2008-12-17T13:56:29.233+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-17T13:56:29.233+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>On Double Checked Locking in Java</title><content type="html">&lt;p&gt;You have probably all heard/seen &lt;a href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;the “Double-Checked Locking is Broken” declaration&lt;/a&gt;. And if you haven't I'll just tell you that before the improved memory model of Java 5, double checked locking didn't work as expected. Even in Java 5 and later there are things you need to consider to get it to work properly, and even more things to consider if you want it to perform well.&lt;/p&gt;&lt;p&gt;Joshua Bloch suggests in his book Effective Java, and keeps repeating in several presentations that there is one way to implement double checked locking and that this code snippet should be copied to every place where it's needed. I disagree. Not with the part about there only being one way of doing it, but with the copying part. In my eyes this is perfect use case for an abstract class:&lt;/p&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;package&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.concurrent&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;public abstract class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;LazyLoaded&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt;&amp;gt; {&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;private&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;volatile&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt; value;&lt;br /&gt;    &lt;span style="color: rgb(204, 102, 204);"&gt;// Get the value, guard the loading by double checked locking&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;public final&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt; getValue() {&lt;br /&gt;        &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt; result = value;&lt;br /&gt;        &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;if&lt;/span&gt; (result == null)   { &lt;span style="color: rgb(204, 102, 204);"&gt;// First check&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;synchronized&lt;/span&gt; (this) { &lt;span style="color: rgb(204, 102, 204);"&gt;// Lock&lt;/span&gt;&lt;br /&gt;                result = value;&lt;br /&gt;                &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;if&lt;/span&gt; (result == null) { &lt;span style="color: rgb(204, 102, 204);"&gt;// Second check&lt;/span&gt;&lt;br /&gt;                    result = loadValue();&lt;br /&gt;                    value = result;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;return&lt;/span&gt; result;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;protected abstract&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;T&lt;/span&gt; loadValue();&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This class would then be used like this:&lt;/p&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;package&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;org.thobe.example&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;java.util.concurrent.LazyLoaded&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;UsesDoubleCheckedLocking&lt;/span&gt; {&lt;br /&gt;    &lt;span style="color: rgb(204, 102, 204);"&gt;// The generics even makes it read well:&lt;/span&gt;&lt;br /&gt;    &lt;span style="font-weight: bold; color: rgb(0, 0, 153);"&gt;private final&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;LazyLoaded&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt;&amp;gt;() {&lt;br /&gt;        &lt;span style="font-weight:bold;"&gt;@Override&lt;/span&gt; &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt; loadValue() {&lt;br /&gt;            &lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;return new&lt;/span&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;Something&lt;/span&gt;();&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;    &lt;span style="color: rgb(204, 51, 204);"&gt;// ... &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(204, 51, 204);"&gt;your&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt; code will probably do something useful here ...&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Just expressing my opinion. I hope someone important reads this and makes sure that it gets included in Java7. And while you're at it, make sure we get some standardized ways of composing &lt;span style="font-weight:bold;"&gt;Iterable&lt;/span&gt;/&lt;span style="font-weight:bold;"&gt;Iterator&lt;/span&gt;s as well...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-450559876094116816?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=iCcyqigO0b0:G8A_4fLMwLI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=iCcyqigO0b0:G8A_4fLMwLI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=iCcyqigO0b0:G8A_4fLMwLI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=iCcyqigO0b0:G8A_4fLMwLI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=iCcyqigO0b0:G8A_4fLMwLI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=iCcyqigO0b0:G8A_4fLMwLI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=iCcyqigO0b0:G8A_4fLMwLI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/iCcyqigO0b0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/450559876094116816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=450559876094116816" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/450559876094116816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/450559876094116816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/iCcyqigO0b0/on-double-checked-locking-in-java.html" title="On Double Checked Locking in Java" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/12/on-double-checked-locking-in-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYBQXY_cSp7ImA9WxRbFEU.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-8699660405760046244</id><published>2008-12-05T15:05:00.000+01:00</published><updated>2008-12-05T15:09:10.849+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-05T15:09:10.849+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="neo4j" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>About types in Neo4j</title><content type="html">&lt;p&gt;When I first started using &lt;a href="http://neo4j.org/"&gt;Neo4j&lt;/a&gt; I wondered "Why is there a RelationshipType and no NodeType?", and as more people are introduced to Neo4j I find that this is a quite common question. And of course an obvious question in the strongly typed single inheritance world of Java. This post was inspired by a &lt;a href="http://lists.neo4j.org/pipermail/user/2008-October/000848.html"&gt;discussion&lt;/a&gt; on the &lt;a href="https://lists.neo4j.org/mailman/listinfo/user"&gt;Neo4j mailing list&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The answer to the question is to be found in the name &lt;span style="font-style: italic;"&gt;RelationshipType&lt;/span&gt;, it means no more than than the name implies. In particular it does not mean &lt;span style="font-style: italic;"&gt;data type&lt;/span&gt;. What you are wishing for when you ask for a node type is a way of specifying what properties a node or relationship has, based on its type. Neo4j does not provied any mechanism for this at the core layer. There is a meta model component available that gives you data types for nodes and relationships with verification and all of that if you would like it, but you need to explicitly turn it on.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;So what are &lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;RelationshipType&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;s then?&lt;/span&gt; A relationship type is a navigational feature of Neo4j. It is used to implement what is known in graph theory as &lt;span style="font-style: italic;"&gt;edge-labeled multigraphs&lt;/span&gt;. This feature makes it a whole lot easier to navigate through a graph that represents application data. Adding similar labels to nodes would not provide any navigational benefit, which is why Neo4j does not implement such a feature.&lt;/p&gt;&lt;p&gt;It is well worth noticing the &lt;span style="font-style: italic;"&gt;RelationshipType&lt;/span&gt; can be used to implement data types for both relationships &lt;span style="font-weight: bold;"&gt;and&lt;/span&gt; nodes. In a way that allows nodes to have multiple (union) data types.&lt;br /&gt;The way that you implement this in Neo4j is that the data type of a node is determined by the &lt;span style="font-style: italic;"&gt;RelationshipType&lt;/span&gt; of the relationship is was reached through. A &lt;span style="font-style: italic;"&gt;n&lt;sub&gt;1&lt;/sub&gt;&lt;/span&gt; has reached through a relationship &lt;span style="font-style: italic;"&gt;r&lt;sub&gt;1&lt;/sub&gt;&lt;/span&gt; with the &lt;span style="font-style: italic;"&gt;RelationshipType&lt;/span&gt; &lt;span style="font-style: italic;"&gt;T&lt;sub&gt;a&lt;/sub&gt;&lt;/span&gt; is said to have the node data type &lt;span style="font-style: italic;"&gt;D&lt;/span&gt;&lt;sub style="font-style: italic;"&gt;a&lt;/sub&gt;, while the same node  &lt;span style="font-style: italic;"&gt;n&lt;sub&gt;1&lt;/sub&gt;&lt;/span&gt; reached through another relationship &lt;span style="font-style: italic;"&gt;r&lt;sub&gt;2&lt;/sub&gt;&lt;/span&gt; with the &lt;span style="font-style: italic;"&gt;RelationshipType&lt;/span&gt; &lt;span style="font-style: italic;"&gt;T&lt;sub&gt;b&lt;/sub&gt;&lt;/span&gt; is said to have the node data type &lt;span style="font-style: italic;"&gt;D&lt;/span&gt;&lt;sub style="font-style: italic;"&gt;b&lt;/sub&gt;. Although it is the same node the application logic will treat it completely different, accessing different properties (with or without overlap). This is a very powerful feature, and not as easy to implement using a label for the nodes to determine the data type of the node.&lt;/p&gt;&lt;p&gt;The &lt;a href="http://wiki.neo4j.org/content/Design_Guide"&gt;design guide for Neo4j&lt;/a&gt; recommends that domain model objects are implemented by wrapping nodes and relationships, and that the wrapper class is determined by the type of the traversed relationship as mentioned above. To make this even more simple the &lt;a href="http://neo4j.org/"&gt;Neo4j community&lt;/a&gt; have developed a few components that automate this process. Most notably there is &lt;a href="http://components.neo4j.org/neo-weaver/"&gt;&lt;span style="font-style: italic;"&gt;neo-weaver&lt;/span&gt;&lt;/a&gt; that automatically implements an interface or abstract class by the means of getting and setting properties on a node/relationship or by traversing relationships.&lt;/p&gt;Happy Hacking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-8699660405760046244?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=l_IN17uMUR0:FHUDCHfE8zw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=l_IN17uMUR0:FHUDCHfE8zw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=l_IN17uMUR0:FHUDCHfE8zw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=l_IN17uMUR0:FHUDCHfE8zw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=l_IN17uMUR0:FHUDCHfE8zw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=l_IN17uMUR0:FHUDCHfE8zw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=l_IN17uMUR0:FHUDCHfE8zw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/l_IN17uMUR0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/8699660405760046244/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=8699660405760046244" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/8699660405760046244?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/8699660405760046244?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/l_IN17uMUR0/about-types-in-neo4j.html" title="About types in Neo4j" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/12/about-types-in-neo4j.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMEQX05fCp7ImA9WxNRFU0.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-853610536676348030</id><published>2008-11-20T13:10:00.004+01:00</published><updated>2009-09-09T15:20:00.324+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-09T15:20:00.324+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="JVM wishlist" /><title>Call frame introspection on the JVM</title><content type="html">&lt;p&gt;One of the pain points of implementing Python on top of the JVM, and in my opinion the worst pain point, is the call frame introspection of Python, and how it is abused throughout Python frameworks. There is in fact a library function &lt;code&gt;sys._getframe()&lt;/code&gt; that returns the frame of the current function, or a deeper frame in the call stack if passed an integer representing the depth.&lt;/p&gt;&lt;p&gt;For Jython this mean that we always have to keep a heap allocated call frame object around for each function invocation, and do all access to local variables through this object. The performance implications of this is absolutely terrible. So any improvement to call frame management would greatly improve performance.&lt;/p&gt;&lt;p&gt;Thinking about how to better implement call frame objects in Jython I thought &lt;span style="font-style: italic;"&gt;“the JVM already manages call frames, and using a debugger I am able to get access to all the aspects of the JVM call frame that I am interested in to construct a Python frame.”&lt;/span&gt;&lt;/p&gt;&lt;p&gt;My first idea on how to implement such a thing was to get under the hood of the JVM and add these capabilities there. Said and done, I checked out OpenJDK and started to patch it to my needs. This actually got me to a working prototype, apart from the fact that I failed to tell the garbage collector that I created extra references to some objects, so they ended up not being equal to null but in every other sense behaving like null. I never tracked down where the problem in my code was, since I found another solution. While I was working on this I found code in the JVM that did things that were surprisingly similar to what I was doing. All of this code was located in a subsystem called &lt;span style="font-style: italic;"&gt;JVMTI&lt;/span&gt;. I looked further into the documentation of the &lt;span style="font-style: italic;"&gt;JVM Tooling Interface&lt;/span&gt;, and found that it had been around since JVMv1.5 (commonly referred to as Java 5). This was great news! If I could create a JVM frame introspection library using JVMTI I would have a library that works for all the JVM versions that we target for the next release of Jython.&lt;/p&gt;&lt;p&gt;It took a while before I actually started implementing the frame introspection library, there were other tasks with higher priority, I read up the documentation of JVMTI and there was also the issue with the build process for JNI-libraries being much more painful than for the nice Java stuff I'm used to, since JNI is C code. The last problem I solved over a weekend two weeks ago by implementing a generic make file and an ant task that feeds make with the required parameters of that makefile. This took me a full weekend, since my makefile skills were never that great to begin with, and even rustier than my C skills. I got it to work for my Mac though, and have yet to test it on other platforms (&lt;span style="text-decoration: line-through;"&gt;Linux will probably be tested and working before the weekend&lt;/span&gt;). This ant task is hosted on Kenai: &lt;a href="https://kenai.com/svn/jvm-frame-introspect~svn/jnitask/"&gt;https://kenai.com/svn/jvm-frame-introspect~svn/jnitask/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Armed with a good way of building JNI libraries I met up with &lt;a href="http://blog.headius.com/"&gt;Charles Nutter&lt;/a&gt; in Malmö, where he was &lt;a href="http://www.oredev.org/topmenu/program/trackcoollanguages/charlesolivernutter.4.3efb083311ac562f9fe80008869.html"&gt;speaking&lt;/a&gt; at the &lt;a href="http://www.oredev.org/"&gt;Øredev conference&lt;/a&gt;, for three days. We managed to get the library working while hacking at various coffee shops in Malmö, it should still be polished a bit but I've published it &lt;strike&gt;in my personal svn repository&lt;/strike&gt; on Kenai: &lt;a href="https://kenai.com/svn/jvm-frame-introspect~svn/frame/"&gt;https://kenai.com/svn/jvm-frame-introspect~svn/frame/&lt;/a&gt; for everyone who wants to take a look. Trying it out should be as simple as:&lt;br /&gt;&lt;code&gt;svn co https://kenai.com/svn/jvm-frame-introspect~svn/frame/ javaframe&lt;br /&gt;cd javaframe&lt;br /&gt;ant test&lt;/code&gt;&lt;br /&gt;The expected output is a few printouts of stack frame content.&lt;/p&gt;&lt;p&gt;The call frame introspection library gives you access to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Access to one call frame at a given depth.&lt;/li&gt;&lt;li&gt;Access to the entire stack of call frames for the current thread.&lt;/li&gt;&lt;li&gt;Access the stack of call frames (without local variables) for any set of threads, or all threads, in the JVM.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Get the reflected method object that the frame is a representation for.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Local variables (if this information is added to the class file by javac)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The number of local variables.&lt;/li&gt;&lt;li&gt;The names of the local variables.&lt;/li&gt;&lt;li&gt;The signatures of the local variables.&lt;/li&gt;&lt;li&gt;The values of the (currently live) local variables.&lt;/li&gt;&lt;li&gt;Locals may be accessed either by name or by index.&lt;br /&gt;There is also a &lt;code&gt;getThis()&lt;/code&gt; method as a shorthand for getting the first local variable, or null if the method is static.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Get the current value of the instruction pointer.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Get the current line number (if this information is added to the class file by javac).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;Update 2008-11-23:&lt;/span&gt; I've added support for getting stack traces of call frame snapshots from multiple threads in the JVM. The &lt;span style="font-style: italic;"&gt;JVMTI&lt;/span&gt; guarantees that the stack traces of all threads are captured at the exact same point of execution. There are method calls for getting traces for a given set of threads or for all JVM threads. These methods do not provide access to the local variables in the frames, since there is no way (apart from suspending the threads) to guarantee that the frame depth is the same at the point of capturing the stack trace as at the point of acquiring the local variables.&lt;br /&gt;I've also made sure that the build scripts work under Linux as well as Mac OS X, and added licensing information (I use the MIT License for this). Also, by request, cleaned up the paragraphs of this entry.&lt;/p&gt;&lt;p&gt;It would be great to get input from my peers on what more information you would like to access from the call frames. The Java bytecode of the method perhaps?&lt;br /&gt;Charles and I also talked about what else we can use JVMTI for, and he was quite enthusiastic about the ability to walk the entire Java object graph, for implementing the objectspace feature of Ruby. One idea would be to write a library that brings the entire functionality of JVMTI to the Java level. The only problem with this would be that a lot of the JVMTI operations don't make much sense unless they are invoked in conjunction with other operations, and that many of the operations are not callback safe, meaning that we cannot allow the execution of arbitrary Java code in between the JVMTI operations. But it should be possible to create an abstraction with a more Java-esque API that performs multiple JVMTI operations at the JNI level.&lt;/p&gt;&lt;p&gt;Another interesting aspect of using JVMTI from Java code is that we can prototype a lot of the functionality that we want the JVM to expose to us directly, and thereby &lt;span style="font-style: italic;"&gt;vote with code &lt;/span&gt;on what we want the JVM of the future to look like.&lt;/p&gt;&lt;p&gt;I hope you will find this useful!&lt;/p&gt;&lt;p style="color: red"&gt;Update: I have move this project to &lt;a href="http://kenai.com/projects/jvm-frame-introspect"&gt;Kenai&lt;/a&gt;, the links have been updated accordingly.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-853610536676348030?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=vnO7jxNdOWs:pnJUa12dPSU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=vnO7jxNdOWs:pnJUa12dPSU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=vnO7jxNdOWs:pnJUa12dPSU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=vnO7jxNdOWs:pnJUa12dPSU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=vnO7jxNdOWs:pnJUa12dPSU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=vnO7jxNdOWs:pnJUa12dPSU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=vnO7jxNdOWs:pnJUa12dPSU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/vnO7jxNdOWs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/853610536676348030/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=853610536676348030" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/853610536676348030?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/853610536676348030?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/vnO7jxNdOWs/call-frame-introspection-on-jvm.html" title="Call frame introspection on the JVM" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>2</thr:total><feedburner:origLink>http://journal.thobe.org/2008/11/call-frame-introspection-on-jvm.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EFSH4-eyp7ImA9WxRSEUs.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5923316278079697925</id><published>2008-09-11T23:25:00.004+02:00</published><updated>2008-09-11T23:46:59.053+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-11T23:46:59.053+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="meta post" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Meta post: Querying languages versus APIs</title><content type="html">This is a &lt;a href="http://journal.thobe.org/2008/09/meta-post-introducing-concept-of-meta.html"&gt;meta post&lt;/a&gt; about the differences between having a querying language and an API for accessing a database. I want to analyze the pros and cons of both approaches. I believe there are benefits of both models, and that they both have weaknesses.&lt;br /&gt;These are my initial ideas on what to discuss in the post:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An API provides a type safe way of operating with the data model.&lt;/li&gt;&lt;li&gt;An API cannot expose query injection weaknesses.&lt;/li&gt;&lt;li&gt;Queries to in a query languages are handled completely internally in the engine, and can therefore be optimized more easily.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Please comment with references on querying languages and your opinion on the pros and cons of the two approaches.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5923316278079697925?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=MSUjISkKyY0:ipnTNq0kKoQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=MSUjISkKyY0:ipnTNq0kKoQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=MSUjISkKyY0:ipnTNq0kKoQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=MSUjISkKyY0:ipnTNq0kKoQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=MSUjISkKyY0:ipnTNq0kKoQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=MSUjISkKyY0:ipnTNq0kKoQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=MSUjISkKyY0:ipnTNq0kKoQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/MSUjISkKyY0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5923316278079697925/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5923316278079697925" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5923316278079697925?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5923316278079697925?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/MSUjISkKyY0/meta-post-querying-languages-versus.html" title="Meta post: Querying languages versus APIs" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/09/meta-post-querying-languages-versus.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMAQH06fSp7ImA9WxRSEUs.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-4340206779502616764</id><published>2008-09-11T21:05:00.004+02:00</published><updated>2008-09-11T23:10:41.315+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-11T23:10:41.315+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="meta post" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Meta post: Introducing the concept of meta posts</title><content type="html">I am introducing a new kind of post in this journal. Meta posts. I have a list of posts that I want to write, each of these are going to be long, and take a while to write. Therefore I thought it would be easier for me, and lead to better posts, if I could get comments on them before I write them. That way I can find out what aspects of the topic to discuss as well as get some references that might be useful for the post.&lt;br /&gt;&lt;br /&gt;These meta posts will carry the tag &lt;a href="http://journal.thobe.org/search/label/meta%20post"&gt;meta post&lt;/a&gt; and I will greatly appreciate any comment on these posts. One of the key features of the meta posts is that I will keep them short, which is why this post ends here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-4340206779502616764?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=LaerG4-od-s:oAhkWFSt7rw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=LaerG4-od-s:oAhkWFSt7rw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=LaerG4-od-s:oAhkWFSt7rw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=LaerG4-od-s:oAhkWFSt7rw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=LaerG4-od-s:oAhkWFSt7rw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=LaerG4-od-s:oAhkWFSt7rw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=LaerG4-od-s:oAhkWFSt7rw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/LaerG4-od-s" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4340206779502616764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/4340206779502616764?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/LaerG4-od-s/meta-post-introducing-concept-of-meta.html" title="Meta post: Introducing the concept of meta posts" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><feedburner:origLink>http://journal.thobe.org/2008/09/meta-post-introducing-concept-of-meta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUHQngzeCp7ImA9WxdVGE0.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5539571411931686410</id><published>2008-07-14T16:56:00.005+02:00</published><updated>2008-07-23T10:53:53.680+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-23T10:53:53.680+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="JVM wishlist" /><title>My JVM wishlist, pt. 1 - Interface injection</title><content type="html">If you've been following what's going on in the JVM-languages community you have probably stumbled across &lt;a href="http://blogs.sun.com/jrose/"&gt;John Roses blog&lt;/a&gt;. One of his entries was about &lt;a href="http://blogs.sun.com/jrose/entry/interface_injection_in_the_vm"&gt;interface injection&lt;/a&gt;. In short wordings &lt;a href="http://openjdk.java.net/projects/mlvm/subprojects.html#InterfaceInjection"&gt;interface injection&lt;/a&gt; is the ability to at runtime add an interface to a class that was not precompiled as implementing that interface.&lt;br /&gt;Interfaces are injected at one of 3 situations:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When a method of the interface is invoked on an object.&lt;/li&gt;&lt;li&gt;When an &lt;code&gt;instanceof&lt;/code&gt; check for the interface is performed on an object.&lt;/li&gt;&lt;li&gt;When the interface is queried for via reflection (I can see this working with &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom%28java.lang.Class%29"&gt;&lt;code&gt;Class#isAssignableFrom&lt;/code&gt;&lt;/a&gt;, but I have my doubts when it comes to &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Class.html#getInterfaces%28%29"&gt;&lt;code&gt;Class#getInterfaces&lt;/code&gt;&lt;/a&gt;, although I'm sure someone smart will be able to solve this without having to know about all injectable interfaces beforehand).&lt;/li&gt;&lt;/ul&gt;When any of these occur a class can either have the interface implemented already (in the regular way) or a special static injection method on the interface class is invoked. It is up to this injection method to determine if the given class can implement the interface or not. If it determines that the class can implement the interface any missing methods have to be supplied at that time. John suggests that these methods are to be supplied as &lt;a href="http://blogs.sun.com/jrose/entry/method_handles_in_a_nutshell"&gt;method handles&lt;/a&gt;. Since &lt;a href="http://openjdk.java.net/projects/mlvm/subprojects.html#MethodHandles"&gt;method handles&lt;/a&gt;, according to the &lt;a href="http://jcp.org/aboutJava/communityprocess/edr/jsr292/index.html"&gt;EDR of the InvokeDynamic proposal&lt;/a&gt; (&lt;a href="http://jcp.org/en/jsr/detail?id=292"&gt;JSR 292&lt;/a&gt;), can be curried this would make it possible to attach an extra state object to the returned method handle, or to return a different implementation of the interface depending on the class they are injected to. Once an injection method of a specific interfaced has been invoked for a specific class, the injection method will never be invoked for that class again, meaning that once a class has been found to not implement an interface, that information will be final, and once an implementation of an interface has been supplied, this implementation can never be changed. This is important since it will allow the VM to perform all optimizations, such as inlining, as before.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;What can this be used for?&lt;/span&gt;&lt;br /&gt;As a language implementer on the Java platform I think interface injection would be a blessing. In fact I think it is the one thing that would simplify the implementation of languages on the JVM the most. Any language probably has a base interface (as Java has &lt;code&gt;java.lang.Object&lt;/code&gt; and Jython has &lt;code&gt;org.python.core.PyObject&lt;/code&gt;), let's be unbiased and call it "&lt;code&gt;MyLangObject&lt;/code&gt;" for the sake of the continued discussion. There are two things that make the Java platform great:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;There are a lot of really good toolkits an libraries implemented for the Java platform.&lt;/li&gt;&lt;li&gt;There are a lot of great languages for the Java platform in which even more great libraries and toolkits will be developed.&lt;/li&gt;&lt;/ol&gt;Therefore, if you are implementing a language for the Java platform you would want to interact with all of these libraries and toolkits. Problem is that most of them haven't been designed with your language in mind, and they shouldn't be. If &lt;code&gt;MyLangObject&lt;/code&gt; was an injectable interface all you would need to do to be able to integrate with any object from another language would be to just interact with it through the &lt;code&gt;MyLangObject&lt;/code&gt; interface, and the injection mechanism would take care of the rest.&lt;br /&gt;The injection mechanism could even be used with the classes within your language.  Instead of having a base class supplying the default implementation of the methods of &lt;code&gt;MyLangObject&lt;/code&gt; you could let the injection method return the default implementation for your methods.&lt;br /&gt;Or why not use interface injection to support function invocation with different argument counts. Each function in your language would implement a set of &lt;code&gt;call&lt;/code&gt; methods, one for each argument count it can be invoked with. Your language would then have a set of injectable &lt;code&gt;Callable&lt;/code&gt; interfaces one for each argument count that any function in your language can be invoked with, each with only one &lt;code&gt;call&lt;/code&gt; method, with the appropriate number of arguments. These interfaces could be generated at runtime if your language supports runtime code generation. The default implementation of the call method in each &lt;code&gt;Callable&lt;/code&gt; interface would of course raise an exception, since the function obviously doesn't support that argument count if it doesn't implement the appropriate method.&lt;br /&gt;Interface injection really does provide a huge set of opportunities.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;How could interface injection implement a Meta Object Protocol?&lt;/span&gt;&lt;br /&gt;There is a great project initialized by Attila Szegedi of the JVM-languages comminuty to create &lt;a href="http://dynalang.sourceforge.net/"&gt;a common meta object protocol&lt;/a&gt; (MOP) for all languages on the JVM. With interface injection this would be a simple task.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Let all objects in your language (that supports the MOP) implement the (probably not injectable) interface &lt;code&gt;java.dyn.SupportsMetaObjectProtocol&lt;/code&gt;. An interface with only one method:&lt;br /&gt;&lt;code&gt;java.dyn.MetaObjectProtocol getMetaObjectProtocol();&lt;/code&gt;&lt;br /&gt;This would return the implementation of the &lt;code&gt;java.dyn.MetaObjectProtocol&lt;/code&gt; interface for your particular language.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;java.dyn.MetaObjectProtocol&lt;/code&gt; contains methods for getting method handles for each dynamic language construct that the community have agreed to be a good common construct, such as getters and setters for subscript operations. These method handles would come from the actual implementation of them for your particular language, and would therefore benefit from every imaginable optimization you have cooked up for your language.&lt;/li&gt;&lt;li&gt;When the main interface of my language is being injected into a class from your language it finds that your class implements &lt;code&gt;java.dyn.SupportsMetaObjectProtocol&lt;/code&gt; and uses that to get the method handles for all dynamic language constructs supported by my language, rebinding them them to the method names used in my language.&lt;/li&gt;&lt;/ol&gt;And as simple as that interface injection has been used to implement a common ground for all languages on the Java platform with &lt;span style="font-weight: bold;"&gt;absolutely no overhead&lt;/span&gt;. I'm not saying that this is &lt;span style="font-style: italic;"&gt;the way&lt;/span&gt; to  implement a meta object protocol for the Java platform, I am just suggesting &lt;span style="font-style: italic;"&gt;one way&lt;/span&gt; to do it, someone a lot smarter than me might come up with a much better implementation.&lt;br /&gt;&lt;br /&gt;To sum things up: I can't wait until the JVM supports interface injection.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Edit&lt;/span&gt;: this post has also been &lt;a href="http://java.dzone.com/articles/my-jvm-wishlist-pt-1-interface"&gt;re-posted on Javalobby&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5539571411931686410?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=BadksL730G0:udcEP8p1544:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=BadksL730G0:udcEP8p1544:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=BadksL730G0:udcEP8p1544:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=BadksL730G0:udcEP8p1544:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=BadksL730G0:udcEP8p1544:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=BadksL730G0:udcEP8p1544:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=BadksL730G0:udcEP8p1544:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/BadksL730G0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5539571411931686410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5539571411931686410" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5539571411931686410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5539571411931686410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/BadksL730G0/my-jvm-whishlist-pt-1-interface.html" title="My JVM wishlist, pt. 1 - Interface injection" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>2</thr:total><feedburner:origLink>http://journal.thobe.org/2008/07/my-jvm-whishlist-pt-1-interface.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MHRXk9eyp7ImA9WxdWF00.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-6158483834556246551</id><published>2008-07-10T15:01:00.004+02:00</published><updated>2008-07-10T16:50:34.763+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-10T16:50:34.763+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="advanced compiler" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="thesis" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>The state of the advanced compiler</title><content type="html">First a disclaimer:&lt;br /&gt;&lt;blockquote&gt;When I say that I will blog regularly, obviously you should not trust me!&lt;br /&gt;I have realized that I don't want to get better at blogging regularly, since I kind of think it's boring and diverts my focus from the more important stuff, the code. But this does not mean that I will not blog more frequently in the future, I might do that, all I am saying is that I will never promise to do more blogging.&lt;/blockquote&gt;Even if I am not blogging on it, the advanced Jython compiler is making progress, just not as fast as I would like it to... So the current state of things in the advanced branch of Jython is that I have pluggable compilers working, so that I can switch which compiler Jython should use at any given time. This enables me to test things more easily, and to evolve things more gradualy.&lt;br /&gt;I am still revising my ideas about the intermediate representation of code, and it is still mostly on paper. My current thinking is that perhaps the intermediate representation should be less advanced than I first had planed. I will look more at how PyPy does this, and then let the requirements of the rest of the compiler drive the need for the IR.&lt;br /&gt;An important change in diraction was made this week. This came from discussion with my mentor, Jim Baker, and from greater insight into how PyPy and Psyco works, form listening to the brilliant people behind these projects at EuroPython. I had originally intended the advanced compiler to do most of it's work up front, and get rid of PyFunctionTable from the Jython code base. The change in direction is the realization that this might not be the best aproach. A better aproach would be to have the advanced compiler work as a JIT optimizer, optimizing on actual observed types, which will probably give us a greater performance boost. This also goes well with the idea that I have always intended of having more specialized code object representations for different kinds of code.&lt;br /&gt;The way responsibilities will be divided in between object kinds in the call chain is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code objects contain the actual code body that gets executed by something.&lt;/li&gt;&lt;li&gt;Function objects contain references to the code objects. This starts out with a single reference to a general code object, then as time progresses, the function gets hit by different types, which will trigger an invocation on the advanced compiler that will create a specialized version of code, that will also be stored in the function for use when that particular signature is encountered in the future.&lt;br /&gt;The functions also contain the environment for use in the code. This consists of the closure variables of the function, and the global scope used in the function.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Frame objects provide the introspection capabilities into running code as needed by the locals() and globals() functions, and pdb and similar tools. There should be a couple of different frame implementations:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Full frames. These contain all of function state. Closure variables, locals, the lot. These are typically used with TableCode implementations of code.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Generator frames. These are actually divided into two objects. One generator state object, that (as the name suggests) contain the state of the generator. This is most of what a regular frame contains, except the previous frame in the call stack. The other object is an object that supports contains the previous frame in the call stack, and wraps generator state object to provide the frame interface.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lazy frames. These are frames that contains almost nothing. Instead they query the running code for their state. I hope to be able to have them access the actual JVM stack frames for this, in which case they will be really interesting.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The function object should be responsible for handling the life cycle of the frame objects, but I have not entierly worked out if the creation of the frame object should be up to the code object or the function object. The code object will know exactly wich implementation to choose, but then again, we might want to have different function implementations as well, so it might make sense to the entire responsibility of frames to functions.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Global scope objects. The global scope could be a regular dictionary. But if we have a special type for globals (that of course supports the dictionary interface) we can have code objects observing the globals for changes to allow some more aggressive optimizations, such as replacing Python loops (over &lt;code&gt;range&lt;/code&gt;) with Java loops (with an int counter), so that the JVM JIT can perform all of its loop unrolling magic on it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Class objects. These are always created at run time, unlike regular JVM classes which are created at compile time. Since classes are defined by what the locals dictionary looks like when the class definition body terminates it is quite hard to determine the actual class, as created at "define time", will look like. Although in most cases we can statically determine what most of the class will look like.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Class setup objects. These are to class objects what code objects are to. These contain the code body that defines a class but also a pre-compiled JVM class that contains what the compiler has determined the interface of the class to be.&lt;br /&gt;Both class objects and class setup object are fairly far into the future though, and will not be part of the initial release of the advanced compiler. They might in fact never be, if I find that there is a better way of doing things before I get there.&lt;/li&gt;&lt;/ul&gt;The other interesting change that the advanced compiler project will introduces, after these specialized call path objects are of course the actual optimizations that they enable:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Type specializations.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Primitive type unpacking. This is of course the first, most simple, and most basic type specialization. When we detect that a specific object (often) is of a primitive number type and used extensively, we can generate a version where the number is unpacked from the containing object, and the operations on the number are compiled as primitive number operations.&lt;/li&gt;&lt;li&gt;Direct invocation of object types. When we detect more coplicated object oriented types we can determine the actual type of the object and find the actual method body for the method we are invoking and insert direct linkage to that body instead of going through the dispatch overhead.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Inlining of builtins. When we detect that a highly used builtin function is extensively used we can inline the body of that builtin, or invoke the builtin function directly without dispatch overhead.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Expression inlining. Some expressions, in particular generator expressions, imply a lot of over head, since they generate hidden functions, that are only invoked localy, quite often at the same place as they are defined. In this case we can immediatley inline the actual action of the expression. So that for exampel a Python expression such as this:&lt;br /&gt;&lt;code&gt;string = ", ".join(str(x) for x in range(14, 23))&lt;/code&gt;&lt;br /&gt;Could be transformed into the following Java snippet:&lt;br /&gt;&lt;code&gt;StringBuilder _builder = new StringBuilder();&lt;br /&gt;for (int _i = 14; _i &lt; 22; _i++) {&lt;br /&gt;    _builder.append(_i);&lt;br /&gt;    _builder.append(", ");&lt;br /&gt;}&lt;br /&gt;_builder.append(22);&lt;br /&gt;string = _builder.toString();&lt;/code&gt;&lt;br /&gt;Or in this particular case, perhaps even constant folded...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Loop transformation. As in the case above the loop over the Python iterator range can be transformed to a regular JVM loop. This might just be a special case of builtin inlining though.&lt;/li&gt;&lt;/ul&gt;The combination of the abstraction and indirection in between the function object and code object and these optimizations are exactly the powerful tool that we need to be able to do really interesting optimistic optimizations while maintaining the ability to back out of such decisions, should they prove to have been too optimistic. All in all providing Jython with a fair improvement in execution speed.&lt;br /&gt;&lt;br /&gt;So that's a summery on what the current work in progress is. If have i look into my magic 8-ball and try and predict the future I would say that one interesting idea would be to have the compiler be able to persist the optimized code versions so that the next time the program is executed, the previous optimizations are already there. This would in fact be a good way of supporting the "test driven oprimizations" that you might have heard Jim and/or me rant about. So there is defenetly cool stuff going on. I cant wait to write the code, and get it out there, which is why I hereby terminate this blogging session in favour of some serious hacking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-6158483834556246551?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nH8fY8wuGto:fV-CIZPcgFM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nH8fY8wuGto:fV-CIZPcgFM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nH8fY8wuGto:fV-CIZPcgFM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nH8fY8wuGto:fV-CIZPcgFM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nH8fY8wuGto:fV-CIZPcgFM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nH8fY8wuGto:fV-CIZPcgFM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nH8fY8wuGto:fV-CIZPcgFM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/nH8fY8wuGto" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/6158483834556246551/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=6158483834556246551" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/6158483834556246551?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/6158483834556246551?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/nH8fY8wuGto/state-of-advanced-compiler.html" title="The state of the advanced compiler" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/07/state-of-advanced-compiler.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQHSXg8fyp7ImA9WxdWF00.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-77347532720872460</id><published>2008-07-10T14:32:00.006+02:00</published><updated>2008-07-10T17:05:38.677+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-10T17:05:38.677+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="PyPy" /><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>EuroPython 2008</title><content type="html">So I've spent 3 days on EuroPython 2008 in Vilnius, Lithuania with my colleges &lt;a href="http://zyasoft.com/pythoneering/"&gt;Jim&lt;/a&gt; and &lt;a href="http://fwierzbicki.blogspot.com/"&gt;Frank&lt;/a&gt;, &lt;a href="http://www.sauria.com/blog/"&gt;Ted from Sun&lt;/a&gt; and of course a lot of other people in the European Python community. Most notably we've spent a fair amount of time talking to the &lt;a href="http://codespeak.net/pypy/dist/pypy/doc/home.html"&gt;PyPy&lt;/a&gt; group. Since they are mostly based in Europe they didn't have a large presence at PyCon.&lt;br /&gt;Jim and I did two talks together. The first one was a tutorial about various ways of manipulating and compiling code in Python, and how to do that while staying compatible across Python implementations. The second was a presentation about the internals of Jython, showing how similar Jython is to CPython internally, and walking through how you go about supporting some of the cool features of Python. We also managed to sneak in some slides about our &lt;a href="http://journal.thobe.org/2008/07/state-of-advanced-compiler.html"&gt;ongoing work with the advanced compiler&lt;/a&gt; and where that will take us (more on that in a later post). From where I was sitting it seemed people were interested in what we were talking about, and I think our presentations were fairly well received.&lt;br /&gt;Yesterday we had a meeting with the PyPy group resulting in a &lt;a href="http://morepypy.blogspot.com/2008/07/ep2008-pypy-meets-jython.html"&gt;list of tasks&lt;/a&gt; on which our two teams are to collaborate. I think this was very interesting and I believe both sides will get substantial benefits from this effort. It is also my hope that this list will not be complete, but that we will find more interesting tasks to collaborate around after the completion of these tasks.&lt;br /&gt;The most important task for us at the moment is to get ctypes ported to Jython and the JVM. This is important for the PyPy team as well since it will make their JVM back end more complete. The way we were outlining it the implementation would be a JNI bridge to _rawffi, the part of ctypes that is implemented in C, and then use the same Python level implementation of the API as PyPy does. Another way of doing it would of course be to use JNA, but I actually think the JNI path might be more maintainable in this case, since PyPy still needs the C version of _rawffi for pypy-c.&lt;br /&gt;Personally I am very interested in the PyPy JIT, and I think that my work on the advanced Jython compiler could be very useful for the PyPy team when they start their effort on a JVM back end of their JIT. I also think that I can use a lot of the ideas they have implemented in their JIT project in the advanced compiler.&lt;br /&gt;I will not go into the entire list of collaboration points, since the PyPy blog post liked above does a good job there, but I would also like to mention the effort of sharing test cases, which I think is highly important.&lt;br /&gt;At the moment Jim and I are in the PyPy sprint room here at EP, and we just have some blogging to do before we get our hands dirty with code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-77347532720872460?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=yl0Lq6__2ZQ:iF7Z5T35OhU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=yl0Lq6__2ZQ:iF7Z5T35OhU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=yl0Lq6__2ZQ:iF7Z5T35OhU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=yl0Lq6__2ZQ:iF7Z5T35OhU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=yl0Lq6__2ZQ:iF7Z5T35OhU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=yl0Lq6__2ZQ:iF7Z5T35OhU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=yl0Lq6__2ZQ:iF7Z5T35OhU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/yl0Lq6__2ZQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/77347532720872460/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=77347532720872460" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/77347532720872460?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/77347532720872460?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/yl0Lq6__2ZQ/europython-2008.html" title="EuroPython 2008" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>1</thr:total><feedburner:origLink>http://journal.thobe.org/2008/07/europython-2008.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUADRH89fyp7ImA9WxdVGEw.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-3728512239224727755</id><published>2008-07-08T10:07:00.007+02:00</published><updated>2008-07-23T13:49:35.167+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-23T13:49:35.167+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Simple stuff with import hooks in Python</title><content type="html">Yesterday Jim an I had a tutorial session at EuroPython about dynamic compilation in Python. We brought up the topics of import hooks (&lt;a href="http://www.python.org/dev/peps/pep-0302/"&gt;PEP 302&lt;/a&gt;) since we have successfully used them as an opportunity to create code dynamically. The code example we demonstrated for that was one of the actual import hooks that we had used in a Jython setup. Even if it was no more than 80 lines of code, it might not have been the most accessible example. A few people asked me afterwords if I had a more simple example, so by public request, here is a simple meta_path hook that prevents the user from importing some modules.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;import&lt;/span&gt; sys&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(51, 102, 255);"&gt;Restriction&lt;/span&gt;(&lt;span style="color: rgb(153, 51, 153);"&gt;object&lt;/span&gt;):&lt;br /&gt;    __forbidden = &lt;span style="color: rgb(153, 51, 153);"&gt;set&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;    @&lt;/span&gt;classmethod&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;    def&lt;/span&gt; &lt;span style="color: rgb(51, 102, 255);"&gt;add&lt;/span&gt;(&lt;span style="color: rgb(153, 51, 153);"&gt;cls&lt;/span&gt;, module_name):&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;       cls&lt;/span&gt;.__forbidden.add(module_name)&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 51, 153);"&gt;    def&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);"&gt;find_module&lt;/span&gt;(&lt;span style="color: rgb(153, 51, 153);"&gt;self&lt;/span&gt;, module_name, package_path):&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;       if&lt;/span&gt; package_path: &lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;       if&lt;/span&gt; module_name in &lt;span style="color: rgb(153, 51, 153);"&gt;self&lt;/span&gt;.__forbidden:&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;       return&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153);"&gt;self&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;    def&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);"&gt;load_module&lt;/span&gt;(&lt;span style="color: rgb(153, 51, 153);"&gt;self&lt;/span&gt;, module_name):&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 51, 153);"&gt;       raise&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153);"&gt;ImportError&lt;/span&gt;(&lt;span style="color: rgb(0, 153, 0);"&gt;"Restricted"&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;sys.meta_path.append(Restriction())&lt;br /&gt;add = Restriction.add&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;"&gt;del&lt;/span&gt; Restriction&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;If we walk through this class from the top we first of all have a set containing the names of the modules that we will not allow the user to import and a method for adding modules to that set.&lt;br /&gt;The next method, &lt;code style="color: rgb(51, 51, 255);"&gt;find_module&lt;/code&gt;, is the method invoked by the import subsystem. It is responsible for locating the requested module and return an object capable of loading it. The arguments passed to &lt;code style="color: rgb(51, 51, 255);"&gt;find_module&lt;/code&gt; are the fully qualified module name and, if the module is a sub module of a package, the path where that package was found. If the module cannot be found one should either return &lt;code style="color: rgb(153, 51, 153);"&gt;None&lt;/code&gt; or raise an &lt;code style="color: rgb(153, 51, 153);"&gt;ImportError&lt;/code&gt;. This is a handy way to delegate to the next import hook or the default import behavior. If it returns a loader object on the other hand, no other import mechanism will be attempted, which of course is useful in this case. So in this implementation we return &lt;code style="color: rgb(153, 51, 153);"&gt;self&lt;/code&gt; if the module name is found to be the one of the modules that we want to prevent the user from importing.&lt;br /&gt;The loader object should implement the method &lt;code style="color: rgb(51, 51, 255);"&gt;load_module&lt;/code&gt;, which takes only one argument, the fully qualified module name and returns the corresponding module or raises an &lt;code style="color: rgb(153, 51, 153);"&gt;ImportError&lt;/code&gt; if the import fails. In this case we know that  &lt;code style="color: rgb(51, 51, 255);"&gt;load_module&lt;/code&gt; is only ever invoked if we want the import to fail, therefore we always raise an &lt;code style="color: rgb(153, 51, 153);"&gt;ImportError&lt;/code&gt;.&lt;br /&gt;There really isn't much more to it. It should be noted however that this isn't a good way to implement security restrictions in Python, since it is possible for any user code to remove the import hook from &lt;code&gt;sys.meta_path&lt;/code&gt;, but I still think it makes for a good introductory example to import hooks.&lt;br /&gt;&lt;br /&gt;Happy hacking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-3728512239224727755?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=CSmd4TFgqzk:VIh8gsVAcYc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=CSmd4TFgqzk:VIh8gsVAcYc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=CSmd4TFgqzk:VIh8gsVAcYc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=CSmd4TFgqzk:VIh8gsVAcYc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=CSmd4TFgqzk:VIh8gsVAcYc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=CSmd4TFgqzk:VIh8gsVAcYc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=CSmd4TFgqzk:VIh8gsVAcYc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/CSmd4TFgqzk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/3728512239224727755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=3728512239224727755" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/3728512239224727755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/3728512239224727755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/CSmd4TFgqzk/simple-stuff-with-import-hooks-in.html" title="Simple stuff with import hooks in Python" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/07/simple-stuff-with-import-hooks-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIBQXY7eyp7ImA9WxZaGUg.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-841980806892250947</id><published>2008-05-05T04:54:00.002+02:00</published><updated>2008-05-05T05:35:50.803+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-05T05:35:50.803+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="thesis" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Jython call frames and Dynamic Languages Symposium</title><content type="html">The call for paper deadline for Dynamic Languages Symposium was last friday (the 25th), I was hard at work the week up until the 25th, working on different implementations of how to represent call frame objects. Sadly I didn't manage to get all the results we wanted and write a paper about it before the CFP deadline for DLS. It was still good work though, I have a few different implementations going now. I still need to do some more testing, benchmarking and comparisons on the different implementations before I publish the results of that here. After that I was swamped with work during the weekend, and then I went to San Francisco for JavaOne, and didn't get reliable Internet connection until now. This sums up why I didn't publish any blog post last week. Besides these updates there isn't more interesting news for this blog post. There will be more to write about on Friday when Jim and I have done our JavaOne presentation. I will post then with an update on how it went. Over and out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-841980806892250947?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=mJpQK-2qjd8:ITxIkTozcnE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=mJpQK-2qjd8:ITxIkTozcnE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=mJpQK-2qjd8:ITxIkTozcnE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=mJpQK-2qjd8:ITxIkTozcnE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=mJpQK-2qjd8:ITxIkTozcnE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=mJpQK-2qjd8:ITxIkTozcnE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=mJpQK-2qjd8:ITxIkTozcnE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/mJpQK-2qjd8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/841980806892250947/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=841980806892250947" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/841980806892250947?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/841980806892250947?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/mJpQK-2qjd8/jython-call-frames-and-dynamic.html" title="Jython call frames and Dynamic Languages Symposium" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/05/jython-call-frames-and-dynamic.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcFRHY5fyp7ImA9WxZbFUQ.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5002944205369984734</id><published>2008-04-18T16:00:00.003+02:00</published><updated>2008-04-19T10:16:55.827+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-19T10:16:55.827+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="thesis" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><title>Jython thesis project</title><content type="html">I need to get better at publishing stuff here. I also need to publish the progress of my masters thesis project.&lt;br /&gt;If you know me you already know that I am doing a thesis project related to my work on Jython. If you don't know me, and/or didn't know that before, you know it now.&lt;br /&gt;The tentative title of the thesis is "Supporting dynamic languages on the present and future implementations of the Java Virtual Machine". I am investigating how we could better represent dynamic languages on the JVM, with focus on Python. As part of this I am evaluating the suggested new features of &lt;a href="http://openjdk.java.net/projects/mlvm/"&gt;the Da Vinci Machine&lt;/a&gt;, and how that project would aid implementations of dynamic languages, Jython in particular. But I am also looking into how to support the benefits of the future platforms on the current versions of the JVM, something I know the entire JVM-languages community is interested in. Furthermore I am also trying to evaluate what the Da Vinci Project has missed, by compiling a wish list of features that the JVM could implement in order to better support dynamic languages. Again, this list is compiled from my findings with Python on the JVM.&lt;br /&gt;I have been working on Jython for about a year now, and I've had the idea of doing my thesis on something related to Jython for quite some time as well. Although it took me some time to define exactly what to do. Mostly because I've had too much fun stuff to do at work. By this post I want to mark an end to that phase. Since of a week ago I have written and submitted &lt;a href="https://projects.thobe.org/jython/attachment/wiki/ProjectPlan/projektplan.pdf"&gt;my project plan&lt;/a&gt; to my examiner, and gotten it accepted. I have also made a few modifications based on the comments I got back.&lt;br /&gt;In the project plan I have stated that I will post weekly updates on the progress of the project here every Friday. So here is the first of those posts.&lt;br /&gt;The most recent achievements, this week, has been that I've set up a computer with the &lt;abbr title="Multi Language Virtual Machine - the Da Vinci Project"&gt;MLVM&lt;/abbr&gt; so that I can start trying out the new features that it has to offer. I have already ported (most of) the compiler I wrote during the Summer of Code to Java. So I have a platform there to continue building this project on.&lt;br /&gt;The most immediate task ahead of me now is writing a paper for the Dynamic Languages Symposium. Me and Jim have some plans for what we would like to publish there, and that is what I am working on at the moment. The compiler doesn't support all the stuff that we want to include in this paper yet though, so I will have to use a slightly slower compiler, with some scheduling restrictions: myself. But hand compiling is a good way to experiment with how to represent code anyway, so I don't mind.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5002944205369984734?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=O777EC0_TsQ:aOd_YHigHg0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=O777EC0_TsQ:aOd_YHigHg0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=O777EC0_TsQ:aOd_YHigHg0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=O777EC0_TsQ:aOd_YHigHg0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=O777EC0_TsQ:aOd_YHigHg0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=O777EC0_TsQ:aOd_YHigHg0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=O777EC0_TsQ:aOd_YHigHg0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/O777EC0_TsQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5002944205369984734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5002944205369984734" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5002944205369984734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5002944205369984734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/O777EC0_TsQ/jython-thesis-project.html" title="Jython thesis project" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2008/04/jython-thesis-project.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYAQXk9eCp7ImA9WxZWFkU.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-2080980961478718505</id><published>2008-03-16T17:00:00.001+01:00</published><updated>2008-03-16T16:59:00.760+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-16T16:59:00.760+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GIL" /><category scheme="http://www.blogger.com/atom/ns#" term="Jython" /><category scheme="http://www.blogger.com/atom/ns#" term="english" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>The next step to increase Python compatability in Jython</title><content type="html">Last night at PyCon, at the Jython dinner (thanks goes to &lt;a href="http://www.sun.com/"&gt;Sun&lt;/a&gt; for feeding us), we followed up a discussion from earlier during the day about Python and concurrency. We realized that CPython is far ahead of us in this area, and that we are lacking in compatibility. After serious brainstorming (and a few glasses of wine), we decided that introducing a Global Interpreter Lock in Jython would solve the entire issue! I hacked together an implementation, while we were having coffee, that is now in trunk. To ensure that this does not break any old code written for Jython the GIL is added as a future feature. To get GIL support today, check out the Jython trunk, start the interpreter, then type:&lt;br /&gt;&lt;blockquote&gt;from __future__ import GIL&lt;/blockquote&gt;Happy hacking!&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-2080980961478718505?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=PHopKSq18bA:XogHulDF0s8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=PHopKSq18bA:XogHulDF0s8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=PHopKSq18bA:XogHulDF0s8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=PHopKSq18bA:XogHulDF0s8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=PHopKSq18bA:XogHulDF0s8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=PHopKSq18bA:XogHulDF0s8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=PHopKSq18bA:XogHulDF0s8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/PHopKSq18bA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/2080980961478718505/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=2080980961478718505" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/2080980961478718505?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/2080980961478718505?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/PHopKSq18bA/next-step-to-increase-python.html" title="The next step to increase Python compatability in Jython" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>2</thr:total><feedburner:origLink>http://journal.thobe.org/2008/03/next-step-to-increase-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYFQ3g5eip7ImA9WB9UGEg.&quot;"><id>tag:blogger.com,1999:blog-3940568014938333882.post-5976136390977354554</id><published>2007-12-17T01:40:00.000+01:00</published><updated>2007-12-17T01:58:32.622+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-17T01:58:32.622+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rant" /><category scheme="http://www.blogger.com/atom/ns#" term="svenska" /><title>Den moderna människans (mitt) förfall</title><content type="html">Jag ligger i skrivandets stund i vår (min och Saras) säng och försöker somna (Sara sover). Ett av de störande momenten som hittils hindrat mig är ett surrande ljud utifrån. Tankarna far precis som de vill, så jag kom att fundera kring möjligheten att det skulle vara någon form av allmänfarlig olycka som låg bakom ljudet, även om det inte lät som ett larm, inte ens ett avlägset sådant. Ifall det nu skulle uppstå en situation i vilken allmänheten skulle varnas, via vilka kanaler skulle det då nå mig?&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Vi har ingen hemtelefon. Hemtelefoner är en onödig utgift för den moderna människan, merparten av all telefonkommunikation går via mobiltelefonin. Därför skulle vi inte nås av telefonlarmsystemet. Jag har för mig att det ska finnas ett sådant, som ska betyda "slå på radion eller TVn för information om säkerhetsåtgärder". Vilket leder oss till punkt 2.&lt;/li&gt;&lt;li&gt;Vi har ingen TV. TV är slöseri med tid som kan användas till mycket bättre saker, och det visas aldrig något bra när man tittar ändå. Vill man koppla av och se något bra ser man en film, och datorn har en DVD-spelare. Ergo: ingen TV. Därför skulle vi inte nås av varningsinformationen som går ut via TV heller.&lt;/li&gt;&lt;/ol&gt;De enda kanalen som återstår är larmsirenerna. Och jag kan inte minnas sisst jag hörde dem testas. Jag skulle kunna tänka mig att samhället räknat med att de ska kunna nå varje medborgare genom TV-nätet eller telefonnätet. Radiotjänst är alltid lika förvånade när man talar om för dem att man inte har någon TV. Och vad jag har förstått är de inte så hårda som de påstrår med att se till att man betalar sin avgift även om man har en TV, just på grund av att systemet förutsätter att alla kan nås via den informationskanalen, och ifall Radiotjänst inte har makten att ta TVn från den som inte betalar sin TV-licens, så har de ju inte heller någon direkt makt att driva in avgiften.&lt;br /&gt;&lt;br /&gt;Bara några tankar som verkade tillräckligt bra i brist på bättre sömn.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3940568014938333882-5976136390977354554?l=journal.thobe.org' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nh8-BimGfUM:ssrEA2PYG7U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nh8-BimGfUM:ssrEA2PYG7U:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nh8-BimGfUM:ssrEA2PYG7U:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nh8-BimGfUM:ssrEA2PYG7U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nh8-BimGfUM:ssrEA2PYG7U:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thobe/wardrobe?a=nh8-BimGfUM:ssrEA2PYG7U:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thobe/wardrobe?i=nh8-BimGfUM:ssrEA2PYG7U:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thobe/wardrobe/~4/nh8-BimGfUM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://journal.thobe.org/feeds/5976136390977354554/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3940568014938333882&amp;postID=5976136390977354554" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5976136390977354554?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3940568014938333882/posts/default/5976136390977354554?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/thobe/wardrobe/~3/nh8-BimGfUM/den-moderna-mnniskans-mitt-frfall.html" title="Den moderna människans (mitt) förfall" /><author><name>Tobias</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07513017652860755184" /></author><thr:total>0</thr:total><feedburner:origLink>http://journal.thobe.org/2007/12/den-moderna-mnniskans-mitt-frfall.html</feedburner:origLink></entry></feed>
