Error with define in Racket
expression, functional-programming, lisp, racket, scheme
Solution
Definitions are allowed in a 'body' context, like in `lambda` and `let` among others. The consequent and alternate clauses of `if` are not body contexts; they are expression contexts and therefore definitions are not allowed.
`begin` is special - `begin` in a body context allows definitions, but `begin` in an expression contexts forbids definitions. Your case falls in to the later.
For example:
(define (foo . args) #| body context #|)
(define foo (lambda args #| body context |#))
(define (foo . args)
(let (...)
#| body context |#))
Syntactic keywords that requires expressions: `if, cond, case, and, or, when, unless, do, begin`. Check out the formal syntax in any Scheme report (r{4,5,6,7}rs); look for `<body>`, `<sequence>`, `<command>`, and `<expression>`.
Also, if you need a body context in an expression, just wrap a `let` syntactic form, as such:
(if test
(let ()
(define foo 'foo)
(list foo foo))
alternate)
Problem
I just discovered Racket a few days ago, and I'm trying to get more comfortable with it by writing a little script that generates images to represent source code using `#lang slideshow`. I know that when programming in a functional paradigm it's good practice to create almost all your variables with `let`, but I find that it introduces too many levels of nesting and that Racket's let has an overcomplicated API which requires superfluous parentheses. I'm sure this is to remove ambiguity when using `let` in more powerful ways, but for my purposes it's just an annoyance. Consequently, I'm creating all my variables with `define`, and writing blocks with `begin` if I need to (such as in the body of an `if` statement). The problem is that I've repeatedly been getting what seem to be very mysterious errors. I'm sure I'm just making some silly beginner's mistake, being new to the language, but I really can't seem to find the source of the complaint. Here's the offending code: ``` (define sub-code (foldr ht-append (rectangle 0 0) (map internal-style (rest code)))) ``` although what we're defining `sub-code` to seems pretty irrelevant. If I replace it with ``` (define sub-code '()) ``` I receive the same error. DrRacket is saying that `define` is being used in an expression context. I understand what this error would normally mean - IE that it would raise when you write code like `(print (define x 10))`, but I can't see what would trigger it here. If it helps, this `define` is at the beginning of a `begin` block, inside an `if` statement ``` (if (list? code) (begin (define sub-code '()) ; a few more define statements and finally an expression )) ``` The specific error message DrRacket is printing is ``` define: not allowed in an expression context in: (define sub-code (quote ())) ``` I thought maybe `define` isn't allowed in `begin` blocks, but I checked the docs and one of the examples for `begin` is ``` (begin (define x 10) x) ``` So I don't really know what to do. Thanks in advance!