In Scheme, the general form of a procedure definition is:
(define (<name> <parameters>) <body>)
where <body> accepts a sequence of expressions, allowing this kind of procedure definitions:
> (define (f) 1 2 3)
> (f)
3
Likewise, the general form of a conditional expression is:
(cond (<predicate> <consequent>) (<predicate> <consequent>) … (<predicate> <consequent>))
where <consequent> in each clause accepts a sequence of expressions, allowing this kind of conditional expressions:
> (cond (#t 1 2 3))
3
But why can’t I use define
in a clause’s consequent of a conditional expression like in the body of a procedure definition?
Compare:
> (define (f) (define x 1) (define y 1) (define z 1) (+ x y z))
> (f)
3
with:
> (cond (#t (define x 1) (define y 1) (define z 1) (+ x y z)))
ERROR on line 1: unexpected define: (define x 1)
Note. — I am using the Chibi-Scheme 0.8.0 implementation on MacOS 10.15.2.
As @Barmar noted, definitions are not expressions, but there are two contexts where both are allowed, cf. section 5.1. of the latest specification of the Scheme programming language Revised7 Report on the Algorithmic Language Scheme (R7RS):
A Scheme program consists of one or more import declarations followed by a sequence of expressions and definitions. Import declarations specify the libraries on which a program or library depends; a subset of the identifiers exported by the libraries are made available to the program. Expressions are described in chapter 4. Definitions are either variable definitions, syntax definitions, or record-type definitions, all of which are explained in this chapter. They are valid in some, but not all, contexts where expressions are allowed, specifically at the outermost level of a ⟨program⟩ and at the beginning of a ⟨body⟩.
That is why define
is allowed in the body of a procedure definition but not in a clause’s consequent of a conditional expression since it is not a body.