Program Flow
Control the program flow.
This section describes various commands to control the program flow. The IF command implements branching, and various loop commands implement looping. CATCH and THROW implement a mechanism to pass control across procedure boundaries.
APPLY
Applies a parameter list to a procedure.
Syntax
APPLY procedure list
Description
APPLY runs the procedure or primitive given as its first input with the arguments supplied as the second input. The output of APPLY is the output of the operation.
Example
APPLY “FPUT [“HELLO [BILL]] Result: [HELLO BILL]
CATCH
Catches runtime errors and THROWn data.
Syntax
CATCH word instructions
CATCH TRUE instructions
CATCH "ERROR instructions
Description
CATCH runs the instructions in its second input. If Logo executes a THROW command during the execution of the commands, Logo returns control to the command following the CATCH command if the input to THROW matches the word supplied as the first input. If the thrown word does not match, Logo searches for another CATCH command further up in the list of called procedures until a match is found, and returns control to the command following that CATCH command. The CATCH command is used to program procedure exits that span multiple nested procedure calls. If a thrown word is not caught, Logo treats it as a runtime error. The instruction list can contain another CATCH command. This way, multiple CATCH commands can be nested to catch different conditions.
There are a few special uses of CATCH. If the first input to CATCH is TRUE, any error that a procedure throws will be caught. Also, CATCH “ERROR catches an error that would otherwise print a Logo message and return to toplevel. CATCH “TOPLEVEL catches any attempt of the program to return to toplevel.
After catching an error or a thrown word, the built-in variable :ERROR contains a word that describes the caught error. The built-in variable :ERRORTEXT contains the error message that Logo would have printed.
Example
TO NAMEIT ; catch the NAMEIT1 value thrown inside NAMEIT1 CATCH “NOTNAME [NAMEIT1] END TO NAMEIT1 PRINT [PLEASE ENTER A NAME] LOCAL”NAME MAKE “NAME READ ; throw the value NOTNAME in case of the input being a list IF NOT WORD? :NAME THEN THROW “NOTNAME PRINT SE :NAME [IS A GOOD NAME] END
NAMEIT </span>
COPYDEF
Copies a procedure definition.
Syntax
COPYDEF newname currentname
Description
COPYDEF copies the definition of its second input to its first input. The second input to COPYDEF must be a name of either a procedure or a primitive. Primitives cannot be redefined. Note that when you use COPYDEF with a command, its abbreviation is NOT affected.
DEFINE
Defines a procedure.
Syntax
DEFINE name instructionlist
Description
DEFINE creates a new procedure with the name of its first input. The second input to DEFINE determines the definition of the procedure. Any variables for the title line must be in a list that is the first element of the list of instructions, with no dots (:) before their names. If there are no variables, the first element must be the empty list. Each remaining element in the list of instructions is a list that consists of one line of the procedure definition. The list of instructions is written in the same form as the output of TEXT. END must not be included in the list of instructions, as it is not part of the definition.
Example
DEFINE “SQUARE [[DIST] [REPEAT 4 [FD :DIST RT 90]]] SQUARE 100
ELSE
Starts the ELSE branch of an IF command.
Syntax
IF expression THEN instructions ELSE instructions
Description
ELSE starts the branch of an IF command that is executed if the condition is false. ELSE is a special word like THEN or END and not a procedure by itself.
END
Ends a procedure definition.
Syntax
END
Description
END ends the definition of a Logo procedure. It checks for any open brackets and reports an error if there are lists which are not closed correctly. END is used in Logo source files only. Do not use END when defining a procedure with the DEFINE command. END is a special word like THEN or ELSE and not a procedure by itself.
EVAL
Runs a list and collects all outputs.
Syntax
EVAL list
Description
EVAL runs its input as if it were typed in directly. EVAL does not throw an error when the execution of the list yields a result; instead, all results are concatenated into a list and output by the procedure. See also RUN.
Example
; PRINT “Hello does not output anything EVAL [1 2 PRINT “Hello “Three] Result: [1 2 THREE]
FOR
Runs a list for a defined number of times.
Syntax
FOR variable-name start-value end-value [runlist]
(FOR variable-name start-value end-value [runlist] increment-value)
Description
FOR allows you to execute a list of Logo commands a given number of times. Inputs to FOR are a control variable, a beginning value, an ending value, and a list of Logo commands to be executed. FOR assigns the beginning value to the variable, executes the instruction list, and then increments the variable by one. This process is repeated until the value of the variable is beyond the ending value. The variable increment step can be changed to a number other than one.
FOR expects the name of the variable, the beginning value, and the ending value as three separate input. If a different increment than 1 is desired, that value is an optional fifth input.
The loop variable is created at toplevel if it is not found. Logo sets the loop variable to the next value at the end of each iteration.
If a procedure alters the value during an iteration, the value is overwritten. It is, for example, not possible to terminate a loop by setting the loop variable to the end value.
Example
FOR “I 1 4 [PRINT :I] 1 2 3 4
FOREACH
Runs a list for each element of its first input.
Syntax
FOREACH word-or-list runlist
Description
The FOREACH command runs a list of commands repeatedly. FOREACH sets an internal pointer to the first element of the list given as its first input. On each run, it substitutes all occurrences of a single question mark ? in the runlist with the list element that the internal pointer points to, runs the runlist, and advances the internal pointer to the next list element. If the runlist reports a value, FOREACH stops and reports that value. If the question mark is quoted as in ”?, the list element is quoted as well; the same applies if the question mark has a leading colon as in :?. If the first input is a word, FOREACH runs the list for each character of the word.
If the first input is a word, FOREACH runs the list for each of the word’s characters.
FOREACH substitutes question marks inside sub-lists. Therefore, nested FOREACH loops are not impossible. If you need nested FOREACH loops, you need to create a separate procdure for the inner FOREACH loop and call that procedure from the outer FOREACH loop.
Note that FOREACH is different from the FOREACH command of Berkeley Logo. The Berkeley Logo FOREACH command knows the ?REST symbol as well as the # symbol; Logo does not recognize these symbols. Also, Berkeley Logo does not transfer a quote or a colon from the question mark to the replaced symbol like Logo does.
Example
A quoted question mark:
FOREACH [JOHN MARTHA] [PRINT “?] JOHN MARTHA
FOREVER
Runs a list forever.
Syntax
FOREVER runlist
Description
FOREVER runs a list forever until a command like STOP or OUTPUT exits the loop, or until the program is stopped. FOREVER acts like the REPEAT command, with an incredibly high repeat count.
GO
Jumps to a label inside a procedure.
Syntax
GO name
Description
GO transfers the flow within a procedure to the command immediately following its corresponding LABEL command. GO and its corresponding LABEL must reside within the same procedure, and they must reside within the same runlist. A GO from the body of a procedure to, for example, the runlist of an IF command is not possible.
Example
The procedure PINWHEEL runs forever; click the Stop button to stop the procedure.
TO PINWHEEL FD 100 LABEL “LOOP REPEAT 4 [FD 50 RT 90] RT 20 GO “LOOP END
PINWHEEL </span>
IF
Runs instructions based on a condition.
Syntax
IF expression [then-instructions]
IF expression [then-instructions] [else-instructions]
IF expression then-instructions
IF expression THEN instructions
IF expression THEN instructions ELSE instructions
Description
IF checks its first input for being TRUE or FALSE. If the value is TRUE, it runs or outputs its second input, and if the value if FALSE, it runs or outputs its third input. If the second or third inputs are lists, IF treats these inputs as instruction lists, and runs the input.
There are several ways to specify the inputs to IF. If other commands just follow the IF command, all commands are executed only if the condition is true. Optionally, the list of commands may be preceded by the THEN keyword. If the list of commands contains the keyword ELSE, the executions of commands stop at that keyword if the condition is true, and the remainder of the line is skipped. If the condition is false, all commands up to and including the ELSE keyword is skipped, and execution continues at the command behind ELSE. If the command following the condition is a list, the list is considered to be a runlist, and Logo executes that list if the condition is true, and continues execution at the command behind the list. If that command also is a list, however, that list is considered to be a runlist that is executed if the condition is false.
Example
IF (FIRST TIME) > 18 THEN “NIGHT ELSE “DAY Result: NIGHT
IFFALSE
Also: IFF
Runs a list if TEST was false.
Syntax
IFFALSE instruction-list
Description
IFFALSE runs its first input if the most recent TEST operation is FALSE. If its input is a list, IFFALSE treats it as an instruction list, and runs the input. If the TEST operation is TRUE, IFFALSE does nothing.
The TEST operation only affects the procedure where it is called, and procedures that the procedure calls. See also IFTRUE and IF.
Example
TO GUESS.IT :NUM PR [CAN YOU GUESS MY NUMBER?] MAKE “GUESS READWORD TEST :NUM = :GUESS IFTRUE [PR [GOOD GUESS!] STOP] IFFALSE [PR [NO, TRY AGAIN.]] GUESS.IT :NUM END
GUESS.IT 4 </span>
IFTRUE
Also: IFT
Runs a list if TEST was true.
Syntax
IFTRUE instruction-list
Description
IFTRUE runs its first input if the most recent TEST operation is TRUE. If its input is a list, IFTRUE treats it as an instruction list, and runs the input. If the TEST operation is FALSE, IFTRUE does nothing.
The TEST operation only affects the procedure where it is called, and procedures that the procedure calls. See also IFFALSE and IF.
Example
TO GUESS.IT :NUM PR [CAN YOU GUESS MY NUMBER?] MAKE “GUESS READWORD TEST :NUM = :GUESS IFTRUE [PR [GOOD GUESS!] STOP] IFFALSE [PR [NO, TRY AGAIN.]] GUESS.IT :NUM END
GUESS.IT 8 </span>
IGNORE
Ignores the output of a procedure.
Syntax
IGNORE object
Description
IGNORE simply “swallows” any output created by its input, which can be any Logo object. IGNORE is very handy if the output of any procedure is not needed.
LABEL
Marks a target for the GO command.
Syntax
LABEL object
Description
LABEL marks the target of a GO-LABEL loop. Its input must match the input of the corresponding GO command. LABEL is used in conjunction with GO.
Example
The procedure PINWHEEL runs forever; click the Stop button to stop the procedure.
TO PINWHEEL FD 100 LABEL “LOOP REPEAT 4 [FD 50 RT 90] RT 20 GO “LOOP END PINWHEEL
LOCAL
Declares local variables inside a procedure.
Syntax
LOCAL name
(LOCAL name1 name2 ...)
Description
LOCAL defines its input as a local variable whose value affects only the procedure in which it is called. The variable’s previous value (if any) is saved at the beginning of the procedure where it is redefined and restored at the end of the procedure. The variable is only available within the procedure in which it is defined and in all other procedures which are called from within the procedure where the variable is defined. The inputs to LOCAL must be quoted words.
Initially, a local name does not have a value. An attempt to read from a freshly declared local name causes a runtime error.
OUTPUT
Also: OP
Exits a procedure and outputs a value.
Syntax
OUTPUT value
Description
OUTPUT makes its input the output of the procedure. After OUTPUT is run, control returns to the calling procedure or to toplevel. If OUTPUT is used outside of a procedure, control returns to toplevel, and the result of the current toplevel command is OUTPUT’s input.
REPCOUNT
Reports the value of the REPEAT counter.
Syntax
REPCOUNT
Description
REPCOUNT outputs the current value of the repeat counter of the innermost active REPEAT or FOREVER command. If there is no active REPEAT or FOREVER command, REPCOUNT outputs the value -1.
Example
REPEAT 5 [(PRINT REPCOUNT “OF REPTOTAL)] 1 OF 5 2 OF 5 3 OF 5 4 OF 5 5 OF 5
REPEAT
Runs a runlist repeatedly.
Syntax
REPEAT number list
Description
REPEAT runs the list of instructions in the second input the number of times indicated by its first input. The number input to REPEAT can be any positive integer greater than 0. If the number is not an integer, its fractional portion is ignored. REPEAT commands can be nested, or placed inside other REPEAT commands.
The REPCOUNT command reports the current value of the internal REPEAT count. The REPTOTAL command outputs the total number of repetitions. See also FOREVER and FOR.
Example
REPEAT 5 [PRINT [I WILL NOT BITE MY NAILS]] I WILL NOT BITE MY NAILS I WILL NOT BITE MY NAILS I WILL NOT BITE MY NAILS I WILL NOT BITE MY NAILS I WILL NOT BITE MY NAILS
REPTOTAL
Reports the total number of REPEATs.
Syntax
REPTOTAL
Description
REPTOTAL outputs the total number of repetitions of the innermost active REPEAT FOREVER command. If there is no active REPEAT or FOREVER command, REPTOTAL outputs the value -1. In case of FOREVER, REPTOTAL outputs a very large number.
Example
REPEAT 5 [(PRINT REPCOUNT “OF REPTOTAL)] 1 OF 5 2 OF 5 3 OF 5 4 OF 5 5 OF 5
RUN
Runs a word or list.
Syntax
RUN word-or-list
Description
RUN runs its input as if it were typed in directly. RUN outputs whatever its list of instructions reports. If the run list contains more than one command, and one of the commands outputs a value, RUN does not run the remaining commands. If the input to RUN is a word, RUN outputs that word. See also EVAL.
Example
RUN [1 PR “NOT.PRINTED] Result: 1
STOP
Exits a procedure.
Syntax
STOP
Description
STOP causes Logo to halt execution of the current procedure and return to the calling procedure. If there is no calling procedure, Logo returns to TOPLEVEL.
TEST
Test a condition; used with IFTRUE and IFFALSE.
Syntax
TEST expression
Description
TEST determines whether its input is TRUE or FALSE and stores it for later use by IFTRUE or IFFALSE. The effect of TEST is local to the procedure in which it is used; any corresponding IFTRUE or IFFALSE must be in the same procedure or a subprocedure. If no procedure is active, the result of the TEST is stored globally, and any procedures that are called afterwards inherit this value. See also IF.
Example
TO GUESS.IT :NUM PR [CAN YOU GUESS MY NUMBER?] MAKE “GUESS READWORD TEST :NUM = :GUESS IFTRUE [PR [GOOD GUESS!] STOP] IFFALSE [PR [NO, TRY AGAIN.]] GUESS.IT :NUM END
GUESS.IT 5 </span>
TEXT
Outputs a procedure definition.
Syntax
TEXT procedurename
Description
TEXT takes a quoted procedure name as input and reports the definition of that procedure. The form of the output is a list. The first element of the list is any variable(s) defined in the title line of the procedure. If there are no variables, the first element is the empty list ([]). Each remaining element is a list that consists of one line of the procedure definition. The output of TEXT is in the same form as the required input for DEFINE. If the input to TEXT is a primitive, TEXT output the list [Primitive XXX], where XXX is the name of the primitive.
See also PRINTOUT, POPS, and POTS.
THEN
Starts the THEN branch of an IF command.
Syntax
IF expression THEN instructions
IF expression THEN instructions ELSE instructions
Description
THEN starts the branch of an IF command that is executed if the condition is true. THEN collects the entire remainder of the current line into a list and outputs a list unless it finds an ELSE command; if found, THEN stops collecting at the ELSE command. THEN is a special word like ELSE or END and not a procedure by itself.
THROW
Throws a Logo word or a runtime error.
Syntax
THROW word
(THROW runtime-error-word text)
(THROW)
Description
THROW returns control to the CATCH statement with a matching first input, or to the CATCH TRUE statement, whichever comes first in the chain of active procedures. If THROW is used without inputs, it re-throws an error that was caught with a CATCH statement in the same procedure. If there was no caught error, (THROW) does nothing. The command THROW “TOPLEVEL ends all programs and returns control to the Listener if the error is not caught.
If THROW is executed with more than one input, it throws a Logo runtime error. See :ERROR for a list of predefined Logo runtime error types. You are free to throw whatever you like, though.
Example
Print an error if present, and rethrow that error.
TO RETHROW :RUNLIST CATCH “ERROR :RUNLIST IF WORD? :ERROR [PR :ERRORTEXT] ; print error if present (THROW) ; rethrow the error END
RETHROW [SQRT -1] </span>
TO
Defines a procedure.
Syntax
TO procname
TO procname :input ...
TO procname ... [:optional-input value] ... argcount
TO procname ... [:list-input] argcount
Description
TO is the first word of a procedure definition. When typed at toplevel and followed by an unquoted procedure name, the prompt changes to the procedure name as lines are typed in. A single line containing the word END ends the procedure definition.
The input to the procedure follows the procedure name. Each input is a colon, followed by the name of the input variable. It is possible to define inputs with default values. These input variables are preset with the given value if the procedure is called with too few inputs. An optional input is a two-element list. The first element is a colon, followed by the name of the input variable, and the second element is the default value. Also, the last input may be a single-element list containing a colon, followed by the input variable name. Such an input variable collects all additional inputs into a list and assigns this list to the input variable. If there are too few inputs, the variable is set to the empty list.
Note: The value for the optional input is not evaluated. It cannot
be an expression, and quoted values remain quoted. Future versions of
Logo will be able to evaluate an expression; if you want to stay
compatible with future versions of Logo, please use only the values
TRUE
or FALSE
, numbers, or lists; do not use words, as they may be
interpreted as procedure names in the future.
It is possible to define the default number of inputs. This number is the number of inputs that Logo feeds the procedure with if the procedure call is not enclosed in parentheses. The number is given as the last element of the TO command. It must always be equal to or greater than the number of non-list inputs. If there is no number given, the number of inputs amounts to the number of inputs that are not lists.
The command TO FUNC :ONE [:TWO 2] 1 defines, for example, the procedure FUNC, with one required and one optional input. If the call is not enclosed in parentheses, Logo will call the procedure with one input, and set the input :TWO to the value 2. Otherwise, Logo will send :TWO to the second input. Thus, FUNC 123 would set :ONE to 123, and :TWO to 2, but (FUNC 123 456) would set :TWO to 456.
If, for example, the command is TO FUNC [:ARGS] 2, Logo usually calls FUNC with two inputs. Both inputs are concatenated into a list and assigned to the variable :LIST. Using the command FUNC “A “B sets :LIST to [A B]; using (FUNC 1 2 3) sets :LIST to [1 2 3], and (FUNC) sets :LIST to the empty list.
Example
TO FUNC :A [:B 2] 1 OP LIST :A :B END
FUNC 11 (FUNC 11 22)
TO FUNC [:LIST] 1 OP :LIST END
FUNC 11 (FUNC 11 22) </span>
TOPLEVEL
Returns to toplevel.
Syntax
TOPLEVEL
Description
TOPLEVEL stops execution of a procedure and returns Logo to toplevel, the command mode. TOPLEVEL in a procedure performs the same function as clicking the Stop button. You may also THROW “TOPLEVEL to return to toplevel. TOPLEVEL may also be caught with a CATCH command. Note that TOPLEVEL is different from STOP in that control is not returned to any calling procedure.
WAIT
Waits for a number of milliseconds.
Syntax
WAIT number
Description
WAIT inserts a pause before the next instruction is run. The length of the pause is the input to WAIT times 1/1000 of a second (milliseconds).
If you use the command WAIT -1, Logo never stops waiting. This is
convenient for programs that handle events, because you do not want the
program to end and lose its WHEN
handlers.
The accuracy of WAIT depends on the wait time and the number of executing background procedures. A WAIT time of under 15 is usually quite precise, while longer WAIT times may wait longer than expected. WAIT times under 15 do not release the CPU, while longer wait times do.
Example
; start InO-Bot and turn off motors for a second if the infrared ; sensor input value is > 0.9 WHEN [INOBOT INFRARED > 0.9] [ MOTORS 0 WAIT 1000 MOTORS 0.3 ] MOTORS 0.3 WAIT -1
WHILE
Runs a list until a condition is false.
Syntax
WHILE testlist runlist
Description
WHILE evaluates its first input and runs the Logo command(s) in its second input if the value of the first input is TRUE. WHILE will continue this process until the value of the first input is FALSE.
Note: WHILE is a Logo procedure. Commands like STOP and OUTPUT in the runlist will, therefore, exit the WHILE loop, but not any procedure that contains the WHILE command!
Example
MAKE “X 1 WHILE [:X <= 5] [PRINT :X MAKE “X :X + 1] 1 2 3 4 5