Potion

Potion, a short pamphlet. Potion is a new language experiment by _why (known from The Poignant Guide to Ruby, among other things).

I love stuff like this... but then again, I have a thing for obscure and unusual languages. Some ultra-quick impressions:

  • So far, it looks minimalistic and flexible.
  • Borrows more than a little bit from Io. (Not that that is a bad thing...)
  • Not sure I like the "licks", but I will withhold my judgement until I know the language better. You'd think that in a language as dynamic as this, special syntax would not be necessary... but as the article points out, there may be problems with that.
  • Apparently "monkey patching" is allowed, much like Ruby and Io. Dangerous...
  • Interestingly, variable names can contain arbitrary UTF-8 characters. I can think of a few problems with this. On the other hand, it seems refreshing to be able to break out of the tired (letters, digits, underscore) set of choices.

I tried to build and install Potion before on OS X, but ran into some issues... will need to try again sometime.

:: Comments (1)

Thick

According to this Dutch article, "two thirds" of Americans are overweight... Yet another article, while agreeing that US obesity rates are on the rise, claims the percentage is "more than one in four adults", with the highest rate at 32.5% (for Mississippi).

Apparently different standards for "overweight" and "obese" are used here, but unfortunately neither article mentions what they are. (Or, if you're slightly paranoid, you might think that Dutch media enjoy portraying Americans negatively. :-)

In related news, I just got my Weight Loss Coach for Nintendo DS today. (Thanks Childy! ^_^)

:: Comments (5)

Duels of the Planeswalkers

There is a new Magic the Gathering game out for Xbox 360, using Xbox Live Arcade: Duels of the Planeswalkers.

I don't have an Xbox 360 and don't plan to get one, but this is still interesting because there are two articles about the development of the game:

(I don't think there is any relation to Microprose Magic, which had an upgraded version that was also called Duels of the Planeswalkers.)

:: Comments (1)

Bargoens zakwoordenboek

Interessant wel: Zakwoordenboekje van het Bargoensch, via Project Gutenberg. Gepubliceerd in 1906.

Sommige woorden zijn inmiddels tot de "gewone" taal doorgedrongen, zodat iedere Nederlander wel zal weten wat ze betekenen; bijv. dokken, bikken, jatten. Andere woorden, hoewel bekend, klinken nog steeds erg Amsterdams: bajes, gabber, gozer. Sommige zijn minder bekend, maar wel grappig: lummelbout, bevroren hond, hortsik, huppelwater. Sommige woorden komen uit het Jiddisch (mesjoche, goochem), andere zijn weer ontleend aan het Engels (monnie, nijffie).

Er zijn ook woorden die tegenwoordig een andere (hoewel gerelateerde) betekenis hebben; bijv. gajes, dat oorspronkelijk gewoon "volk" betekende (zonder negatieve bijbetekenis); of "mokum", dat stad betekende, maar waar tegenwoordig Amsterdam mee bedoeld wordt.

(Mijn opa kwam uit Amsterdam, misschien dat daarom relatief veel woorden mij als "normaal" voorkomen... :-)

:: Comments

Keyboard

This abKey Revolution keyboard is seriously weird... I would be interested if it didn't have a non-QWERTY layout. =)

white_big

:: Comments (4)

More obscure projects: Magicripper

OK kids, I'm pushing out more personal projects. (There's lots more to come... don't worry, none of them are particularly useful. ;-)

Today's treat is Magicripper, a tool to extract Magic card data from Gatherer. There's a catch, of course... it used to work with the original version of Gatherer, but since they've upgraded the site, it no longer does. I am making it available anyway for two reasons:

1. The tarball includes pre-generated XML files with card data, which may be useful to someone.

2. Looking around on github, I noticed that I am not the only one interested in stuff like this (CCGs etc), so maybe enough people will pester me to update the code so it works with the new site as well. (Passive-aggressive motivation technique ;-)

There was a program called Spellweaver as well, that lets you search the data, much like Magi-Nation Search. (Well, sort of... Magic has a lot more cards than MND, and is much more complex. Wizards likes to come up with new features that break existing assumptions. (Hybrid mana, anyone?)) ... Since the new version of Gatherer is much better than the old one, Spellweaver has probably become obsolete.

:: Comments (3)

dollop grows continuations...

Re: dollop... Continuations now work... or at least a subset of them. This works, for example:

> (+ 1 (call/cc (lambda (k) (+ 3 (k 2)))))
=> 3

Continuations are hairy like Fuzzyman. ;-) So if you don't understand the example above, don't worry, they take a while to wrap your head around. Someday I'll write a "continuations in 60 seconds" post (or maybe a bit more time will be needed :-); until then, this explanation might help.

:: Comments

Heist

Yesterday I stumbled upon this: Heist, a Scheme interpreter in Ruby.

It looks pretty good; it's certainly more advanced than my attempt at a Scheme interpreter in Python (which is, in turn, more advanced than Psyche, and will be released eventually, once I backport some of the dollop code to it). Apparently it supports (among other things) hygienic macros and continuations, features that haven't yet made it into my interpreter.

On a side note, it's interesting to see how different the Ruby code looks compared to Python code. Five years ago I would have said (and did say :-) that Python and Ruby are much more alike than unalike. They still are, but they surely encourage (and discourage) different programming practices and idioms.

:: Comments (2)

A dollop of Lisp

I've written a few (toy) Lisp interpreters over the years. Who hasn't right? :-) At the core of such interpreters, there's the eval-apply cycle. It basically works like this:

  • To evaluate an expression, call eval on it.
  • If the expression is atomic, this is just a matter of a simple name lookup, or the expression evaluates to itself (in the case of literals).
  • If the expression is composite (i.e. a list), it is considered to be a function call, where the first element of the list is a function, and the other elements are the arguments passed to that function. We evaluate all of these elements (again by calling eval on them), then call apply to do the actual function application.
  • If said function is built-in, we just call it, get a result back, and be done. If it's a user-defined function, then we need to evaluate the expressions in that function's body, using the procedure described here.

