Monthly Archives: December 2006

Pathological Stack Hell: Underload

Our pathological language this week is [Underload][underload]. Underload is, in some ways, similar to Muriel, only it’s a much more sensible language. In fact, there are actually serious
practical languages called *concatenative languages* based on the same idea as Underload: [Joy][joy] and [Factor][factor] are two examples.
[underload]: http://esoteric.voxelperfect.net/wiki/Underload
[muriel]: http://scienceblogs.com/goodmath/2006/11/friday_pathological_programmin_5.php
[joy]: http://www.latrobe.edu.au/philosophy/phimvt/joy.html
[factor]: http://www.factorcode.org/
Underload is a remarkably simple language. It’s stack based, like Forth, so all of the data is stored on the stack. Its only means of control is constructing a program on the stack and executing it; and the only data that it can manipulate is lists of characters.
The commands in Underload are:
* `~` – swap the top two elements on the stack.
* `:` – duplicate the top element on the stack.
* `!` – discard the top element on the stack.
* `*` – concatenate the two elements on top of the stack into a single list.
* `a` – take the element on top of the stack, and wrap it in “()”s.
* `(…)` – push the contents of the parens on the stack as a single stack element.
* `S` – print the element on top of the stack.
* `^` – take the element on top of the stack, and append it to the currently executing program
string.
As usual, we’ll start with a “Hello world” program.
(Hello world!)S
Simple, right?
Suppose we wanted to add two numbers. The easiest way to handle numbers in Underload is unary format. So suppose want to add 3 + 5. First, we need to put 3 and 5 on the stack. We can represent three as a list `xxx` and 5 as a list `xxxxx`. To push those onto the stack, we need
to wrap them in parens; and t add them, we want to just concatenate the two lists. So the program to add 3 + 5 and print the result is:
(xxx)(xxxxx)*S
As you’d probably expect, an Underload quine is extremely simple:
(:aSS):aSS
I’ll walk through that just to make it clear. First, the list `”:aSS”` is pushed onto the stack, so writing the stack as a list of comma separated elements, the stack is “`[:aSS]`”. Then we execute “:”, which duplicates the top of the stack, leaving “`[:aSS,:aSS]`”. Then we execute “a”, which wraps the element on top of the stack in parens, giving us “`[(:aSS),:aSS]`”. Now there are two “S” commands, which output the two top stack elements; so the out is `(:aSS):aSS`.
A program to generate the fibonacci series is also pretty simple:
(()(*))(~:^:S*a~^a~!~*~:(/)S^):^
It looks like a nighmare, but it’s really not bad. It starts with “()” (0) and “(*)” (1) on the stack. And the rest of the program basically copies the larger number, adds the smaller and larger (giving the next element of the sequence), leaving two fibonacci numbers of the stack. It duplicates the larger, prints it, and then goes on to the next iteration. The body of the program is `(~:^:S*a~^a~!~*~:(/)S^)`, which at the very beginning `(~:^)` duplicates itself.
There’s an online interpreter for [Underload][interp] which does single-stepping. I recommend popping over there, and watching the fibonacci series program execute. It’s much more interesting to watch it in action than it would be to read my detailed description of it!
Now, is this Turing complete? It’s a little hard to see. But the author of Underload took care of that question, by showing how to compile [Unlambda][unlambda] into Underload.
* Unlambda “`s`” translates to Underload “`((:)~*(~)*a(~*(~^)*))`”
* Unlambda “`k`” translates to Underload “`(a(!)~*)`”
* Unlambda “`i`” translates to Underload “`()`”.
* Unlambda “““” translates to Underload “~^”.
* Unlambda “`.x`” translates to Underload “`((x)S)`”.
[interp]: http://esoteric.voxelperfect.net/files/underload/underload.html
[unlambda]: http://scienceblogs.com/goodmath/2006/08/friday_pathological_programmin_3.php

Nullity – the Nonsense Number

Tons of folks have been writing to me this morning about the BBC story about an idiot math teacher who claims to have solved the problem of dividing by zero. This is an absolutely *infuriating* story, which does an excellent job of demonstrating what total innumerate idiots reporters are.

