<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"><channel><title>Paul Joseph Davis</title><link>http://davispj.com</link><description>Semicoherent Writings</description><lastBuildDate>Fri, 02 Apr 2010 04:11:46 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Facelift</title><link>http://davispj.com/2010/04/01/facelift.html</link><description>&lt;pre&gt;Facelift
========

Bit of a CSS facelift. Apologies if I've managed to spam everyone's RSS
Readers with the swap over from ATOM.&lt;/pre&gt;</description><guid>http://davispj.com/2010/04/01/facelift.html</guid><pubDate>Thu, 01 Apr 2010 00:00:00 GMT</pubDate></item><item><title>AGPL != Awesome GPL.</title><link>http://davispj.com/2010/02/19/agpl-not-awesome-gpl.html</link><description>&lt;pre&gt;AGPL != Awesome GPL.
====================

So I was about to write a really funny blog post. It would've been really super
amazingly funny. It was going to go something like such:

A verbatim copy of the AGPL license. And I would rename it to something like the
CGPL - Contemplorary GNU Public License. I was going to replace all the mentions
of Affero with Contemplorary (yes, I made it up) and then rewrite clause 13 that
describes network interaction. My new clause would've read something like:

    13. Willful Contemplation of Enhancement; Use with the GNU General Public License.
    
    Any entity who contemplates or can be shown to have likely entertained
    the notion of contemplating the use or enhancement of The Progarm for
    any purpose shall be required to convey a copy of the covered work plus
    any contemplation of enhancement to anyone willing to receive said copy.
    
    As contemplation is fleeting it is required that all persons having
    obtained a copy of The Program are required to record all thoughts in
    triplicate such that these contemplated enhancements may be conveyed to
    all interested parties. In order to ensure that interested parties are
    able to retain the right to contemplating said contemplations, the
    aforementioned notes must be made publically accessible within five
    business days under applicable local laws.

Yes. I would actually have found that amusing. And I would've gone back and
relicensed a project with it just to see what happens. Nothing would've
happened. But I would've still enjoyed the thought of someone scratching their
head over the whole thing.

As it Turns Out
---------------

I started reading the AGPL and for the first time I really read the copyright
statement:

     Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;
     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.

You're shitting me. The license itself can not be changed? Now IANAL, but does
that really mean I can't make an amusing (to me) alteration to the license?
Assuming derivative work as defined in the license itself I'm gonna have to
guess that yes, making fun of the AGPL by writing a derived license would be a
violation.

So assuming that theory is correct, one of the most popular open source licenses
doesn't allow derivative works of the license itself?

Caveats, Always Caveats
-----------------------

My legal interpretation is probably wrong. Though I doubt that it's so wrong
that a lawyer would say, "Go for it!" And you could argue that allowing copies
may result in brand dilution or something along that vein. I know of no other
license that has a copyright notice on the license itself. The whole thing is
just really messing with my head.

Tumbolia Public License
-----------------------

So, instead of writing that really funny blog post, I'm just going to advertise
a license that more people should be using: the Tumbolia Public License. I've
included a verbatim copy here for reference. I have already released projects
under this license and so should you. Mostly just to screw with the lawyer types
that make us non-lawyer types extremely confused over what it is we're supposed
to be doing with licenses.

                               Tumbolia Public License
 
    Copyright &lt;year&gt;, &lt;name of author&gt;
 
    Copying and distribution of this file, with or without modification, are
    permitted in any medium without royalty provided the copyright notice and
    this notice are preserved.
 
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
      0. opan saurce LOL
&lt;/pre&gt;</description><guid>http://davispj.com/2010/02/19/agpl-not-awesome-gpl.html</guid><pubDate>Fri, 19 Feb 2010 00:00:00 GMT</pubDate></item><item><title>erlang_js - Awesome</title><link>http://davispj.com/2010/01/19/erlang_js_awesome.html</link><description>&lt;pre&gt;erlang_js - Awesome
===================

erlang_js
---------

If you haven't heard, the Basho team released [1] erlang_js [2] today. Its a
linked in driver that provides a Spidermonkey JavaScript context to run JS code
for Erlang. This is interesting to me because it avoids the stdio overhead
incurred by the current Map/Reduce system that CouchDB uses. So I did what any
bored hacker would do: threw erlang_js into the CouchDB build system and hacked
the view generation code to use the in-VM contexts.

Numbers
-------