This is a simplified version -- it doesn't take into account special forms or macros, for example -- but it does capture the essence of the eval-apply cycle.

Anyway, since expressions can be nested arbitrarily deep, it should be clear that eval and apply can and often do call themselves and each other.

Now, when writing a Scheme interpreter in a language like Python, it is tempting to use a straightforward translation of this principle. You write functions (or methods, if you wish) eval() and apply(), which may call themselves and each other. This works rather well -- until you blow the stack. The implementation language's stack, that is... because every call to eval or apply in the Scheme interpreter, also uses the implementation language's call stack.

This is a problem, especially in Scheme, which relies on tail recursion to define "iterative" processes. (These still use recursion, but because of tail call optimization, they operate in constant stack space. See SICP 1.2.1.)

We can simulate tail recursion by using exceptions (as demonstrated by this Cookbook recipe, for example). This is the approach I followed in most of my projects. While it does work, sooner or later you'll run into other problems, because the interpreter is still piggybacking on Python's call stack, rather than having one of its own. So, implementing continuations, for example, becomes very difficult, as the notion of "the calling expression" is implicit.

So, I decided to use a different approach. And now we're finally getting to the point of this blog post. :-)

This time I started with a call stack. The expression we want to evaluate is pushed onto it. For example,

(+ 1 a)

Then, I wrote a method run() which does one "evaluation step" using this call stack. If it's done evaluating, it returns the result value, otherwise it returns None, as an indication that there's still more work to do. (So, in order to evaluate an expression, you call it multiple times until you get a result back.)

How does such an evaluation step work? We take the topmost expression on the call stack, and start evaluating it. In this case, it's a composite expression, so we just start at the beginning. We want to evaluate the symbol +. To do so, we push + onto the stack, and put a placeholder in its original position, indicated by "$$".

;; call stack now looks like:
($$ 1 a) +

We're now done with this step. In the next step, we again look at the topmost expression on the stack. It's a symbol; we look it up, get a function back (represented by <lambda:+>, and stick it back into the original expression. We then move on to the next element of the list, which is 1, and push it.

(<lambda:+> $$ a) 1

Another step, and we get:

(<lambda:+> 1 $$) a

Let's say the variable a has been defined and its value is 4. We then get:

(<lambda:+> 1 4)

Now we're done evaluating the elements of this expression, and we can do the actual function application. Finally, we get the result 5.

This gets more complex when we use nested expressions, but the principle is the same.

(+ (* a (- c d)))
($$ (* a (- c d))) +
(<lambda:+> $$) (* a (- c d))
(<lambda:+> $$) ($$ a (- c d)) *
(<lambda:+> $$) (<lambda:*> $$ (- c d)) a
(<lambda:+> $$) (<lambda:*> 4 $$) (- c d)
;; ...etc...

It becomes more interesting when we introduce special forms into the mix. But since we have an explicit call stack now, we can clearly see what is going on with it, and tail recursion starts making much more sense. For example, if our topmost expression is

(if condition (do-this) (do-that))

and during evaluation we determine that condition evaluates to true, we can at that point replace the whole expression by

(do-this)

rather than having to push (do-this) and then sticking the result back into the if expression. Ditto for the last expression inside a begin block, and so on.

The special forms require a bit of hackery, since we don't evaluate all of their arguments... but there's only a few of them.

The proof-of-concept implementation that uses this concept is called dollop and is available at github. (Requires Python 3.0.) The name is because it's only a "dollop of Lisp" (or rather, Scheme); it only supports a few special forms (begin, define, if, lambda), and a few functions for example programs (+, -, *, =, list). It cuts corners in other ways as well, as my goal was to get a working proof-of-concept out, not to write a complete Scheme interpreter.

Anyway, comments, bug fixes, improvements, etc, welcome.

(I will also release two other Lisp-y interpreters, but those will get blog posts and project pages of their own...)

:: Comments (3)

The Underworked American

The Underworked American: Children are exceptions to the country’s work ethic. Yeah, no kidding. There is so much I could say about this...

I'm not sure if the "American work ethic" is so much better than the European one, though. Or at it applies at all here. If this was a matter of work ethic, you'd think that Americans would instill these values into their children. On average, this just doesn't happen. The general consensus seems to be that it's OK for kids to be lazy (or to have other vices, for which plenty of excuses are conjured up... but I won't go into that right now).

The fact that Americans have to work more than Europeans, probably has to do with the way worker movements evolved. In most European countries, these movements fought for better worker rights. In the US, such movements were much weaker or non-existent, so as a result, Europeans tend to have more paid holidays, better unemployment compensation, etc. I think the current situation has more to do with that, than that Americans *like* to work hard.

By contrast, in Asian countries like Japan and Korea, working hard is generally considered "good" and admirable. Over here in the US, the feelings seem to be more mixed. Long work days are just something you have to put up with (mostly because you have no other choice). You can brag about it, but who really is envious?

On a side note, the article claims that "the average American gets only four weeks of paid leave a year". Who actually gets that? I don't think I know of a single person here who does. From what I have seen, you should be glad to get any paid vacation at all. But then again I'm in Florida; maybe the situation is better up north or in California.

(Also, I'm not sure about the lengths of the school weeks described here... 60 hours in Sweden? I'll have to ask around to check if that is true...)

[Disclaimer: The above is simply based on what I've seen and experienced here in the US. And, I'm sure you like to work hard and your kid does too. Great! But I'm talking about the average American here. :-)]

:: Comments (4)

« Previous entries