go
go Special Operator
Syntax:
go tag →
Arguments and Values:
tag—a go tag.
Description:
go transfers control to the point in the body of an enclosing tagbody form labeled by a tag eql to tag. If there is no such tag in the body, the bodies of lexically containing tagbody forms (if any) are examined as well. If several tags are eql to tag, control is transferred to whichever matching tag is contained in the innermost tagbody form that contains the go. The consequences are undefined if there is no matching tag lexically visible to the point of the go.
The transfer of control initiated by go is performed as described in Section 5.2 (Transfer of Control to an Exit Point).
Examples:
(tagbody
(setq val 2)
(go lp)
(incf val 3)
lp (incf val 4)) → NIL
val → 6
The following is in error because there is a normal exit of the **tagbody** before the **go** is executed.
(let ((a nil))
(tagbody t (setq a #’(lambda () (go t))))
(funcall a))
The following is in error because the **tagbody** is passed over before the **go** *form* is executed.
(funcall (block nil
(tagbody a (return #’(lambda () (go a))))))
See Also:
tagbodyExpanded Reference: go
Basic control transfer within tagbody
go transfers control to a tag label within an enclosing tagbody form. Tags are symbols or integers that label positions in the body.
(let ((result nil))
(tagbody
(push 'a result)
(go skip)
(push 'b result) ; this is skipped
skip
(push 'c result))
(nreverse result))
=> (A C)
Building a simple loop with go
go and tagbody can be used to create loops. In practice, higher-level constructs like do and loop are preferred.
(let ((i 0) (sum 0))
(tagbody
top
(when (> i 5) (go end))
(setq sum (+ sum i))
(setq i (+ i 1))
(go top)
end)
sum)
=> 15
go within prog
prog establishes an implicit tagbody, so go can be used directly in a prog form.
(prog ((x 0))
start
(if (>= x 5) (return x))
(setq x (+ x 1))
(go start))
=> 5
Tags can be integers
Go tags can be integers as well as symbols.
(let ((x 'initial))
(tagbody
(setq x 'before)
(go 10)
(setq x 'skipped)
10
(setq x (list x 'after)))
x)
=> (BEFORE AFTER)
The scope of go is lexical
go can only transfer to tags that are lexically visible. You cannot use go to jump into a tagbody from outside its lexical scope.
;; go finds the innermost matching tag
(let ((result nil))
(tagbody
(tagbody
(go done) ; jumps to inner done
done
(push 'inner result))
(push 'outer result)
done)
(nreverse result))
=> (INNER OUTER)