Wishful Coding

Didn't you ever wish your computer understood you?

My girlfriend in Rust

Some people don’t like to say “my girlfriend”. They think it implies ownership over the person. Lets explore that using Rust. Swap genders at will.

struct Human {
    name: str
    // ???
}

Even though Rust is not object oriented, I’m sorry for objectifying Alice here.

let bobs_girlfriend = Human { name: "Alice", /* ??? */ };

This is what some people think when they hear “my girlfriend”, Bob owns Alice in this cenario.

let charlies_friend = &bobs_girlfriend;

Charlie can only borrow Alice, Bob maintains ownership of Alice, the compiler enforces monogamy.

That is not how it works, lets try again.

use std::rc::Rc;
use std::option;

let alice = Rc::new(Human { name: "Alice", /* ??? */ });

The name “Alice” refers to Alice, who is now owned by the reference counter. In this digital world it’s like a god, it decides who lives and dies.

let mut bobs_girlfriend = Some(alice.clone());

“Bobs girlfriend” is a reference to Alice, no more or less than the name “Alice”. Bob owns the reference, but not Alice.

assert!(*alice == *(bobs_girlfriend.unwrap()));

“Alice” and “Bobs girlfriend” are the same thing, though the latter is mutable and optional.

assert!(*(bobs_girlfriend.unwrap()).beautiful == true);

This throws a compiler error; Beauty is in the eye of the beholder.

let mut charlies_girlfriend = Some(alice.clone()); // Polygamy

Charlie does not own Alice either.

charlies_girlfriend = None
bobs_girlfriend = None

If you are forgotten, do you cease to exist? Better not find out. Love the ones dear to you. You’ll never know when they will be garbage collected.

Pepijn de Vos

Raspberry Pi as my primary computer

my work

It occurred to me that most of the work I do on my shiny dual core i7 ultrabook is using VIM, Python, ssh, and other command-line tools. So why do I need a fast CPU and fancy graphics?

When the Raspberry Pi B+ was released, I knew I had to try this. I ordered one, installed Raspbian and all the stuff I needed, and took it to work.

my desk

I hooked up an external monitor, keyboard, and mouse. Then I sneaked a LAN cable into the WiFi hotspot and set to work.

I decided to forgo X entirely. As I mentioned, I use mostly terminal applications, and alternatives for the few GUI apps I use are readily available.

After a week, I can say it worked surprisingly well. I could pretty much do my job as usual. Most applications never used much CPU or memory. And even while compiling Python 3.4 from source, my terminal stayed snappy.

The only mayor problem is browsing the web. Elinks is pretty good, and most things that do not use JS are usable, but it’s not ideal. At times I had to startx and fire up Midori. It’s so much slower and resource hungry than elinks though.

On the upside, RFC’s look pretty much unchanged. Still dry and boring.

The one application that makes this work is tmux. Without tmux there is no way this would ever work. Tmux is my tiling window manager. Everything I do, I do it in tmux.

The best part is that you can startx, open a terminal, run tmux attach and continue working alongside the sluggish GUI apps. You could even walk over to a colleague, ssh to your machine and work there.

I use fbterm as my terminal emulator. This allows you to use your favourite monospaced font in a framebuffer. I use Zsh for my shell. I can highly recommend the .zshrc from grml.

I recommend that you enable overclocking and adjust the memory split to 16MB to give you all the resources you can get. However, this is mostly for web browsing, on the console you don’t notice the difference.

During the weekend before the experiment, I had a lot of fun setting up all the tools I need and more.

I set up alpine for email and weechat for IRC, but also youtube-dl and mplayer for playing videos in a framebuffer.

I did experiment with netsurf. A graphical browser in a framebuffer. The problem is that there is still no JS, and there is no way to quit it. So for times that elinks is not enough, you really want proper webkit.

In the case you want to try this, here are some essential keyboard shortcuts I learned in te past few days.

Tmux commands are all prefixed with ctrl+b. Put set -g mode-keys vi in ~/.tmux.conf for copying to work.

c   new pane
p   previous pane
n   next pane
0-9 go to pane
%   split vertically
o   other split pane
[   start selection/scroll mode
        space start selection
        enter copy selection
        v     toggle block selection
        q     exit mode
]   paste selection

VIM commands for working with tabs

:tabedit {file} open file in new tab
gt              go to next tab
gT              go to previous tab
{i}gt           go to tab in position i

Elinks also has tabs. I created a little alias to launch google results from the terminal directly.

t create tab
c close tab
> next tab
< previous tab
g go to url
G edit url

Weechat is mostly controlled by IRC commands I used anyway such as /join and /quit. To switch buffers you press alt+0-9. It really helps to install the buffers.pl script so you can see a numbered list of them.

If you startx use, ctrl+alt+F1-F7 to change TTY.

Pepijn de Vos

Mature HTTP client for asyncio

I have recently started writing a server for some obscure protocol using Python’s new asyncio module.

The module works great for writing the server, but any external IO the server has to do is tricky. There are simply not so many libraries, and asyncio doesn’t do patching the way gevent does.

The quick and dirty solution is to use run_in_executor to run blocking code in a thread.

The only other game in town for HTTP is aiohttp, which is relatively young and occasionally buggy.

Then I found that Tornado has support for running on the asyncio event loop. Tornado includes a much more mature HTTP client that can optionally use libcurl.

The Tornado HTTP client returns a Future that is similar but not compatible with Futures from asyncio. So in order to use Tornado in a asyncio coroutine, a little wrapper is needed.

from tornado.platform.asyncio import AsyncIOMainLoop
from tornado.httpclient import AsyncHTTPClient
import asyncio

# Tell Tornado to use the asyncio eventloop
AsyncIOMainLoop().install()
# get the loop
loop = asyncio.get_event_loop()
# the Tornado HTTP client
http_client = AsyncHTTPClient()

# wrap the Tornado callback in a asyncio.Future
def aio_fetch(client, url, **kwargs):
    fut = asyncio.Future()
    client.fetch(url, callback=fut.set_result, **kwargs)
    return fut

# enjoy
@asyncio.coroutine
def main():
    print("fetching my site")
    mysite = yield from aio_fetch(http_client, "http://pepijndevos.nl/")
    print("my site said", mysite.reason)
    print("hello httpbin")
    httpbin = yield from aio_fetch(http_client, "http://httpbin.org/get?code=%d" % mysite.code)
    print(httpbin.body.decode())

print(loop.run_until_complete(main()))
Pepijn de Vos