1. The turtle and the graphics field

In the middle of the graphics screen there is a little arrow : the turtle. It has a position (a point on the screen), a heading (the direction it points in) and a pen it can lower to draw or raise to move without leaving a trail.

The graphics field is a space 1600 steps wide by 1000 steps high. The origin, the point [0, 0], is at the centre. The x axis runs from −800 to +800 (left to right), the y axis from −500 to +500 (bottom to top). The turtle always starts at the centre, pointing upward (heading 0).

Moving the turtle

FD 100      ; forward 100 steps
BK 50       ; back 50 steps
RT 90       ; turn right by 90 degrees
LT 45       ; turn left by 45 degrees

The heading follows the compass convention : 0 = north (up), 90 = east (right), 180 = south (down), 270 = west (left). RT adds degrees clockwise, LT counter-clockwise.

To place the turtle directly at a point :

SETPOS [ 100 50 ]   ; go to point (100, 50), keeping the heading
SETHEADING 180     ; set heading to 180 (downward)
HOME             ; turtle back to centre, heading 0

The pen

By default, the pen is down : the turtle draws as it moves. You raise or lower it with :

PU          ; Pen Up
PD          ; Pen Down
PRINT PENDOWN?   ; TRUE if the pen is down

The line colour is changed with SETPC (SETPENCOLOR), giving a code from 0 to 15, or a red-green-blue triple :

SETPC 6              ; cyan (default colour)
SETPC 1              ; red
SETPC [ 255 128 0 ]   ; orange (free RGB colour)
0 black
1 red
2 green
3 yellow
4 blue
5 magenta
6 cyan
7 white
8 gray
9 light red
10 light green
11 light yellow
12 light blue
13 light magenta
14 light cyan
15 orange

Background and border

SETBG 4              ; blue background (default)
SETBORDER 0          ; black border
CS                   ; clears the screen and resets everything
CLEAN                ; erases the drawing without moving the turtle

Field modes

What happens when the turtle reaches the edge of the field? It depends on the chosen mode :

WRAP
REPEAT 200 [ FD 10 RT 7 ]   ; a spiral that wraps

Multiple turtles

By default there is a single turtle, numbered 0. You can keep several alive on the same screen : SETTURTLE n selects the active turtle (created if needed), and all the usual commands (FD, RT, SETPC…) then act on it. Each turtle keeps its own position, heading and pen ; the background, scale and field mode, however, are shared by the whole screen. Numbers range from 0 to 1023 (up to 1024 turtles).

SETTURTLE 1          ; creates and selects a 2nd turtle
SETPC 1 RT 90 FD 100  ; it draws in red, to the right
SETTURTLE 0          ; back to the 1st turtle (unchanged)

