Logo is an interesting ProgrammingLanguage
, designed by SeymourPapert
for children, once much used in schools, and never fully appreciated.
Logo as a FunctionalProgramming language
Logo looks like it's about manipulating a triangle on the screen (or a robot on the floor) that can leave a mark behind it, with the intention of drawing pictures. However, it can also be used to do much, much
more complex things; indeed, EricRaymond
referred to Logo as a "StealthLisp
Ironically, there is a LispLanguage
dialect with turtle graphics (originally with a real robotic turtle!):
Logo also had an important influence on SmalltalkLanguage
Logo is notable as one of the very few languages that ever had both DynamicScoping
at the same time.
Over the years, more than one person has believed this combination to be impossible in the general case (see, for example, pages 12 and 13 of Lambda: The Ultimate Declarative
Is the LogoLanguage really a full-featured FunctionalProgramming language? Does it have LexicalClosures? Does it have even FirstClassFunctions? How about ExtensibleTypes??
-- Bear in mind that LispLanguage
itself generally used DynamicScope
embedded in a TiddlyWiki
Date: Wed, 08 Mar 2006 22:13:10 -0800
From: Brian Harvey
Subject: Re: ucblogo parameter binding peculiarity
The message below is being cross-posted from comp.lang.logo.
If I were writing a large production program, I'd want a lexically scoped language.
But in a language meant to encourage exploration by kids, I still think dynamic scope is the right choice. In case anyone's interested in a longer exposition, here is the relevant excerpt from the lecture notes of my SICP-based course at Berkeley:
Logo uses dynamic scope, which we discussed in Section 3.2, instead of Scheme's lexical scope. There are advantages and disadvantages to both approaches.
Summary of arguments for lexical scope:
- Allows local state variables (OOP).
- Prevents name "capture" bugs.
- Faster compiled code.
Summary of arguments for dynamic scope:
- Allows first-class expressions (WHILE).
- Easier debugging.
- Allows "semi-global" variables.
Lexical scope is required in order to make possible Scheme's approach to local state variables. That is, a procedure that has a local state variable must be defined within the scope where that variable is created, and must carry that scope around with it. That's exactly what lexical scope accomplishes.
On the other hand, (1) most lexically scoped languages (e.g., Pascal) don't have LAMBDA, and so they can't give you local state variables despite their lexical scope. And (2) lexical scope is needed for local state variables only if you want to implement the latter in the particular way that we've used. Object Logo, for example, provides OOP without relying on LAMBDA because it includes local state variables as a primitive feature.
Almost all computer scientists these days hate dynamic scope, and the reason they give is the one about name captures. That is, suppose we write procedure P that refers to a global variable V. Example:
(define (area rad)
(* pi rad rad))
This is intended as a reference to a global variable PI whose value, presumably, is 3.141592654. But suppose we invoke it from within another procedure like this:
(define (mess-up pi)
(area (+ pi 5)))
If we say (mess-up 4) we intend to find the area of a circle with radius 9. But we won't get the right area if we're using dynamic scope, because the name PI in procedure AREA suddenly refers to the local variable in MESS-UP, rather than to the intended global value.
This argument about naming bugs is particularly compelling to people who envision a programming project in which 5000 programmers work on tiny slivers of the project, so that nobody knows what anyone else is doing. In such a situation it's entirely likely that two programmers will happen to use the same name for different purposes. But note that we had to do something pretty foolish--using the name PI for something that isn't pi at all--in order to get in trouble.
It's just the letter p followed by the letter i. It could stand for anything in the mind of any number of programmers.
Lexical scope lets you write compilers that produce faster executable programs, because with lexical scope you can figure out during compilation exactly where in memory any particular variable reference will be. With dynamic scope you have to defer the name-location correspondence until the program actually runs. This is the real reason why people prefer lexical scope, despite whatever they say about high principles.
As an argument for dynamic scope, consider this Logo implementation of the WHILE control structure:
to while :condition :action
if not run :condition [stop]
while :condition :action
to example :x
while [:x > 0] [print :x make "x :x-1]
? example 3
This wouldn't work with lexical scope, because within the procedure WHILE we couldn't evaluate the argument expressions, because the variable X is not bound in any environment lexically surrounding WHILE. Dynamic scope makes the local variables of EXAMPLE available to WHILE. That in turn allows first-class expressions. (That's what Logo uses in place of first-class functions.)
There are ways to get around this limitation of lexical scope. If you wanted to write WHILE in Scheme, basically, you'd have to make it a special form that turns into something using thunks. That is, you'd have to make
(while condition action)
(while-helper (lambda () condition) (lambda () action))
But the Logo point of view is that it's easier for a beginning programmer to understand first-class expressions than to understand special forms and thunks.
Most Scheme implementations include a debugger that allows you to examine the values of variables after an error. But, because of the complexity of the scope rules, the debugging language isn't Scheme itself. Instead you have to use a special language with commands like "switch to the environment of the procedure that called this one." In Logo, when an error happens you can *pause* your program and type ordinary Logo expressions in an environment in which all the relevant variables are available. For example, here is a Logo program:
to assq :thing :list
if equalp :thing first first :list [op last first :list]
op assq :thing bf :list
to spell :card
pr (se assq bl :card :ranks "of assq last :card :suits)
to hand :cards
if emptyp :cards [stop]
spell first :cards
hand bf :cards
make "ranks [[a ace] [2 two] [3 three] [4 four] [5 five] [6 six] [7 seven]
[8 eight] [9 nine] [10 ten] [j jack] [q queen] [k king]]
make "suits [[h hearts] [s spades] [d diamonds] [c clubs]]
? hand [10h 2d 3s]
TEN OF HEARTS
TWO OF DIAMONDS
THREE OF SPADES
Suppose we introduce an error into HAND by changing the recursive call to
hand first bf :cards
The result will be an error message in ASSQ--two procedure calls down--complaining about an empty argument to FIRST. Although the error is caught in ASSQ, the real problem is in HAND. In Logo we can say PONS, which stands for "print out names," which means to show the values of *all* variables accessible at the moment of the error. This will include the variable CARDS, so we'll see that the value of that variable is a single card instead of a list of cards.
Finally, dynamic scope is useful for allowing "semi-global" variables. Take the metacircular evaluator as an example. Lots of procedures in it require ENV as an argument, but there's nothing special about the value of ENV in any one of those procedures. It's almost always just the current environment, whatever that happens to be. If Scheme had dynamic scope, ENV could be a parameter of EVAL, and it would then automatically be available to any subprocedure called, directly or indirectly, by EVAL. (This is the flip side of the name-capturing problem; in this case we *want* EVAL to capture the name ENV.)
The tragedy of Logo
Part of Logo's low esteem amongst programmers is that they simply aren't aware of its full power; they learned Logo at school, from teachers who didn't know about it (because it's too 'advanced'); most of the schoolkids who learned Logo hit the ceiling of their instructors' knowledge before they reached any limit of the language's capabilities. Ironically, this means that Logo doesn't get a chance to show its real strength, which could be described as LowFloorHighCeiling?
: a six-year-old can learn the basics of turtle control in a matter of minutes, but can continue building on those fundamentals indefinitely, and eventually use the same tools to master advanced programming concepts.
That part about instructors hitting their limits is so true... I 'borrowed' the manual and got my turtle drawing Koch snowflakes with a recursive function. The normal instruction didn't even get into functions, let alone recursion.
We'd still like to see how far a group of elementary school students could progress in Logo if taught by a knowledgeable computer scientist. That would be interesting. One perennial question in this area is WhatSortOfComputationWouldInterestJuniorSchoolChildren
I got excited a bit about Logo, partly because I was trying to interest my kids in something creative with the computer. I don't think I've managed a MindStorm?
:-(. I also found some of the language syntax inconsistent and hard to explain to kids, particularly the quoting rules and use of colons for arguments. -- AndyDent
Not the Logo specification
There is no real Logo specification.
''I worked briefly with BrianHarvey
on Berkeley Logo, and his response to "Where's the Logo spec?" was "Basically, there isn't one." However, as with its kindred in the LispLanguage
family, there is a subset of functionality which is shared between most implementations. -- JosephDale
That's right. I emailed BrianHarvey
several years ago asking this, asking if there's a spec, his reply was that they had some meetings about it (I lost the mail, I don't recall who's exactly 'they'), he said the things they all agreed on were that: (a) it has to have list processing (b) no TurtleGraphics
required. I ended up implementing a ForthLanguage
The thing that disappoints me most about Logo is that the different versions diverged considerably in language so you're fairly stuck (MSWLogo has done a fairly nice job of extensions as a current free version but I'd like to see it on the Mac) and so a lot of the interesting examples from old Apple-based Logo environments don't easily propagate. -- AndyDent
The first commercial MicroComputer
implementation of Logo was on the TexasInstruments
TI99/4. It would complain "out of ink" and refuse to draw further until the screen was cleared. The TI99/4 was using a character generator, and creating new character definitions as needed to fake bitmap graphics. With a 1000 character screen buffer and only 256 characters in the character generator. The TI99/4 used the SpriteChip?
invented by DanielHillis
for his masters thesis at MassachusettsInstituteOfTechnology
Later versions appeared for the Apple II (AppleTwo
), the Commodore 64, (CommodoreSixtyFour
) the AppleMacintosh
, and eventually the IBM PC. At its height in the 1980s, it was in use in one out of every four elementary schools in the US.
wrote a C implementation of Logo and it has been maintained and updated since. It runs on Unix with X11 (including Linux), DOS, Windows, and MacOS. It's command-line based, rather than fully GUIish. It's available from Brian's homepage at http://www.cs.berkeley.edu/~bh/
Especially of interest is a new version of Logo called StarLogo
with is a parallel version of logo for doing things like flock simulations.
Another new version of Logo with multiturtles called NetLogo
There's an implementation of Logo in MonoProject
's CVS, called, appropriately enough, MonoLogo?
. No TurtleGraphics
KTurtle is part of the official KDE Edutainment package. The interperator is based on WsBasic?
. It is built specifically for kids so it doesn't have all the advanced features, but has a very easy xml format to translate keywords into other natural languages.
doesn't have Logo (yet), but it has an activity called "Turtle Art" for playing with TurtleGraphics
using a snap-together VisualProgrammingLanguage
Python wants to be logo
Uncle Guido wants PythonLanguage
to be the new Logo. I say, only if he can make native support for TurtleGraphics
, or come up with something that's just as much fun.
-- Perhaps, as well as Turtle Graphics, some tutorials using 'TKInter' would help. Just recently, I pulled down a tutorial to explore Python, and within minutes had a series of interactive buttons built. The importing of tools to easily create a strong button/window interface gives another example of 'keep it interesting by giving the student a familiar context', a teaching rule I really respect. --Darryl Davidson
Not sure how long it's been there, but check out Python's standard 'turtle' module
. There is a Quick'n'dirty implementation in the PythonCard
There is also VeePython
, which is mainly used by physics people. It probably isn't really suitable for young children though.
I always claimed :Logo came too early
Nowadays on faster systems even interpreted it would work marvelous ! Comparable even to Unix. -- PieterJansegers
Logo and lego
These are aimed at children but appreciated by adults, but are otherwise not the same.
How about LegoLanguage?
Also, note that SeymourPapert
's seminal logo book is called MindStorms
). Lego borrowed the name for their programmable stuff, which has nice hack value.
I have tried to compile a list of the original Logo memos, now scattered among the MIT AI lab memos. Many of them are very interesting. The first four do a good job of explaining the project and the philosophy. The TORTIS papers are about a big button box that let really young children control the turtle (including the ability to store procedures and a "slot machine" which the child programmed by putting cards representing actions into slots in a board!). There are papers reporting on a test of Logo in a Brookline school with LSI-11's (microprocessor version of the PDP-11). There's even a paper breaking down the art of juggling into "procedures" and explaining how to fix common "bugs". Good stuff!
There is a LogoFoundation?
is a cool website for kids who want to learn logo : http://turtleacademy.com
See also: CategoryOldSoftware