These times are for the "mega view" reported in seconds from raindrop-perf.py
found here [3].

Run  Trunk  erlang_js
---  -----  ---------
1    13.63  6.89
2    11.16  6.94
3    11.82  6.80

Code
----

Can be found at [4].

Next Up
-------

The communication between Erlang and JS is unnecessarily converting Erlang -&gt;
JSON -&gt; Spidermonkey Objects. I've written the code to go from the external
Erlang representation to Spidermonkey objects directly so I plan on integrating
that in the next couple days to see how these numbers change.

Code Might be Nice
------------------

Just thought that maybe people would be interested in the code that's used to
talk to erlang_js. Its pretty straight forward, though not very elegant on my
side.

    % From couch_query_servers.erl
    start_doc_map(_Lang, Functions) -&gt;
        {ok, Port} = js_driver:new(),
        ok = js_driver:define_js(
            Port, &lt;&lt;"map_support.js"&gt;&gt;, map_support(), 5000
        ),
        lists:foreach(fun(FuncSource) -&gt;
            Source = &lt;&lt;"map_funs.push(", FuncSource/binary, ");"&gt;&gt;,
            ok = js_driver:define_js(Port, Source)
        end, Functions),
        {ok, Port}.

    map_docs(Port, Docs) -&gt;
        Results = lists:map(
            fun(Doc) -&gt;
                Json = couch_doc:to_json_obj(Doc, []),
                {ok, Results} = js:call(Port, &lt;&lt;"map_doc"&gt;&gt;, [Json]),
                lists:map(
                    fun(FunRs) -&gt;
                        [list_to_tuple(FunResult) || FunResult &lt;- FunRs]
                    end,
                Results)
            end,
            Docs),
        {ok, Results}.

    stop_doc_map(nil) -&gt;
        ok;
    stop_doc_map(Port) -&gt;
        js_driver:destroy(Port).
    % EOF

And map_support.js I wrote to avoid having to think to hard on the Erlang side
of things:

    // src/couchdb/priv/map_support.js
    var map_funs = [];
    var results = [];

    var emit = function(key, value) {
      results.push([key, value]);
    };

    var map_doc = function(doc) {
      var ret = [];
      map_funs.forEach(function(func) {
        results = [];
        func(doc);
        ret.push(results);
      });
      return ret;
    };
    // EOF

Shoutout
--------

Go, Basho [5], Go!

References
----------

[1]:  &lt;a href="http://twitter.com/justinsheehy/status/7950307815"&gt;http://twitter.com/justinsheehy/status/7950307815&lt;/a&gt;
[2]:  &lt;a href="http://bitbucket.org/basho/erlang_js/"&gt;http://bitbucket.org/basho/erlang_js/&lt;/a&gt;
[3]:  &lt;a href="/scripts/2010-01-19-raindrop-perf.py"&gt;/scripts/2010-01-19-raindrop-perf.py&lt;/a&gt;
[4]:  &lt;a href="http://github.com/davisp/couchdb/tree/erlang_js"&gt;http://github.com/davisp/couchdb/tree/erlang_js&lt;/a&gt;
[5]:  &lt;a href="http://basho.com"&gt;http://basho.com&lt;/a&gt;&lt;/pre&gt;</description><guid>http://davispj.com/2010/01/19/erlang_js_awesome.html</guid><pubDate>Tue, 19 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Fighting Hype with Hype - RDBMS FTW!!!1!</title><link>http://davispj.com/2010/01/18/fighting-hype-with-hype.html</link><description>&lt;pre&gt;Fighting Hype with Hype - RDBMS FTW!!!1!
========================================

Yay Google Alerts
-----------------

I woke up this morning to an amusing blog post [1] by Ryan Park [2] in my Google
alerts. I tend to read alot of the "RDBMS's are awesome! No, NOSQL is moar
awesome!" with great bemusement. Even though it's a year and a half old it was
amusing enough to motivate me to write out some of the thoughts I had while
reading it.

1. Data integrity is not guaranteed.
------------------------------------

Ryan spends a couple paragraphs talking about how horrible it is that non-RDBMS
systems don't provide data constraints. In general he's pretty spot on here. One
of the first things that tends to get left out of non-RDBMS systems is
constraint enforcement.

There are two and a half points I'd like to make. First, constraints are usually
the first to go because they're costly. Costly to implement and costly at
runtime. Especially when the system is being designed with the ability to run on
multiple machines.

