turtle gives you a little imaginary creature that walks around
a drawing surface trailing a pen behind it. You tell it to go forward, turn
right, lift the pen, put it down — and shapes appear. It's the gentlest
way into graphics there is. Instead of thinking in pixel coordinates, you
think in the turtle's own body: "walk fifty steps, turn ninety degrees, walk
fifty more", and a square appears without your ever naming a corner. The
turtle draws into a scribbler, Shoddy's
pixel-buffer window, and carries its scribbler around with it. So a whole
drawing is just a turtle handed from one command to the next. Every command
takes a turtle and returns a new one; nothing is ever modified in place,
which fits Shoddy's grain exactly.
The turtle was born as a teaching idea. In 1967, Seymour Papert,
with Wally Feurzeig and Cynthia Solomon, created the LOGO
programming language expressly so that children could learn to program. It
began at the firm Bolt, Beranek and Newman and was carried on at the
MIT Artificial Intelligence Lab. Papert had spent years
working with the psychologist Jean Piaget, and he brought a conviction with
him: people learn best by building things and thinking about how
they built them. The turtle was his instrument for that. The first turtles
were real — small robots that trundled across the floor on command, a
pen at their centre leaving a line on paper beneath them. Children could
stand up, walk out the shape themselves, and then tell the turtle to do the
same. Papert called this "body syntonic" learning: you understand
turn right 90 because you know in your own body what turning
right feels like.
When screens replaced the floor robots, the turtle became a dot of light, but the idea stayed identical. Papert set it all down in his 1980 book Mindstorms. The book argued that a computer could be a place for children to think with, not a machine to be drilled by. You can still trace its influence directly, right down to the LEGO Mindstorms robotics kits that took their name from the book. The turtle spread into countless later languages because its core lesson never aged: a shape can be a story about movement, and that story is something a beginner can write on their very first day.
Classic LOGO's turtle is a mutable object: you send it a command
and it changes where it stands. Shoddy has no mutation, so this machine tells
the same story a little differently. The turtle is a value,
handed from each command to the next, exactly as Shoddy programs already
thread any other piece of state. And LOGO's control words —
REPEAT, TO…END, IF —
aren't reinvented here, because Shoddy already is that language.
Where LOGO writes REPEAT 4 [FD 50 RT 90], Shoddy writes a
Fold over a range. Same turtle, same spirit, expressed in the
tools already at hand.
Some pictures are far easier to describe than to plot. A
five-pointed star, a spiral, a snowflake, a tree that branches and branches:
try to work those out as lists of pixel coordinates and you'll be at it all
afternoon. Describe them as a walk ("forward, turn, forward, turn…")
and they fall out in a few lines. That's the turtle's gift: it turns geometry
into movement. It is also, famously, how a great many people met programming
for the first time. Draw a square, draw it wrong, see exactly how it's wrong,
fix it. Reach for turtle whenever a shape is more natural to
walk than to place: spirographs and stars, fractals and
plant-like forms, teaching examples, or just doodling. Under the hood it's
the scribbler doing the drawing, so anything the
turtle makes is a real pixel buffer you can show in a window or read
back.
You start by opening a turtle on a surface of a given size. It parks itself
at the centre, facing straight up, pen down, drawing white on black. From
there you drive it: Forward and Back to move,
TurnRight and TurnLeft to turn (in degrees),
PenUp and PenDown to lift or drop the pen. Every
command returns a fresh turtle, so you thread it along — and LOGO's
REPEAT becomes an honest Fold:
Include "turtle.shoddy"
Def Main()
Let t = NewTurtle(400, 400)
Let t = Title(t, "a five-pointed star")
Let t = SetPenColor(t, 255, 220, 0)
' Walk the five points of a star: forward, turn 144 degrees, five times.
Let t = Fold(Range(1, 5), t, Fn(t, _) => TurnRight(Forward(t, 200), 144))
Let t = Blit(t) ' push the drawing to the window
WaitForQuit(t)
Def WaitForQuit(t As Turtle)
Select Case NextEvent(Sc(t)) ' Sc(t) is the turtle's scribbler
Case ScribblerQuit()
Close(t)
Case Else
WaitForQuit(t)
Things worth keeping in mind:
t at
every step. Reuse an old turtle by accident and you'll be drawing from where
it used to be.TurnRight increases the heading clockwise,
TurnLeft decreases it. So Forward after
SetHeading(t, 90) heads east, 180 heads down the screen, 270 west.
Headings wrap, so turning past 360 is fine.SetTowards(t, px, py) turns the turtle to face an absolute point.
DistanceTo(t, px, py) tells you how far away it is. Together they
are handy for "walk to the mouse" or joining up known coordinates.Sc(t). Read
events from it, mix in scribbler drawing calls, or read pixels back — the
turtle is just a convenient way to steer the pen.Blit is what makes it visible in the window, and
Close shuts the window down. As with any scribbler program, the
window only exists under mill run — see the
scribbler's note on that.You don't need any of this to draw a star. It's here for the curious, and it explains a couple of choices that look odd until you know why.
The turtle is an immutable record — a bundle of
named fields that is never changed after it is made. A Turtle
bundles its scribbler, its fractional position (X, Y),
its Heading in degrees, whether the Pen is down, and
its R, G, B colour. Every command builds
a new Turtle from the old one with the relevant fields
changed. TurnRight is just "same turtle, heading plus a few
degrees." Nothing is mutated. The one thing genuinely shared and written in
place is the pixel buffer inside the scribbler: two turtles descended from the
same surface draw onto the same pixels. That is exactly what you want —
the picture is cumulative even though the turtle values are not.
Position is kept fractional on purpose. The turtle's
X and Y are real numbers. They're rounded to whole
pixels only at the last moment, when handing endpoints to the scribbler's
DrawLine. If the pose were snapped to integers after every step,
the tiny rounding errors would pile up over many small moves. A shape that
should close — a polygon walked all the way round — wouldn't
quite meet its start. Keeping the true position and rounding only for drawing
keeps the geometry honest.
The heading maths, briefly. Screens number their rows
downward, but the turtle thinks in the usual compass sense with 0 pointing up.
So a step of length d at heading h moves by
(d × sin h, −d × cos h).
The minus on the vertical is what turns "up on the compass" into "up on the
screen." SetTowards runs the same relationship backwards with an
atan2 (the function that recovers an angle from a pair of
offsets) to get a heading from a direction. The angle words lean
on Shoddy's math.shoddy machine for
Rad, Deg, Atn2, Dist, and
Wrap.
Why TurnLeft/TurnRight and
SetTowards(t, px, py)? Two small naming dodges. The
turning words aren't called Left and Right because
those are Shoddy's string built-ins (Left$/Right$),
and a Def would silently shadow them. And SetTowards
takes its target as px/py rather than
x/y because a parameter named x would
fold to X and shadow the X field accessor. If it
did, X(t) inside the word would read the parameter, not the
turtle's position. The kind of quiet care that keeps the useless useful.
Shoddy by name.
Every word, plus the Turtle type
| Word | Description |
|---|---|
| Turtle | The turtle itself, as one value: its Sc
(the scribbler it draws into), fractional X and Y,
Heading in degrees, a Pen flag (down means drawing),
and its pen colour R, G, B. Every command
below takes one and returns a new one; you thread it through your program the
way you'd thread any other value. |
| Word | Description |
|---|---|
| NewTurtle(width, height) | Opens a fresh scribbler of the given size, clears it to black, and returns a turtle parked at the centre, facing up, pen down, drawing in white. |
| Home(t) | Moves the turtle back to the centre of its surface, facing up. Pen state and colour are kept. Does not draw a line getting there. |
| Blit(t) | Pushes the pixel buffer to the window so you can see it. The drawing already happened in place, so the turtle comes back unchanged — this only shows what's there. |
| Close(t) | Closes the turtle's window. Returns the turtle
unchanged. net exports a Close too, so a
program using both must include one of them under a namespace — give the
As to net and keep this one bare, as
that page explains. |
| Title(t, s) | Sets the window's title bar to s.
Returns the turtle unchanged. |
| Word | Description |
|---|---|
| Forward(t, d) | Walks d steps in the direction the
turtle is facing, drawing a line if the pen is down. |
| Back(t, d) | Walks d steps backwards, without turning
around. (Just Forward by −d.) |
| SetXY(t, x, y) | Moves straight to the absolute point
(x, y), drawing a line there if the pen is down — a jump or a draw
depending on the pen, exactly like Forward. |
| MoveTo(t, nx, ny) | The shared core the other motion words are
built on: move to (nx, ny), drawing the segment from the current
position first if the pen is down, and keep the current heading. |
| Word | Description |
|---|---|
| TurnRight(t, deg) | Rotates deg degrees clockwise
(the heading increases). |
| TurnLeft(t, deg) | Rotates deg degrees
counter-clockwise (the heading decreases). |
| SetHeading(t, deg) | Points the turtle at an absolute heading in degrees (0 = up, clockwise positive). The value is wrapped into 0–360. |
| SetTowards(t, px, py) | Turns the turtle to face the absolute
point (px, py), wherever it currently stands. |
| DistanceTo(t, px, py) | The straight-line distance from the turtle
to the point (px, py). Doesn't move or turn it. |
| Word | Description |
|---|---|
| PenDown(t) | Lowers the pen, so subsequent moves draw lines. |
| PenUp(t) | Lifts the pen, so subsequent moves reposition the turtle without leaving a mark. |
| SetPenColor(t, r, g, b) | Sets the pen colour to
r,g,b (each 0–255) for everything drawn from here
on. |
No machine and no mill includes it yet — its words are already at
the reckoner's prompt through its seed, and
tst/turtle-demo.shoddy is the working showcase for a
program.
| Machine | Why | |
|---|---|---|
| math | Rad,
Deg and Dist — headings in degrees, geometry in
radians. | |
| scribbler | DrawLine
— every segment the pen leaves behind. |