With Blocks in Twoville
In my software engineering class in college, Dr. Drake dropped on us a half-written piece of software that managed a database of movies. Our challenge was to improve it. It was the first and only time I’ve touched Visual Basic, and I remember only one thing about the project and the language: with-statements.
Suppose you’re rattling off a sequence of references to an object:
hero.Name = "Tenshi"
hero.HitPoints = 100
hero.Mana = 40
hero.ClearEffects()
Notice that every line starts with hero
. A with-statement factors out this object prefix:
with hero
.Name = "Tenshi"
.HitPoints = 100
.Mana = 40
.ClearEffects()
end
20-year-old me thought with-statements were fun. Fast-forward to today. 37-year-old me still thinks with-statements are fun.
In Twoville, the programmer creates a shape and then sets many properties to orient and color the shape. There are so many properties to set that I decided to leave them all out of the constructor. For example, here we create a square with a black outline:
square = rectangle() square.position = [0, 0] square.size = [100, 100] square.rgb = [1, 0, 1] square.stroke.rgb = [0, 0, 0] square.stroke.size = 1
I soon tired of writing square
so many times, so I added with-statements to Twoville. Now I can write this:
square = rectangle() with square position = [0, 0] size = [100, 100] rgb = [1, 0, 1] stroke.rgb = [0, 0, 0] stroke.size = 1
I can even deny the square the privilege of having a name:
with rectangle() position = [0, 0] size = [100, 100] rgb = [1, 0, 1] stroke.rgb = [0, 0, 0] stroke.size = 1
During a talk yesterday I sketched out an animation of two circles dancing together forever using with-statements. Both follow a concentric figure-8 pattern, but one travels horizontally and the other vertically. Here’s the end result:
And here’s the Twoville code that produced this animation:
with t start = 0 stop = 40 # Until we get a background command, let's just splat # a big white rectangle across the canvas. with rectangle() position = [0, 0] size = [1000, 1000] rgb = [1, 1, 1] # Horizontal circle with circle() opacity = 0.5 rgb = [0, 1, 1] radius = 50 position = [400, 300] # The first phase is a loop around the left. 0 -> t -> 20 pivot = [300, 300] 0 -> t rotation = 0 t -> 20 rotation = 360 # The second phase is a loop around the right. 20 -> t -> 40 pivot = [500, 300] 20 -> t rotation = 0 t -> 40 rotation = -360 # Vertical circle with circle() opacity = 0.5 rgb = [1, 1, 0] radius = 50 position = [400, 300] # The first phase is a half-loop around the top-left. 0 -> t -> 10 pivot = [400, 200] 0 -> t rotation = 180 t -> 10 rotation = 0 # The second phase loops around the bottom. 10 -> t -> 30 pivot = [400, 400] 10 -> t rotation = 0 t -> 30 rotation = 360 # The third phase is a half-loop around the top-right. 30 -> t -> 40 pivot = [400, 200] 30 -> t rotation = 0 t -> 40 rotation = -180
I wondered if there was a way to situate and spin the circles so that they never collide. After a few experiments, I’m mostly certain that there will always be a collision somewhere. But I haven’t worked out a formal proof and never will—unless I get bored in a talk.