Secondly, there are plenty of people that don't use constraints. Ryan falls
pretty squarely into the "RDBMS's work for me, so they should work for you too"
camp. He appears to know his stuff but what people like Ryan forget is that
there are a lot of people that don't. They use an RDBMS because that's what the
internet says to do. And then they plop an ORM on top of it and never actually
use any of the RDBMS features that are so lauded. As it turns out, lots of these
developers are super happy using a database that doesn't provide constraint
enforcement.

The last half a point I'll make later as it was suggested in a comment on Ryan's
post and applies later on in the conversation.

2. Inconsistency will provide a terrible user experience.
---------------------------------------------------------

Even reading the bullet point on this one and I knew I was in for some fun. I
mean seriously, if that's not proof by assertion then I don't know what is.

Ryan is quite right that developers need to make some things appear consistent
so as to not confuse users. I can't speak to the specifics of SimpleDB, but
obviously someone's using it successfully so I'll assume that its possible.

The two things I'd point out though is that consistency is not limited to those
crazy non-RDBMS people. Even in a traditional three-tier web architecture,
there's the issue with sessions. Basically the issue is that a client needs to
be repeatedly routed to the same application server handling their session.

The other thing I'll point out is an interesting Facebook blog
post [3] I read a couple months ago. Its an interesting look at
how Facebook added a second datacenter on the east coast. A datacenter based on
MySQL no less. I'll draw your attention to the "Cache Consistency" section. And
I'll I'm going to point out is that their solution required modifying MySQL's
query parser. Seriously.

3. Aggregate operations will require more coding.
-------------------------------------------------

For the bullet point, yes, that's more or less true. The argument in support of
this is pretty much non-existent. If Ryan really wanted to make an argument
about aggregates, the best thing would be to go on about how a non-RDBMS
requires you to know what type of aggregates you'll want up front and then do
insert time calculations for these values. While that will work just fine, it
makes ad-hoc queries harder. The ad-hoc issue is the next bullet point, but for
some reason the connection wasn't made.

4. Complicated reports, and ad hoc queries, will require a lot more coding.
---------------------------------------------------------------------------

This was one of my favoqrite bullet points in the whole article. And by favorite
I mean that it produced the most WTF's per word.

Firstly, Ryan points out that there are three general work loads for databases.
(1) General queries that are used by the application, (2) More complicated
queries run by staff for reporting, (3) ad-hoc queries for debugging. I would
pretty much agree with him there. But then he goes on to make the assertion that
points 2 and 3 are better served by SQL.

The entire second paragraph is some sort of weird twisted logic to bolster the
argument that SQL makes reporting super easy. My favorite part of the whole
thing is the quote right in the middle:

    In my previous jobs, our reports often required hundreds of lines of SQL to
    get the right information out of the database. This is a lot of code, but it
    was required to generate the data for our customers.

As far as I can tell, the argument is that SQL makes complex reports easy even
though it still might take hundreds of lines to get the data required. And the
other thing that's not mentioned, these reports can still take a substantial
amount of time to generate. But obviously this is still better than the
non-RDBMS systems where they don't even have SQL! Because obviously its
impossible that an any imperative language could be as good as SQL... because...
because... well I never figured that part out either.

5. Aggregate operations will be much slower if you don't use an RDBMS.
----------------------------------------------------------------------

Yeah. This one is special.

    RDBMSes are highly optimized for performing aggregate operations across huge
    volumes of data. Fast algorithms like the hash join, merge join, and indexed
    binary search have been around for 20 years or more.

Ok. Breathe. I'm assuming that he forgot that joins are not aggregates. And a
binary search, well, shit... I guess the non-RDBMS people really are screwed.
And the second paragraph talks about how the client is going to need to scan the
entire database thus incurring the huge network transfer to even try and compute
an aggregate.

I'll just point out that there are non-RDBMS systems that provide aggregate
functionality and anything that uses a b+tree probably uses binary search.
Remember people, just because you can't think of a different solution to your
problem doesn't mean it can't exist.

6. Data import, export, and backup will be slow and difficult.
--------------------------------------------------------------

Now this is just FUD. Sorry, but there's no better way to say it. If you've ever
had to fit some random piece of data into your existing relational schema you'll
probably agree that this is crap. Munging random data is hard. And if its not
random data then its not really that important. And getting data out? Perhaps
Ryan was being satirical?

7. SimpleDB isn't that fast.
----------------------------