ASK n [ … ] runs a block on turtle n (or on each turtle of a list of numbers) then returns to the previously active turtle. TURTLE outputs the current number, TURTLES the number of turtles, and CLEARTURTLES keeps only one (#0).

SPRITE and SETPC act on the active turtle too : each turtle can therefore have its own shape and its own pen colour.

SETTURTLE 2                ; now we have turtles 0, 1 and 2
ASK 1 [ RT 120 ]            ; each one faces a different way
ASK 2 [ RT 240 ]
ASK [ 0 1 2 ] [ FD 80 ]    ; the three fan out from the centre, then back to #2

COLLIDE? [ a b ] outputs TRUE if turtles a and b exist, are visible and overlap: handy for a small game (hitting a target, avoiding an obstacle…).

Drawing your own shape: DEFSPRITE

In the spirit of BASIC's DEFGR$, DEFSPRITE defines a 16×16 pixel shape "in ASCII": a list of up to 16 rows of 16 characters, where . = empty pixel and any other character (an X for instance) = filled pixel. The shape gets a number from 3 to 255 (0, 1, 2 are the built-in shapes), then SPRITE selects it. It is drawn in the pen colour and rotates with the heading. Shapes survive CLEARSCREEN (but not RESET).

DEFSPRITE 3 [
  ......XXXX......
  ....XXXXXXXX....
  ...XX.XXXX.XX...
  ...XXXXXXXXXX...
  ...XX.XXXX.XX...
  ....XX.XX.XX....
  ......XXXX......
]
SPRITE 3                  ; the active turtle takes this shape

Animating turtles: ANIME

ANIME id x y speed mode (EN ANIMATE) moves a turtle automatically toward a point, in parallel with the program. speed is the number of Logo steps travelled per frame; CADENCE (EN SETFPS) sets the frames per second (default 30). Because speed is per frame, the ratio between two speeds stays the same whatever the frame rate.

The mode is a word: "ONCE (go to the target then stop), "LOOP (jump back to the start and repeat, handy for scrolling) or "PINGPONG (continuous back and forth). If the pen is down the turtle leaves a trail; raise it (PU) for a clean move. A manual command (FD, SETXY…) on the turtle stops its animation, as do STOPANIMATE and Ctrl+C.

SETFPS 60
ANIMATE 1 300 150 2 "PINGPONG   ; turtle 1 makes slow round trips
ANIMATE 2 -300 150 8 "LOOP      ; turtle 2 goes 4 times faster
WAIT 180                     ; 3 s: both move (the program waits, the animation does not)
STOPANIMATE 1                    ; stops turtle 1 ; turtle 2 keeps going. (STOPANIMATE) stops them all

The wait is essential here: without it the four lines run in an instant and STOPANIMATE 1 stops turtle 1 before you can see it move. During WAIT the program pauses, but the animations keep running.

Combined with COLLIDE?, this is enough for a small game: a target moves on its own while the loop reads the joystick to move the player, until they touch. Here is a complete game, playable with the arrow keys: bring the player (at the bottom) onto the target sweeping across the top.

CLEARSCREEN
PU SETXY 0 -200              ; the player (turtle 0) starts at the bottom
ASK 1 [ PU SETXY -600 150 ]       ; the target (turtle 1) starts on the left
ANIMATE 1 600 150 4 "PINGPONG   ; it sweeps the top back and forth
WHILE [ NOT COLLIDE? [ 0 1 ] ] [
  MAKE "D JOYSTICK 0
  IF :D = 1 [ SETH 0   FD 20 ]      ; up
  IF :D = 5 [ SETH 180 FD 20 ]      ; down
  IF :D = 3 [ SETH 90  FD 20 ]      ; right
  IF :D = 7 [ SETH 270 FD 20 ]      ; left
  WAIT 1
]
STOPANIMATE 1
PRINT [ CAUGHT! ]

The target moves on its own (animation engine) while the loop reads the joystick and moves the player; as soon as they touch, COLLIDE? becomes true and the loop ends. Ctrl+C interrupts the game (and the animations).

SCENE: flicker-free animation

The ANIMATE engine moves sprites without erasing anything. But many games and animations redraw the whole scene themselves on every frame: CLEAN, then redraw the background and the turtles inside a loop. The screen may then be shown in the middle of the redraw (right after CLEAN, an empty field, or half drawn) — that is what causes the flicker.

SCENE [ … ] fixes it. Everything drawn inside the block is built in a hidden buffer, and the screen only switches to the new image once the block is finished (double buffering). Wrap the drawing of one frame in SCENE and keep WAIT outside it:

WHILE [ NOT KEY? ] [
  SCENE [
    CLEAN
    ; … redraw the whole background and the turtles …
  ]
  WAIT 2              ; the wait stays outside the block
]

2. Data

In Logo, everything is an object. There are three kinds of object :

Numbers

Numbers can be whole or decimal (the separator is the dot). The four arithmetic operations are written naturally, with spaces around the operators :

PRINT 3 + 4          ; prints 7
PRINT 10 - 3         ; prints 7
PRINT 6 * 7          ; prints 42
PRINT 100 / 4        ; prints 25
PRINT 360 / 8        ; prints 45

You can also write the long forms : SUM 3 4, DIFFERENCE 10 3, PRODUCT 6 7, QUOTIENT 100 4.

Useful mathematical functions :

PRINT SQRT 16        ; square root -> 4
PRINT INT 3.7        ; integer part -> 3
PRINT ROUND 3.6      ; nearest integer -> 4
PRINT ABS -5          ; absolute value -> 5
PRINT RANDOM 6       ; random integer between 0 and 5
PRINT SIN 30         ; sine of 30 degrees -> 0.5
PRINT COS 60         ; cosine of 60 degrees -> 0.5
PRINT PI             ; the constant pi -> 3.14159...
Precedence: a function « swallows » the expression that follows it. A prefix function (such as COUNT, INT, ABS, SQRT...) takes as its argument the whole expression to its right, operators included. So COUNT :WORD - 1 is read as COUNT ( :WORD - 1 ), not ( COUNT :WORD ) - 1. To subtract 1 from the function's result, add parentheses: ( COUNT :WORD ) - 1. When in doubt, parenthesise the call.

Words

A word is a string of characters. To write a literal word, you put a quote " in front of it :

PRINT "HELLO
PRINT "RED
PRINT WORD "HEL "LO    ; joins them -> HELLO

To query a word :

PRINT COUNT "HELLO       ; number of characters -> 5
PRINT FIRST "HELLO       ; first character -> H
PRINT LAST "HELLO        ; last -> O
PRINT ITEM 3 "HELLO     ; 3rd character -> L
PRINT BF "HELLO          ; butfirst -> ELLO

Lists

A list is a group of objects in brackets. The objects can be numbers, words, or other lists :

[ 1 2 3 ]
[ RED GREEN BLUE ]
[ 100 0 ]              ; coordinates
[ [ 1 2 ] [ 3 4 ] ]   ; list of lists

To work with lists :

PRINT COUNT [ A B C ]          ; -> 3
PRINT FIRST [ A B C ]          ; -> A
PRINT LAST [ A B C ]           ; -> C
PRINT BF [ A B C ]             ; butfirst -> [B C]
PRINT ITEM 2 [ A B C ]        ; -> B
PRINT FPUT "X [ A B ]          ; adds at front -> [X A B]
PRINT LPUT "Z [ A B ]          ; adds at end -> [A B Z]
PRINT SE [ A B ] [ C D ]        ; sentence (flattens) -> [A B C D]
PRINT LIST "A "B              ; builds [A B]
PRINT REVERSE [ A B C ]        ; -> [C B A]
PRINT SORT [ 3 1 2 ]           ; -> [1 2 3]

Arrays

Beyond the three basic types, GoLogo also offers arrays. A list is flexible, but to reach its hundredth element you have to walk past the ninety-nine before it. An array gives direct access to any cell by its number, and you can change a cell in place. It is the right tool as soon as you juggle many values pinned to a position : a score table, a game board, a grid.

ARRAY n builds an array of n cells, numbered from 1 (each cell starts out as the empty list). You read a cell with ITEM, change it with SETITEM, and COUNT gives the number of cells :

MAKE "SCORES ARRAY 3
SETITEM 1 :SCORES 50       ; store 50 in cell 1
SETITEM 2 :SCORES 80
PRINT ITEM 2 :SCORES       ; -> 80
PRINT COUNT :SCORES         ; -> 3

You can also write an array directly between braces. By default the first cell is numbered 1 ; to start at 0 (often handier when you compute indices), add @0 right after the closing brace :

MAKE "DAYS { MON TUE WED THU FRI }
PRINT ITEM 3 :DAYS          ; -> WED
MAKE "T { A B C }@0            ; cells numbered 0, 1, 2
PRINT ITEM 0 :T             ; -> A
An array is shared, a list is copied. Unlike lists, an array is passed by reference. If you write MAKE "U :SCORES, then :U and :SCORES point to the same array, and a SETITEM on one shows up on the other. This is on purpose (it avoids copying a big array each time it is passed to a procedure), but it catches you out the first time. To get a truly independent copy, use COPYARRAY.

A few handy companions : ARRAY? :X tells whether :X is an array, SORTARRAY :T sorts its cells in place, and the two bridges LISTTOARRAY and ARRAYTOLIST move from one to the other. The latter is useful to process an array with FOREACH or MAP, which work on lists.

For a two-dimensional grid (a checkerboard, a maze, a screen of dots), MDARRAY builds a multi-dimensional array, and MDITEM / MDSETITEM reach a cell through a list of indices :

MAKE "GRID MDARRAY [ 3 3 ]       ; 3 by 3
MDSETITEM [ 2 2 ] :GRID "X        ; the middle cell
PRINT MDITEM [ 2 2 ] :GRID        ; -> X

Stacks and queues

Two small but handy tools work on a variable that holds a list (the empty list [ ] to start with). A stack pushes and pops at the same end, so the last in is the first out ; a queue adds at one end and removes at the other, so first in, first out.

MAKE "P [ ]
PUSH "P 1   PUSH "P 2   PUSH "P 3
PRINT POP "P         ; -> 3  (the last pushed)
PRINT POP "P         ; -> 2

MAKE "F [ ]
QUEUE "F "A   QUEUE "F "B
PRINT DEQUEUE "F     ; -> A  (the first in)

Printing objects

PRINT "HELLO            ; prints HELLO then a new line
TYPE "HELLO             ; prints HELLO with no new line
SHOW [ A B C ]          ; keeps the brackets -> [A B C]

3. Variables

A variable is a name that stands for an object. You create one with MAKE :

MAKE "AGE 17
MAKE "NAME "TINTIN
MAKE "COLORS [ RED GREEN BLUE ]

To read a variable's value, you put a colon in front of its name :

PRINT :AGE       ; -> 17
PRINT :NAME      ; -> TINTIN
FD :AGE          ; forward 17 steps

The notation :AGE is short for THING "AGE. You can change a variable's value simply by giving it again :

MAKE "COUNTER 0
MAKE "COUNTER :COUNTER + 1   ; add 1

4. Procedures

The great idea of Logo is that you can teach GoLogo new words. A procedure is exactly that : a command you invent yourself.

Defining a simple procedure

You define a procedure with TO followed by its name, and end it with END :

TO SQUARE
  REPEAT 4 [ FD 80 RT 90 ]
END

GoLogo replies SQUARE DEFINED and, from that moment, SQUARE is a command in its own right :

SQUARE
RT 30
SQUARE

Procedures with parameters

A parameter lets you pass a value to the procedure when you call it. You declare it with a colon on the TO line :

TO POLYGON :N :SIDE
  REPEAT :N [ FD :SIDE RT 360 / :N ]
END

You call this procedure by passing its two arguments :

POLYGON 3 100    ; triangle
POLYGON 4 80     ; square
POLYGON 6 60     ; hexagon
POLYGON 12 30    ; dodecagon (looks like a circle)

Procedures that return a value (operations)

A procedure can also compute and return a result with OUTPUT. It then becomes an operation, usable anywhere GoLogo expects a value :

TO DOUBLE :N
  OUTPUT :N * 2
END

PRINT DOUBLE 5       ; -> 10
FD DOUBLE 30          ; forward 60 steps

5. Variable scope : local or global ?

Here is a point that often surprises beginners, and yet it is at the heart of how Logo works. By default, a variable created with MAKE is global : it exists everywhere, including inside other procedures. That is handy, but it hides a trap.

The trap : one procedure can overwrite another's variable

Imagine two procedures that each use a variable named RES :

TO TRIPLE :X
  MAKE "RES :X * 3
  OUTPUT :RES
END

TO COMPUTE
  MAKE "RES 100
  PRINT TRIPLE 5    ; -> 15
  PRINT :RES         ; -> 15  (not 100 !)
END

We expected :RES to still be 100 at the end of COMPUTE. But since TRIPLE did MAKE "RES on the same global variable, it replaced COMPUTE's 100 with 15. The called procedure quietly damaged a variable of the calling one.

The fix : LOCAL

LOCAL "RES tells GoLogo : « inside this procedure, RES is mine, I won't touch anyone else's ». One line changes everything :

TO TRIPLE :X
  LOCAL "RES           ; RES becomes private to TRIPLE
  MAKE "RES :X * 3
  OUTPUT :RES
END

TO COMPUTE
  MAKE "RES 100
  PRINT TRIPLE 5    ; -> 15
  PRINT :RES         ; -> 100  (preserved !)
END

Now each RES lives in its own procedure : TRIPLE's one disappears as soon as it is done, COMPUTE's one stays intact.

The same trap in a loop

It is even sneakier when the caller uses a loop variable such as I and a called procedure overwrites that same I :

TO DISP :X
  MAKE "I :X * 10      ; oops: I is also the caller's loop variable
  PRINT :I
END

TO LOOP
  FOR [ I 1 3 ] [ DISP :I   PRINT :I ]
END

LOOP     ; prints 10 10 20 20 30 30 (the second number should be 1 2 3 !)

Adding LOCAL "I inside DISP brings the loop back to its senses : 10 1 20 2 30 3. Simple rule : any working variable (counter, total, intermediate result) created inside a procedure deserves a LOCAL.

Good news : parameters are already local. A procedure's parameters (the :N in TO DOUBLE :N) are automatically private : changing them never touches a global variable of the same name. LOCAL is only needed for variables you create with MAKE inside the procedure.

A well-written example

A tidy procedure declares its working variables as local right from the start :

TO APPROX_CIRCLE :R
  LOCAL "STEP
  MAKE "STEP 2 * PI * :R / 360
  REPEAT 360 [ FD :STEP RT 1 ]
END
Why this behaviour ? This « dynamic » scope (global by default, LOCAL to reserve a name) is the one of the original Logo, and GoLogo stays faithful to it. The LOCAL habit is part of the language's basics.

6. Loops

REPEAT

REPEAT n [ instructions ] runs the instructions n times. It is the simplest and most-used loop :

REPEAT 4 [ FD 80 RT 90 ]          ; square
REPEAT 360 [ FD 1 RT 1 ]          ; circle
REPEAT 12 [ SQUARE RT 30 ]         ; rosette

Inside a REPEAT loop, REPCOUNT returns the number of the current iteration (1, 2, 3…) :

REPEAT 5 [ FD REPCOUNT * 20 RT 90 ]   ; square spiral
Lines too long? A ~ (tilde) at the end of a line means the instruction continues on the next line, handy for laying out a loop with nested lists. So REPEAT 6 ~ followed by the list [ … ] on the next lines is the same as writing it all on one line. (The ! character does the same, inherited from the MO5 Logo.)

FOR

FOR is a counting loop : a variable takes the values from start to end, by a step :

FOR [ I 1 10 ] [ PRINT :I ]           ; from 1 to 10
FOR [ I 0 100 10 ] [ FD :I RT 90 ]   ; spiral by steps of 10

WHILE

WHILE keeps going as long as its condition is true.

MAKE "N 1
WHILE [ :N < 100 ] [
  FD :N
  RT 91
  MAKE "N :N + 1
]

FOREACH

FOREACH walks through each item of a list. The current item is available under the name :? :

FOREACH [ 1 2 3 4 5 ] [ FD :? * 10 RT 90 ]

FOREACH [ RED GREEN BLUE ] [
  PRINT :?
]

7. Conditionals

IF

IF runs instructions depending on whether a condition is true or false :

IF :N > 0 [ PRINT "POSITIVE ]
IF :N > 0 [ PRINT "POSITIVE ] [ PRINT "NEGATIVE_OR_ZERO ]

The two-list form is an if/else. The alias IFELSE says the same thing more explicitly.

Predicates

A predicate is an operation that returns TRUE or FALSE. All Logo predicates end with ? :

PRINT EQUAL? 3 3            ; -> TRUE
PRINT LESS? 2 5             ; 2 < 5 -> TRUE
PRINT GREATER? 8 3          ; 8 > 3 -> TRUE
PRINT EMPTY? [ ]             ; empty list ? -> TRUE
PRINT NUMBER? "HELLO        ; is it a number ? -> FALSE
PRINT MEMBER? "B [ A B C ]   ; B in the list ? -> TRUE

The operators AND, OR and NOT combine predicates :

IF AND LESS? 0 :N GREATER? 100 :N [ PRINT "BETWEEN_0_AND_100 ]
IF NOT EMPTY? :LIST [ PRINT FIRST :LIST ]

Comparisons and letter case

Word comparisons ignore letter case: EQUAL? "a "A returns TRUE. The same holds for =, BEFORE?, SUBSTRING? and MEMBER?. This is usually convenient, but a problem when case carries meaning, for instance to tell an a cell apart from an A cell in a grid.

When case matters: compare the character codes with ASCII rather than the characters themselves. EQUAL? ASCII :C1 ASCII :C2 is true only for two strictly identical characters (ASCII "a is 97, ASCII "A is 65).

8. Recursion

In Logo, a procedure can call itself. This is called recursion. It is the ideal tool for structures that repeat at different scales.

The simplest example is a countdown :

TO COUNTDOWN :N
  IF :N = 0 [ PRINT "LIFTOFF STOP ]
  PRINT :N
  COUNTDOWN :N - 1
END

COUNTDOWN 5

Recursion is also the natural way to walk through a list :

TO PRINT_ALL :LIST
  IF EMPTY? :LIST [ STOP ]
  PRINT FIRST :LIST
  PRINT_ALL BF :LIST
END

And for fractal drawings it is irreplaceable (see the Example programs page).

Recursion made easy. A procedure can call itself a great many times without slowing down or freezing GoLogo. And if a recursive loop runs forever, you can stop it at any time with Ctrl+C.

9. Controlling the flow inside a procedure

Three instructions let you leave a procedure while it is running :

TO FORWARD_IF_OK :N
  IF :N < 0 [ STOP ]        ; do nothing if N is negative
  FD :N
END

TO SIGN :N
  IF :N > 0 [ OUTPUT 1 ]
  IF :N < 0 [ OUTPUT -1 ]
  OUTPUT 0
END

10. Advanced graphics

Circle and arc

CIRCLE 50              ; circle of radius 50, centred on the turtle
ARC 60 0 90           ; arc of radius 60, from 0 to 90 degrees (a quarter)
ARC 40 45 315         ; arc from 45 to 315 degrees (three quarters)

The turtle does not move : it stays at the centre of the circle or arc.

Filling

REPEAT 4 [ FD 80 RT 90 ]   ; first draw the shape
FILL                          ; then fill the area that contains the turtle

To choose a fill colour different from the pen colour :

SETPC 7     ; white pen for the outline
SETFC 1     ; red fill
REPEAT 4 [ FD 80 RT 90 ]
FILL

Line thickness

SETPENSIZE 5
REPEAT 4 [ FD 100 RT 90 ]   ; square with a thick line
SETPENSIZE 2                  ; back to normal thickness

Writing in the graphics field

SETPC 3
LABEL "HELLO               ; writes at the turtle's position

Saving the drawing

SAVEPNG "MY_DRAWING         ; saves as MY_DRAWING.PNG

11. Text area and printing

Outside the graphics field, GoLogo has a text area with a grid of 40 columns by 25 lines. That is where the PRINT and TYPE commands write.

SETTEXTLINES 5     ; show 5 text lines below the graphics field
SETTEXTLINES 25    ; full text (hides the graphics field)
CLEARTEXT          ; clears the text area
SETCURSOR [ 10 5 ] ; places the text cursor at column 10, line 5
SETTEXTCOLOR 3      ; text in yellow

12. Reading the keyboard and the mouse

Keyboard

MAKE "C READCHAR        ; waits for a character, stores it in C
MAKE "L READLIST        ; waits for a full line -> list of words
IF KEY? [ PRINT READCHAR ]   ; if a key is available, read it

To ask the user a question :

READ [ WHAT IS YOUR NAME ] "NAME
( PRINT "HELLO :NAME )

Mouse

PRINT MOUSEPOS           ; [x y] if the pointer is in the field
IF MOUSEDOWN? [ PRINT "CLICK ]

13. Music

GoLogo can play notes. Notes are written with their solfège names :

PLAY "DO
PLAY [ DO RE MI FA SOL LA SI ]
PLAY [ DO RE# MI SOL LA ]   ; with a sharp

You set the octave, duration, tempo and timbre :

OCTAVE 5         ; high octave (1 to 5, default 4)
DURATION 12      ; shorter notes (1 to 96, default 24)
TEMPO 10         ; faster (1 to 255, default 5)
TIMBRE 192       ; sine sound (0=square, 64=sawtooth, 128=triangle, 192=sine)
PLAY [ DO MI SOL DO ]

14. Files

Logo files (.GLG) are stored in the ~/Logo/ folder on Linux/macOS, or in Documents\Logo\ on Windows. There is no need to give the full path.

SAVE "PROJECT CONTENTS   ; saves everything to PROJECT.GLG
LOAD "PROJECT            ; loads and runs PROJECT.GLG
EDLOAD "PROJECT          ; loads into the editor without running
CATALOG                   ; lists the available files
ERASEFILE "PROJECT       ; deletes the file

The examples shipped with GoLogo

GoLogo comes with an examples directory of ready-to-load programs. Three commands, ending in EX, work exactly like their counterparts but look in that directory (read-only) :

CATALOGEX                 ; lists the available examples (like CATALOG)
LOADEX "MANDELBROT        ; loads and runs an example (like LOAD)
EDLOADEX "MANDELBROT      ; opens an example in the editor (like EDLOAD)

The location of the examples directory depends on the system (it is installed with GoLogo). If the directory or the requested file cannot be found, the command says so.

Reading and writing data files

Everything above is about program files. But you often need to read or write your own data : a list of scores, some text, numbers to process. GoLogo then works with streams, the FMSLogo way. The idea is simple : you open a file, make it the current stream, and the usual reading commands (READCHAR, READWORD, READLIST, and above all READRAWLINE) read from it instead of the keyboard. Writing works the same way : once a file is the current write stream, PRINT, TYPE and SHOW write into it rather than to the screen.

To go through a text file line by line, the usual pattern is a WHILE loop that stops at the end of the file, detected by EOF? :

OPENREAD "DATA.TXT            ; open the file for reading
SETREAD "DATA.TXT             ; it becomes the current read stream
WHILE [ NOT EOF? ] [
  MAKE "LINE READRAWLINE      ; read one whole line, as is
  PRINT :LINE                ; ... and do whatever with it ...
]
CLOSE "DATA.TXT               ; close it once done

Writing follows the same spirit : open for writing, which creates the file or overwrites the old one (or OPENAPPEND to add to the end), aim writing at that stream, then come back to the screen by passing the empty list to SETWRITE :

OPENWRITE "NOTES.TXT
SETWRITE "NOTES.TXT
PRINT [ 12 15 9 ]            ; this line goes into the file
SETWRITE [ ]                     ; back to normal output
CLOSE "NOTES.TXT

When you simply want to swallow a whole text file at once, FILETOARRAY reads it in one go and returns an array whose every cell is a line (the first line in cell 1). It is the natural companion of the arrays seen above : COUNT gives the number of lines, and you reach any of them by its number.

MAKE "LINES FILETOARRAY "DATA.TXT
PRINT COUNT :LINES          ; how many lines?
PRINT ITEM 1 :LINES          ; the first line
Where do these files live ? Like .GLG files, data files stay in the working directory (~/Logo/ or Documents\Logo\) : you give a name, not a full path, and you cannot step outside that directory. Line endings are written Unix-style (LF) by default ; SETEOL "CRLF switches to the Windows format if the file is meant to be read elsewhere.

15. Workspace

GoLogo keeps in memory all the procedures and variables defined during the session. You can inspect and manage them :

POALL              ; prints all the procedures and variables
POTS               ; prints only the procedure titles
PO "SQUARE          ; prints the definition of SQUARE
ERASE "SQUARE        ; erases the procedure SQUARE
ERNAME "AGE          ; erases the variable AGE
ERALL              ; erases everything (procedures and variables)
RESET              ; resets everything (asks for confirmation)

16. Common error messages

When GoLogo does not understand what you ask, it replies with a clear error message. The messages keep their original French wording ; switch to English with the ENGLISH command to read them translated.

Message (English mode)Cause
I DON'T KNOW HOW TO FORWADThe command FORWAD does not exist (a typo for FORWARD?)
NOT ENOUGH INPUTS TO FDAn argument is missing for FD
YOU DON'T SAY WHAT TO DO WITH 42An operation returned 42 but nobody uses it
FD DOESN'T LIKE HELLOThe argument type is wrong
TURTLE OUT OF BOUNDSMove outside the field in FENCE mode
X HAS NO VALUEThe variable X does not exist
STOPPED!You pressed Ctrl+C

On an error, GoLogo also names the procedure at fault : FD DOESN'T LIKE HELLO IN SQUARE. This helps you locate the problem.