User Tools

Site Tools


logo:commands:flow

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

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.

See also FOREACH and REPEAT.

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

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.

See also IFFALSE and IFTRUE.

Example

IF (FIRST TIME) > 18 THEN "NIGHT ELSE "DAY
Result: NIGHT

IFFALSE (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

IFTRUE (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

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 (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

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]

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)

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).

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

WAIT 1000

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
logo/commands/flow.txt · Last modified: 2019/01/22 06:09 (external edit)