Jan Lehnardt has a couple thought provoking arguments [4] [5] and Volker Mische
[6] provides some interesting fodder as well. Basically, to say something isn't
fast requires you to define what fast is and, generally, no two people will ever
agree on the same definition.

That said, Ryan does make an allusion to this situation when he mentions that
SimpleDB probably needs a larger DB to be measured on. And he also points out
that lots of databases probably fit into RAM.

There's an interesting article [7] by one of the 37signals guys about buying
more RAM instead of sharding. While definitely a valid approach, not everyone
can go out and buy a single machine with 32 GiB of RAM (though obviously that's
getting closer). Though I now curiously wonder what type of disks they have to
keep up with the write load they might have.

8. Relational databases are scalable, even with massive data sets.
------------------------------------------------------------------

I don't have a better response than the commenter jackson [8] on the original
blog post. Once an RDBMS is scaled to multiple machines, lots of the benefits
are nullified and you're dealing with the same issues that the non-RDBMS folks
are.

9. Super-scalability is overrated. Slowing the pace of your product development is even worse.
----------------------------------------------------------------------------------------------

There is definitely a lot of noise in the echo chamber about scalability.
Developers like to talk about needing hundreds of nodes to support their work
load because that's just cool. But in reality, the issue isn't adding the
hundredth node to a system, its adding the second. Regardless of the database
being used, if that second node isn't planned for it'll be painful. Non-RDBMS
systems generally reduce that pain point by discouraging designs that exacerbate
the problems when adding a second node.

10. SimpleDB is useful, but only in certain contexts.
-----------------------------------------------------

I'll file this under the "No shit?" category. There are plenty of places that an
RDBMS might be a better fit than any given non-RDBMS. And vice versa. The
underlying issue that people seem to miss is being able to describe situations
where one might be better than the other.

The bottom line to this whole "My database is better than your database!"
argument is that "You're both right, so STFU!" Eventually people will calm down
and start to realize that there are multiple solutions and the right one will
depend as much on the problem domain as the developer coding the solution. A
better use of time would be finding personal projects and drawing up the
arguments for and against the coded solution so that others might learn from
past experience.

References
----------

[1]:  &lt;a href="http://www.ryanpark.org/2008/04/top-10-avoid-the-simpledb-hype.html"&gt;http://www.ryanpark.org/2008/04/top-10-avoid-the-simpledb-hype.html&lt;/a&gt;
[2]:  &lt;a href="http://www.ryanpark.org/about-2"&gt;http://www.ryanpark.org/about-2&lt;/a&gt;
[3]:  &lt;a href="http://www.facebook.com/note.php?note_id=23844338919"&gt;http://www.facebook.com/note.php?note_id=23844338919&lt;/a&gt;
[4]:  &lt;a href="http://jan.prima.de/plok/archives/175-Benchmarks-You-are-Doing-it-Wrong.html"&gt;http://jan.prima.de/plok/archives/175-Benchmarks-You-are-Doing-it-Wrong.html&lt;/a&gt;
[5]:  &lt;a href="http://jan.prima.de/plok/archives/176-Caveats-of-Evaluating-Databases.html"&gt;http://jan.prima.de/plok/archives/176-Caveats-of-Evaluating-Databases.html&lt;/a&gt;
[6]:  &lt;a href="http://vmx.cx/cgi-bin/blog/index.cgi/benchmarking-is-not-easy:2009-09-23:en,CouchDB,Python,TileCache,geo"&gt;http://vmx.cx/cgi-bin/blog/index.cgi/benchmarking-is-not-easy:2009-09-23:en,CouchDB,Python,TileCache,geo&lt;/a&gt;
[7]:  &lt;a href="http://37signals.com/svn/posts/1509-mr-moore-gets-to-punt-on-sharding"&gt;http://37signals.com/svn/posts/1509-mr-moore-gets-to-punt-on-sharding&lt;/a&gt;
[8]:  &lt;a href="http://www.ryanpark.org/2008/04/top-10-avoid-the-simpledb-hype.html#comment-4308692"&gt;http://www.ryanpark.org/2008/04/top-10-avoid-the-simpledb-hype.html#comment-4308692&lt;/a&gt;
&lt;/pre&gt;</description><guid>http://davispj.com/2010/01/18/fighting-hype-with-hype.html</guid><pubDate>Mon, 18 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Erlang NIF Test</title><link>http://davispj.com/2009/11/23/erlang-nif-test.html</link><description>&lt;pre&gt;Erlang NIF Test
===============

    *NOTE* This tutorial will only work for Erlang R13B03. R13B04 requires a
    newer syntax which I'll get around to blogging soonish, but you can find
    an example at [1] if you need it nowish.