What this guy has done is invent a new number, which he calls “nullity”. This number is not on the number line, can’t be compared to other numbers by less than or greater than, etc. In other words, he’s given a name to the basic mathematical concept of “undefined”, and proclaimed that this is somehow a solution to a deep and important problem.

The thing is, there is no problem. We understand what division by zero means. You can’t do it. There is no number that meaningfully expresses the concept of what it means to divide by zero.

You can assign a name to the concept of “not a number”, which is what this bozo has done; but that’s not new! The standard floating point representation used by computer hardware manufacturers (NaN (Not a Number). NaN works as you should expect a non-number to work: it can’t be compared to anything, and no arithmetic operation works on it – because comparisons and arithmetic only work on numbers.

What he’s done is to take projective geometry – which (as I mentioned in the Steiner post a few weeks back) gives you some useful ways of using infinity; added the concept of a NaN value called nullity, and redefined the multiplication and division operators so that they’re defined to be able to produce nullity.

What good is it? Well, the crank behind it claims two things:

  1. That currently, dividing by zero on a computer causes problems because division by zero is undefined. But if computers adopted nullity, then division by zero errors could be gotten rid of, because they’ll produce nullity. Except of course that modern floating point hardware already does have a NaN value, and it doesn’t help with the kind of problem he’s talking about! Because the result is not a number; whether you call it undefined, or you define it as a value that’s outside the set of real numbers, it doesn’t help – because the calculation you’re performing can’t produce a meaningful result! He says if your pacemaker’s software divides by zero, you’ll die, because it will stop working; how will returning nullity instead of signalling a divide by zero error make it work?
  2. That it provides a well-defined value for 00, which he claims is a 1200 year old problem. Except that again, it’s not a problem. It’s a meaningless expression! If you’re raising 0 to the 0th power in a calculation, then something’s wrong with that calculation. Modifying basic math so that the answer is defined as NaN doesn’t help that.

Basically, he’s defined a non-solution to a non-problem. And by teaching it to his students, he’s doing them a great disservice. They’re going to leave his class believing that he’s a great genius who’s solved a supposed fundamental problem of math, and believing in this silly nullity thing as a valid mathematical concept.

It’s not like there isn’t already enough stuff in basic math for kids to learn; there’s no excuse for taking advantage of a passive audience to shove this nonsense down their throats as an exercise in self-aggrandizement.

To make matters worse, this idiot is a computer science professor! No one who’s studied CS should be able to get away with believing that re-inventing the concept of NaN is something noteworthy or profound; and no one who’s studied CS should think that defining meaningless values can somehow magically make invalid computations produce meaningful results. I’m ashamed for my field.

Bad Math and Ethanol

One thing I’ve been hearing a lot lately is discussions about Ethanol, and it’s been
really pissing me off. Can ethanol be a serious replacement for oil as a source of energy? I don’t know. Because *both* sides are using really bad math to make their arguments.
There are two fundamental questions about ethanol as fuel where the bad math comes in:
1. How much energy does it cost to *produce* ethanol compared to the amount of
energy released by *consuming* ethanol?
2. How much pollution is generated by the process of producing ethanol?
There are numerous reports or studies from both sides of the political spectrum that quote the
supposed “fact” that ethanol product consumes more energy than can be produced by burning ethanol. But that fact dates back to a single study, which is at best misleading, and at worst, deliberately deceptive.

Continue reading

A Tree Grows Up in Haskell: Building a Dictionary Type

Last time around, I walked through the implementation of
a very simple binary search tree. The implementation that I showed
was reasonable, if not great, but it had two major limitations. First,
it uses equality testing for the search, so that the implementation is only really suitable for use as a set; and second, because it’s such
a trivial tree implementation, it’s very easy for the tree to become
highly unbalanced, resulting in poor performance.

Today, we’ll look at how to extend the implementation so that our BST
becomes useful as a key/value dictionary type. We’ll take two different
approaches to that, each of which demonstrates some common Haskell
techniques: one based on on using higher order functions, and one based on
using tuples. Balancing the tree will be a task for another day.

As an aside: in a real Haskell program, you would probably never write a simple type like this. Haskell has a great library, and it’s got plenty of library types that do a much better job than this. This
is really only for tutorial purposes.

Continue reading

Interesting Parallels: The Leader Election Problem and Notch Receptors

Yesterday at Pharyngula, PZ posted a description of his favorite signaling pathway in developmental biology, the [Notch system.][notch] Notch is
a cellular system for selecting one cell from a collection of essentially indistinguishable cells, so that that one cell can take on some different role.
What I found striking was that the problem that Notch solves is extremely similar to one of the classic problems of distributed systems that we study in computer science, called the leader-election problem; and that
the mechanism used by Notch is remarkably similar to one of the classic
leader-election algorithms, called the [Itai-Rodeh algorithm][ir].
[notch]: http://scienceblogs.com/pharyngula/2006/12/notch.php
[ir]: http://citeseer.ist.psu.edu/itai81symmetry.html
Before I go into detail, I think it’s worth throwing a bit of a dig at
some of the IDist type bozos. This is very much the kind of thing
that IDists look for; they try to find natural systems that strongly
resemble designed systems, so that they can assert that the natural
system must have been designed. But the people allegedly doing ID
research *don’t bother to study the fundamental science*. No one in
ID-land is studying developmental biology, to really understand
the complex signaling pathways, and what I would call the algorithmic
way that they operate. I think it’s quite damning to their arguments
that they don’t study this; but I also think I know *why*. If you
read PZs article, and you starting looking in depth into developmental
pathways, and understanding how they fit together, and how very small
changes in a process can produce drastically different results – well, it
really sort of pulls the carpet out from under the ID argument. You can really see just how these systems evolved in terms of gradual changes. Just look at Notch – how simple the behavior is, how widely it’s used to produce very *different* kinds of differentiation, and how easily the
process can be perturbed to produce different results.

Continue reading

Building Datatypes in Haskell (part 1)

For this post, I’m doing a bit of an experiment. Haskell includes a “literate” syntax mode. In literate mode, and text that doesn’t start with a “>” sign is considered a comment. So this entire post can be copied and used as a source file; just save it with a name ending in `”.lhs”`. If this doesn’t work properly, please post something in the comments to let me know. It’s more work for me to write the posts this way, so if it’s not working properly, I’d rather not waste the effort. I’ve tested it in both Hugs and ghci, and everything works, but who knows what will happen after a pass through MovableType!

Like most modern programming languages, Haskell has excellent support for building user-defined data types. In fact, even though Haskell is very much not object-oriented, most Haskell programs end up being centered around the design and implementation of data structures.

So today, I’m going to start looking at how you implement data types in Haskell. What I’m
going to do is start by showing you how to implement a simple binary search tree. I’ll start with
a very simple version, and then build on that.

Continue reading

Functions, Types, Function Types, and Type Inference

Haskell is a strongly typed language. In fact, the type system in Haskell is both stricter and more
expressive than any type system I’ve seen for any non-functional language. The moment we get beyond
writing trivial integer-based functions, the type system inevitably becomes visible, so we need to
take the time now to talk about it a little bit, in order to understand how it works.

Continue reading

Pathological Programming: Do we need to have our wires crossed?

I’m sure that in the friday pathological programming languages, I have a fondness for languages
that make your code beautiful: languages like [SNUSP][snusp], [Befunge][befunge], [Piet][piet], and such. Those languages all you two-dimensional layouts for their programs.
[snusp]: http://scienceblogs.com/goodmath/2006/08/beautiful_insanity_pathologica.php
[befunge]: http://scienceblogs.com/goodmath/2006/07/friday_pathological_programmin.php
[piet]: http://scienceblogs.com/goodmath/2006/11/programming_in_color_fixed.php
Among the nutters that make up the community of folks interested in this kind of thing, looking
at these languages led to a theoretical question, which was named *”the wire-crossing problem”*. The
basic question was:
>Is it possible to define a two-dimensional flow-based language which does *not* ever need
>one execution path to *cross* another execution path?
Alternatively:
>Is it possible to express every computable function as a two-dimensional graph
>where no edges ever cross?
This question raged for quite a while without an answer. Todays pathological language is
a very simple language designed for the sole purpose of demonstrating, once and for all, that
*yes*, you can write every computable function with no wire-crossing.

Continue reading