A Little LOGO

You may remember the LOGO programming language from the old days of Turtle Graphics. If you are like me, you probably remember drawing polygons and stars by typing a command like:

repeat 5 [forward 100 right 72]

This draws a pentagon, and with different numbers plugged in the 3 different places, you can get a infinite variation of shapes.

But it turns out LOGO is more than just forward, turn left, turn right, and repeat - it actually is a pretty powerful language having its roots in LISP.

Much like LISP, the list data type is central to the language. As an example, let's write a sumlist function which just sums the numbers in a list. A list is written like

[1 2 3 4]

So calling the function looks like

print sumlist [1 2 3 4]

This should print 10 as the result.

Like LISP again, LOGO uses linked lists, so the most basic way to iterate a list would be to use tail recursion. We can write sumlist like this

to sumlist :list
	ifelse equal? 0 (count :list)
		[0]
		[(first :list) + (sumlist butfirst :list)]
end

Declaring a function has a nice down-to-earth syntax

to func :param1 :param2 ... statement1 statement2 ... end

The ifelse function simulates an if-else statement, taking 3 parameters, the test condition, a statement block to execute for true and another for false. So here we are saying if the list is empty, return zero, otherwise return the first element of the list plus the sum of the rest(butfirst) of the list. Notice that the statement blocks passed as the second and third arguments to the ifelse function are nothing more than lists. Lists, in addition to acting as literal lists of element, also double as lazily evaluated statement blocks.

Writing recursive functions is usually kinda tedious like the sumlist function that we wrote above, but if you knew a little about functional programming, you know that you can use foldr or reduce to simplify your code. Well, you can do that in LOGO too

to sumlist :list (reduce "sum :list 0) end

Sweet! Now we have a one-liner. You can read up on foldr or reduce if you don't know it - I won't explain it in depth here. Essentially, the reduce function allowed us to refactor our recursive function into a much more succinct form.

Great! But we aren't done yet. There's a yet simpler way to write the function. It turns out that there's already a sum function in UCBLogo - perhaps the most popular implementation of LOGO. It does not act exactly the way we want though. You can sum two numbers together

print sum 1 2

prints 3.

But if you try adding more parameters it'll just ignore them

print sum 1 2 3

still prints 3.

Turns out you can use variable number of parameters, you just have to write it differently

print (sum 1 2 3)

prints 6. This is called the LISP-style call syntax. Notice that a function has a natural arity(number of parameters). In the case of sum the natural arity is 2, but the arity can be changed if you use the LISP-style call syntax. Using the natural arity of the function for lookahead is the reason why LOGO code doesn't have as much parentheses as LISP code. You can write

forward 100 right 45 forward 50 left 80

There is no ambiguity as to what is the correct grouping for this expression because each of the functions forward, right, left take one parameter, and the interpreter uses that information for disambiguation during parsing.

Anyway, I digress. Now, back to the sum function. It turns out we can also call the function using the apply function, much like Javascript's Function.prototype.apply. And so, our final version of sumlist looks like

to sumlist :list apply "sum :list end

Nice! apply takes two arguments: the name of the function to call and the parameter list. We prepend a double quote to sum to make it a string literal to prevent it from being applied as a function.

There's a counterpart for Function.prototype.call in Javascript too, it's called invoke.

print (invoke "sum 1 2 3)

But like Javascript's call() it's also less useful than apply.

Going Further

Joshua Bell wrote a LOGO interpreter in Javascript. That's where you'd go if you want to try out some LOGO right away. Alternatively, download UCBLogo.

blog comments powered by Disqus