Erlang NIF's
------------

I've been waiting excitedly for the new Natively Implemented Function (NIF)
interface to land in the next Erlang release since I first saw them announced
[2]. Then I saw another message [3] form @dizzyco [4] that was more specific
[5]. So I did what any normal person would do. Read the test suite and wrote a
minimal NIF to figure out the compiling and call semantics.


The NIF Module C API
--------------------

The first thing to note is that a NIF module has four callbacks that are used
for bookkeeping with loading the shared library code: load, reload, upgrade, and
unload. Each function gets an ErlNifEnv* argument, a pointer to some driver
specific data, and (except unload) an ERL_NIF_TERM load_info argument. The
environment and private data pointers are pretty standard for this sort of
thing. I'm not entirely certain what load_info is for. The method for
initializing NIF modules takes a second parameter which may be what this is for,
but I haven't investigated to find out for certain.

After defining each of those four methods, to actually implement the NIF
functions we define a function that takes an ErlNifEnv* argument and zero or
more positional parameters of type ERL_NIF_TERM. These functions will show up in
the Erlang side and can be called as expected.

The code for our minimal NIF module looks like this:

    // mynif.c
    #include &lt;stdio.h&gt;
    #include "erl_nif.h"
    
    static int
    load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
    {
        return 0;
    }
    
    static int
    reload(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
    {
        return 0;
    }
    
    static int
    upgrade(ErlNifEnv* env, void** priv, void** old_priv,
              ERL_NIF_TERM load_info)
    {
        return 0;
    }
    
    static void
    unload(ErlNifEnv* env, void* priv)
    {
        return;
    }
    
    static ERL_NIF_TERM
    do_something(ErlNifEnv* env, ERL_NIF_TERM a1)
    {
        unsigned long val;
        if(!enif_get_ulong(env, a1, &amp;val)) {
            return enif_make_badarg(env);
        } else {
            return enif_make_ulong(env, val*2);
        }
    }
    
    static ErlNifFunc mynif_funcs[] =
    {
        {"do_something", 1, do_something}
    };
    
    ERL_NIF_INIT(mynif, mynif_funcs, load, reload, upgrade, unload)
    // EOF

That's all fairly straight forward. Define the four required functions and just
return 0 to indicate no error. The ErlNifFunc structure appears to be a triple
of {name_in_erlang, arity, name_in_c} calls. There's an example in the
source on having the same Erlang name and different arities. As you'd expect,
you just specify the same string, and change the second value.

The implementation of do_something shows a basic error when the argument is not
an unsigned long. We'll test that this works as expected later.

The Erlang API
--------------

The Erlang side is pretty simple as well. To load a NIF module we just call
erlang:load_nif/2. The first parameter is the path to the shared object to
load. The second parameter I just specify as 0 to follow the test code, I've not
investigated its use though I assume it shows up in the load_info argument in
the module API.

Another thing to note is that the NIF module and its corresponding Erlang module
have overlapping function namespaces. When we define a function in the NIF
module, it shows up in our Erlang module. The tests use a pattern to throw an
error if the Erlang function gets called. In other words, when we load the NIF
module it replaces the Erlang definition, so if we hit the Erlang definition we
report an error.

Our Erlang code looks like this:

    // mynif.erl
    -module(mynif).
    -export([start/0, do_something/1]).
    
    start() -&gt;
        erlang:load_nif("mynif", 0).
    
    do_something(_Val) -&gt;
        nif_error(?LINE).    
    
    nif_error(Line) -&gt;
        exit({nif_not_loaded,module,?MODULE,line,Line}).
    // EOF

Building the Modules
--------------------

Building appears to just be the standard shared object style. I happened to have
an example lying around from my earlier work on an EEP0018 module (which I'll
definitely be revisiting now). The linker dark magic is outside this simple
example, but there are plenty of places that will explain this. I haven't tested
the Linux flags, but they should work just fine.

    // Makefile
    OTPROOT=/Users/davisp/tmp/otp_src_R13B03/
    INCLUDES = -I$(OTPROOT)/erts/emulator/beam/
    
    # OS X flags.
    GCCFLAGS = -O3 -fPIC -bundle -flat_namespace -undefined suppress -fno-common -Wall
    
    # Linux Flags
    #GCCFLAGS = -O3 -fPIC -shared -fno-common -Wall
    
    CFLAGS = $(GCCFLAGS) $(INCLUDES)
    LDFLAGS = $(GCCFLAGS) $(LIBS)
    
    OBJECTS = mynif.o
    
    DRIVER = mynif.so
    BEAM = mynif.beam
    
    all: $(DRIVER) $(BEAM)
    
    clean: 
    	rm -f *.o *.beam $(DRIVER)
      
    $(DRIVER): $(OBJECTS)
    	gcc -o $@ $^ $(LDFLAGS)
      
    $(BEAM): mynif.erl
    	erlc $^
    # EOF

With all three of those files in your $CWD you should be able to just run `make`
and have the proper output in the same directory.

Running the Example
-------------------

A sample console log to show that it behaves as expected:

    $ ~/tmp/otp_src_R13B03/bin/erl
    Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

    Eshell V5.7.4  (abort with ^G)
    1&gt; mynif:start().
    ok
    2&gt; mynif:do_something(0).
    0
    3&gt; mynif:do_something(2).
    4
    4&gt; mynif:do_something(nil).
    ** exception error: bad argument
         in function  mynif:do_something/1
            called as mynif:do_something(nil)
    5&gt; mynif:do_something(2.3). 
    ** exception error: bad argument
         in function  mynif:do_something/1
            called as mynif:do_something(2.3)

And there you have it. This is fairly exciting stuff. I've already got a list of
projects I'm going to play with integrating into the NIF API to see what type of
speedups I can get.

References
----------

[1]:  &lt;a href="http://github.com/davisp/emonk.git"&gt;http://github.com/davisp/emonk.git&lt;/a&gt;
[2]:  &lt;a href="http://twitter.com/FrancescoC/status/5651602607"&gt;http://twitter.com/FrancescoC/status/5651602607&lt;/a&gt;
[3]:  &lt;a href="http://twitter.com/dizzyco/status/5889832914"&gt;http://twitter.com/dizzyco/status/5889832914&lt;/a&gt;
[4]:  &lt;a href="http://twitter.com/dizzyco/status/5891652969"&gt;http://twitter.com/dizzyco/status/5891652969&lt;/a&gt;
[5]:  &lt;a href="http://twitter.com/dizzyco"&gt;http://twitter.com/dizzyco&lt;/a&gt;&lt;/pre&gt;</description><guid>http://davispj.com/2009/11/23/erlang-nif-test.html</guid><pubDate>Mon, 23 Nov 2009 00:00:00 GMT</pubDate></item><item><title>Unix in 13 lines of Python - Mostly trivial</title><link>http://davispj.com/2009/11/17/unix-in-python.html</link><description>&lt;pre&gt;Unix in 13 lines of Python - Mostly trivial
===========================================

I found this [1] fairly amusing, but just a big if statement? So I
ported it to Python. I was reminded that iterating over stdin in Python is
always a bit weird. I generally create an iterator that just yields
sys.stdin.readline() forever, but went more hackish here to conserve lines and
add lulz.

    import sys
    print "You have no mail"

    commands = {
        "uname": lambda args: "Punix 1.0",
        "halt": lambda args: exit(0)
    }
    error = lambda args: "Command not found."

    sys.stdout.write("$ ")
    for line in (sys.stdin.readline() for i in xrange(sys.maxint)):
        print commands.get(line.split()[0], error)(line.split()[1:])
        sys.stdout.write("$ ")

References
----------

[1]:  &lt;a href="http://pwpwp.blogspot.com/2009/11/unix-in-14-lines-of-ruby-its-trivial.html"&gt;http://pwpwp.blogspot.com/2009/11/unix-in-14-lines-of-ruby-its-trivial.html&lt;/a&gt;
&lt;/pre&gt;</description><guid>http://davispj.com/2009/11/17/unix-in-python.html</guid><pubDate>Tue, 17 Nov 2009 00:00:00 GMT</pubDate></item><item><title>CouchDB Boston Meetup - Tues, 10/27/09</title><link>http://davispj.com/2009/10/22/couchdb-boston-meetup.html</link><description>&lt;pre&gt;CouchDB Boston Meetup - Tues, 10/27/09
======================================

A couple out-of-towners are planning on being in Boston, MA next week so I
thought that was a good enough of a reason to organize a bit of a meetup. And by
organize I mean I ask who else is interested.

The current plan is to meetup this comming Tuesday. As you can tell I've spent
quite a lot of time figuring out the details.

Email me [1] if you're interested so I can gauge interest and expected group
size.

References
----------

[1]:  &lt;a href="mailto:paul.joseph.davis@gmail.com"&gt;mailto:paul.joseph.davis@gmail.com&lt;/a&gt;&lt;/pre&gt;</description><guid>http://davispj.com/2009/10/22/couchdb-boston-meetup.html</guid><pubDate>Thu, 22 Oct 2009 00:00:00 GMT</pubDate></item><item><title>Grand Central Dispatch + Clang == Awesome</title><link>http://davispj.com/2009/09/04/gcd-clang-awesome.html</link><description>&lt;pre&gt;Grand Central Dispatch + Clang == Awesome
=========================================

Blocks
------

I read about blocks in 10.6 and they sounded quite cool. So the first thing I
did (after poking at the new Expose) was to try and write a block:

So I started with this:

    #include &lt;stdio.h&gt;

    int
    main(int argc, char* argv[])
    {
        fprintf(stderr, "Creating a closure!\n");
        int x = ^{ printf("hello world\n"); };
        x();
    }

Obviously the int 'x = ^{}' syntax was wrong, but I was banking on compiler
warnings to give me a hint:

    davisp@cube:~/tests/gcd$ gcc -o gcd first.c
    first.c: In function 'main':
    first.c:7: error: incompatible types in initialization
    first.c:8: error: called object 'x' is not a function

Doh! No love. But then an epiphany. The review [1] on Ars Technica
mentioned how Clang (a new compiler) was way more awesome at compiler warnings.
Thanks to a tweet [2] the other day I took it for a spin:

    davisp@cube:~/tests/gcd$ /Developer/usr/bin/clang -o gcd first.c
    first.c:7:13: error: incompatible type initializing 'void (^)(void)', expected
          'int'
        int x = ^{ printf("hello world\n"); };
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 diagnostic generated.

Whoa neato! So make the suggested update:

    #include &lt;stdio.h&gt;

    int
    main(int argc, char* argv[])
    {
        fprintf(stderr, "Creating a closure!\n");
        void (^x)(void) = ^{ printf("hello world\n"); };
        x();
    }
    
And compile and run:

    davisp@cube:~/tests/gcd$ /Developer/usr/bin/clang -o gcd first.c
    davisp@cube:~/tests/gcd$ ./gcd
    Creating a closure!
    hello world

Grand Central Dispatch
----------------------

So the only thing left to do was to set one of our closures up to run in one of
the GCD queues.

    #include &lt;dispatch/dispatch.h&gt;
    #include &lt;stdio.h&gt;
    #include &lt;time.h&gt;

    int
    main(int argc, char* argv[])
    {
        fprintf(stderr, "DO IT!\n");
        dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t i){
            fprintf(stderr, "I: %d\n", i);
        });
        sleep(1);
    }

