Error with define in Racket

前端 未结 4 808
既然无缘
既然无缘 2021-02-05 23:04

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 #l

相关标签:
4条回答
  • 2021-02-05 23:27

    As GoZoner explained, you can't use define in an expression context.

    What could you do instead?

    Use let:

    (if (list? code)
        (let ([x '()])
          x)
        ...
    

    Or it would work with an "empty" let and define:

    (if (list? code)
        (let ()
          (define x '())
          x)
        ...
    

    But that's a bit silly.

    Or use cond and define:

    (cond [(list? code)
           (define x '())
           x]
          ...
    

    This last way -- using cond and define -- is closest to what the current Racket style guide recommends.

    0 讨论(0)
  • 2021-02-05 23:28

    Here's more details, from the Racket docs.

    The different contexts are required because macros must expand differently, depending on which language forms are allowed.

    As others have said, definitions are not allowed in expression contexts ("expr ..." in the docs), but are ok in other contexts.

    In other doc entries, "body ..." indicates an internal-definition context (guide, reference), for example in lambda bodies, and "form ..." indicates all non-expression contexts, like in the docs for begin.

    0 讨论(0)
  • 2021-02-05 23:36

    Or you could wrap the expressions in (begin) e.g.(begin (define x 10) (define y 100) (define z 1000))

    0 讨论(0)
  • 2021-02-05 23:38

    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)
    
    0 讨论(0)
提交回复
热议问题