Sunday, August 22, 2010

_Why Yown Is Funny, So You Can Laugh Too

_why, aka whytheluckystiff, was a well known Ruby hacker before he mysteriously decided to erase his online presence.* What you may not know is that he also made a few interesting contributions to the Io community. _why's post on his hackety.org site, "Io Has a Very Clean Mirror" got me back into Io a couple of years ago after I'd been away. It is an interesting bit of synchronicity that I ended up starting this blog on the same day that came to be declared Whyday.

*(Here I should put in a disclaimer: the rumor is that _why is fine, and all he wanted was some peace and quiet away from internet fame.)

Today I want to talk about Yown. Yown is a webserver that _why wrote in Io. Except, it's not just that. It's also a clever practical joke (while still being a functional web server!) I'm the annoying sort who tells a joke and immediately explains, "See, that's funny because..." so if you don't want to read any ***spoilers***, stop now, go pick up a copy of Yown on your own and just start digging in the code; try to figure out how it works. If you're so motivated.

Now, for all those unmotivated folks whose answer to the above was, "let's not and say we did," here's what you would have learned.

First, a quick explanation of what the program does. Like ASP or PHP, you write something that is like a template and Yown builds a complete HTML page from the template to send to a browser. It comes with an example file:

//
// The most trivial Yown app
//
doRelativeFile("../yown.io")

YownSimple := Yown clone do(
  get("/test",
    html(
      title("Hello??")
      h1("THIS IS A TEST")
    )
  )
) run

This loads the Yown.io app, creates a clone of the Yown proto, hands it a page definition, and then calls the run method. We see some stuff in there that looks like HTML, but it doesn't use the angle brackets or closing tags.  We see html, title, h1.  What happens if we add a line, 'strong("is this line in bold?")'?  It does what you'd expect:  it puts <strong></strong> tags around that line of text.

Let me be quite clear:  the example above was also Io code, not just a page template.  It contains some things that appear to be method calls, but we'll find later that there's some funny business going on too.

Hint: to run these examples
(assuming you already have git and Io)

git clone http://github.com/whymirror/yown.git
cd yown
io samples/simple.io

Connect Firefox or another browser to:
http://localhost:8010/test

Then, View Source

So far so good.

When I was investigating Yown for the first time, I next tried making links.  This seemed like a reasonable guess:
//
doRelativeFile("../yown.io")

YownSimple := Yown clone do(
  get("/test",
    html(
      title("Hello??")
      a("www.google.com", "This is a link")
    )
  )
) run

The result?  Oh, too bad:  www.google.com is displayed as text, the second argument is dropped, and there's no link.  The HTML source for the page looks like this:  <html><title>Hello??</title><a>www.google.com</a></html>.  Odd:  Yown seems to have eaten that "a" very matter-of-factly.  Where's href=""?  Let's just find the methods that create these tags; maybe it will show us what the syntax is and we might even be able to add links if they aren't supported.

Here's the file from Yown that applies:
//
// Yown Builder
// html construction kit
//
Builder := Object clone
Builder tag := method(name, nodes,
  inner := ""
  attrs := name split(".")
  if (attrs size > 1,
    name := attrs at(0)
    attrs := " class='" .. attrs slice(1) join(" ") .. "'",
    attrs := ""
  )
  while(nodes,
    if(nodes name != ";",
      inner = inner .. if(nodes argCount > 0, 
        tag(nodes name, nodes argAt(0)), 
        doMessage(nodes))
    )
    nodes = nodes next
  )
  "<#{name}#{attrs}>#{inner}</#{name}>" interpolate
)

Builder forward := method(
  tag(call message name, call message argAt(0))
)

Oookay. Where's 'title()'? How about 'strong()'? Or h1? A href=?

Gaaaah! There's nothing here! What-? How-?

You can grep the Yown directory all you want. The methods are not there.

And that my friends is why Yown is so funny: it's like a man walking on stilts without any stilts. _why is playing a magic trick on us.

OK, but how does it work?

Take a close look at that last Builder method, see it, the one called 'forward'? What that does is any message (aka method call) that the object doesn't understand gets routed to the forward method. In the forward method, _why is using the name of the method as the HTML tag. (The part that says 'call message name'.)  You could pass 'gobblegobble("hello!")' and Yown would turn it into '<gobblegobble>hello</gobblegobble>'!

There are some things you should know about forward(). It's very powerful. Too powerful. Anything you try to define afterwards using := will go to forward() instead. So it will probably be the last slot you define on a particular object. Note that this includes assigning from within the forward() method itself; if you try to use 'self someName := someValue' within forward, it will go into infinite recursion. Use 'self someName ::= nil' before the forward method exists, and then you can safely use 'setSomeName(someValue)' within forward.

Finally, note that anything handled by the object as a method natively will not go on to the forward method. That is obvious from the description of what foward() does, but if you were creating a domain specific language and used forward() for it, it might easily slip your mind when you try to add a keyword to the DSL that happens to already be defined for Io objects. There are alternative ways of creating DSLs using Io reflection that I will cover in a future post.

In the particular case of Yown, forward() is probably the most appropriate technique: it would allow you to define other methods (such as an 'a' method) for builder to handle special cases. If you decide to try extending Yown in this way, note that you'll need to change the inner loop of the Builder 'tag()' method to resend nested messages with arguments back to Builder itself.

Thursday, August 19, 2010

Why Brevity Matters

If you are used to a mainstream language like C# or Java, your introduction to Io will feel like meeting a woman from a spy movie: seductive but also dangerous. Mainstream languages coddle the programmer and take power away from the hacker. They are designed for corporate use, and businesses enforce conformity over productivity. To ensure this, the designers of blub languages limit the meaning of language constructs to a predefined few things and guard every abstraction with syntactic boilerplate. The cost of this overabundance of caution is cumulative: everything takes more code.

Io feels dangerous because all the guard rails are gone. Io allows you to express complex ideas with short code and extend its semantics without calling out your extensions with syntactic boilerplate. Why does this matter? Because in coddling languages that do not allow you this, frameworks and design patterns spring up to fill the gap. This is why these languages have so many frameworks. The trouble is such languages will never really allow to say anything as succinctly as you might like, so just invoking and combining elements from the frameworks themselves takes enough code that the calling code may also need to be abstracted. The alternative is long functions that are too big to fit on the screen or in your head. Yet whether you sweep the cruft under the rug of a framework or leave it in an open pile, it's still the same amount of cruft, just pushed around. Much effort is expended and endless ritual code devoted to the boilerplate rain dance, but the process of programming itself never optimized beyond a local minimum. That is the hallmark of corporate programming.

This is why brevity matters: it is prerequisite to advancing the art of programming past the rut it is stuck in. Every unnecessary keyword stands between you and what you really mean to say. If a language has irreducible syntax no amount of abstraction can allow you to express yourself more succinctly than the atoms of that language. Io is disruptive because its atoms are smaller. It is dangerous because the meaning of those atoms is in the hands of the programmer. Embrace danger and write shorter code, and you will taste freedom.

About This Blog

In the essay "Being Popular", Paul Graham said,
A language also needs to have a book about it. The book should be thin, well-written, and full of good examples.
For years I have wanted to write that book about Io, and I believe now is the time to start. To stay motivated and solicit input from the community at large, I'm going to write the book as a serial in the form of blog posts, once a week every Saturday afternoon until I have enough to collect into an e-book. The chapters will not be posted in order; this is an interactive work and your comments will help direct where it goes.

Some of the posts on this blog will read like a philosophical manifesto, but I hope to balance practical Io programming advice in equal amounts. I believe that, like Unix, Io represents both a thing and a way of thinking.