And try that on for size:

    davisp@cube:~/tests/gcd$ /Developer/usr/bin/clang -o gcd first.c
    davisp@cube:~/tests/gcd$ ./gcd 
    DO IT!
    I: 0
    I: 1
    I: 2
    I: 3
    I: 4
    I: 5
    I: 6
    I: 7
    I: 8
    I: 9

I think me and GCD are going to be very good friends.

One Thought
-----------

So far I'm quite fond of GCD. It looks to be as easy to use as was advertised.
The only thing that worries me is if I start using this for lots of code, I'm
locked to OS X. Some of the scientific bits wouldn't even be worth sketching out
without an implementation for Linux.

I know its only a matter of time, but I haven't the slightest how long that
will be.

References
----------

[1]:  &lt;a href="http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/9#llvm-clang "&gt;http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/9#llvm-clang &lt;/a&gt;
[2]:  &lt;a href="http://twitter.com/binary42/statuses/3689493854"&gt;http://twitter.com/binary42/statuses/3689493854&lt;/a&gt;

&lt;/pre&gt;</description><guid>http://davispj.com/2009/09/04/gcd-clang-awesome.html</guid><pubDate>Fri, 04 Sep 2009 00:00:00 GMT</pubDate></item><item><title>GPL - Makeshift Patriot</title><link>http://davispj.com/2009/07/06/gpl-makeshift-patriot.html</link><description>&lt;pre&gt;GPL - Makeshift Patriot
=======================

