The Logo language
A full introduction: data, variables, procedures, loops, conditionals, graphics
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)
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 :
FENCE(default) : the turtle refuses to leave and showsLA TORTUE VA SORTIR(the turtle would go out).WRAP: wrapped field, the turtle reappears on the opposite edge, like a game of snake.WINDOW: extended window, the moving space reaches well beyond what you see on screen.
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 :
42,3.14,-7 - words :
"HELLO,"RED - lists :
[ A B C ],[ 1 2 3 ],[ [ 1 2 ] [ 3 4 ] ]
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...
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
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.
: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
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
~ (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.
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).
9. Controlling the flow inside a procedure
Three instructions let you leave a procedure while it is running :
STOP: leaves the current procedure (for commands).OUTPUT value: leaves the procedure and returns a value (for operations).TOPLEVEL: full stop, back to the REPL whatever the call depth.
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
.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 FORWAD | The command FORWAD does not exist (a typo for FORWARD?) |
NOT ENOUGH INPUTS TO FD | An argument is missing for FD |
YOU DON'T SAY WHAT TO DO WITH 42 | An operation returned 42 but nobody uses it |
FD DOESN'T LIKE HELLO | The argument type is wrong |
TURTLE OUT OF BOUNDS | Move outside the field in FENCE mode |
X HAS NO VALUE | The 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.