The other day Gruber [1] once again linked to a good article [2]. The author,
Daniel Jalkut [3], described his opinion on the effects of using the
GPL [4] as an OSS [5] license. The post can be pretty well summed up with
this quote:

    I suggest that the GPL does more to harm collaborative development
    than it does to help it. - Daniel Jalkut

Today Gruber posted a follow up [6] from Matt Mullenweg [7] that argues the
exact opposite, that Wordpress [8] is successful not in spite of, but because
of the GPL.

Matt, you're wrong.
-------------------

Towards the bottom of Matt's post he goes off on a tangent about how the GPL
protects the rights (as in constitution) of 'users'. He even links to the
Declaration of Independence article at Wikipedia [9]. It'd be heart warming if
it weren't such a fallacy. The core of his argument:

    You are free to do pretty much whatever you want as long as it does not
    infringe on the freedoms of others.

The only way a user has rights to the derivative work is if those rights are
somehow propagated from original to derivative which is exactly why the GPL
exists. Welcome to the beginning, Alice.

Lets rephrase the argument: "The GPL is good because it protects users' rights
which only exist because of the GPL." Recursive FTW!

Bottom Line
-----------

The GPL exists and is used as a tool to further the political and philosophical
agendas of those who choose to use it. This is not a bad thing. As a developer
you are free to do as you choose with your code. As a user I must decide if I'm
willing to abide by your license just as I must choose to obey a closed source
license. But for fuck's sake, don't pretend you're any different than a closed
source licensor. Your onerous requirements annoy the shit out of me just as much
as anyone else's.

References
----------

[1]:  &lt;a href="http://daringfireball.net"&gt;http://daringfireball.net&lt;/a&gt;
[2]:  &lt;a href="http://www.red-sweater.com/blog/825/getting-pretty-lonely/"&gt;http://www.red-sweater.com/blog/825/getting-pretty-lonely/&lt;/a&gt;
[3]:  &lt;a href="http://www.red-sweater.com/about/DanielJalkut.html"&gt;http://www.red-sweater.com/about/DanielJalkut.html&lt;/a&gt;
[4]:  &lt;a href="http://www.fsf.org/licensing/licenses/gpl.html"&gt;http://www.fsf.org/licensing/licenses/gpl.html&lt;/a&gt;
[5]:  &lt;a href="http://en.wikipedia.org/wiki/Open-source_software"&gt;http://en.wikipedia.org/wiki/Open-source_software&lt;/a&gt;
[6]:  &lt;a href="http://ma.tt/2009/07/not-lonely-at-all/"&gt;http://ma.tt/2009/07/not-lonely-at-all/&lt;/a&gt;
[7]:  &lt;a href="http://ma.tt/about/"&gt;http://ma.tt/about/&lt;/a&gt;
[8]:  &lt;a href="http://wordpress.com/"&gt;http://wordpress.com/&lt;/a&gt;
[9]:  &lt;a href="http://wikipedia.org/"&gt;http://wikipedia.org/&lt;/a&gt;&lt;/pre&gt;</description><guid>http://davispj.com/2009/07/06/gpl-makeshift-patriot.html</guid><pubDate>Mon, 06 Jul 2009 00:00:00 GMT</pubDate></item><item><title>Forging - Beats TLAs</title><link>http://davispj.com/2009/06/17/forging-beats-tlas.html</link><description>&lt;pre&gt;Forging - Beats TLAs
====================

Avoiding hate-mail
------------------

I am a fan of testing. I write tests. I try and write good tests that test
functionality and not that a computer can properly add integers. Testing is
great for validating my mental model and checking that refactored code continues
to conform to my mental model.

New analogy!
------------

I just realized the reason why I dislike test driven development. My coding is
like simulated annealing. I work up alternative solutions quickly and iterate
through until I find a local extrema that appears to suck the least. My testing
phases are more like a non-linear cooling optimization at the end. To me these
phases are the final step that gives any particular solution its strength and
confidence.

Slightly differently
--------------------

I code like a blacksmith forges. Get the object of current obsession malleable,
beat on it for awhile and then temper the result. Face it. Forging
etymologically kicks the crap out of all those TLA's.
&lt;/pre&gt;</description><guid>http://davispj.com/2009/06/17/forging-beats-tlas.html</guid><pubDate>Wed, 17 Jun 2009 00:00:00 GMT</pubDate></item></channel></rss>