内部定义的替代方案是什么

时间:2015-04-07 23:34:43

标签: scheme racket r5rs

我使用的

版本的球拍/ drSCHEME不允许我使用(R5RS)语言使用内部定义

就像下面这两个例子给我的错误信息

  

define:在表达式上下文中不允许:(定义inp(读命令))

(define repl 
 (lambda() 
 (display "\nUofL>") 
 (define inp (read-command)) 
 (define lengtha (length com)) 
      (cond 
        ((equal? inp "CLEAR")(set! lista '())(repl)) 
        ((equal? inp "REV")(set! lista (cdr lista))(set! lista (rev lista))(repl)) 
        ((equal? inp "STACK")(set! lista (cdr lista))(display lista)(repl)) 
        ((equal? inp "SWAP")(set! lista (cdr lista))(set! lista (append (list (cadr lista)) (list (car lista)) (cddr lista)))(repl)) 
        ((equal? (car lista) "EXIT") (display "Bye.")(set! lista (cdr lista))) 
        ((equal? inp "DROP")(set! lista (cddr lista))(repl)) 
        ((equal? (car lista) "POP") 
         (set! lista (cdr lista)) 
         (cond 
           ((null? lista)(display "Empty Stack")(repl)) 
           ((string->number (car lista))(set! pop (car lista))(set! lista (cdr lista))(repl) ) 
           ((search (car lista) sym symval) 
            (cond 
              ((null? (cdr lista)) (set! lista (cdr lista)) 
              (display "Empty Stack") (repl)) 
              (else 
               (addsym (car lista) (cadr lista)) 
               (set! pop (cadr lista)) 
               (set! lista (cddr lista)) 
               (repl)))) 

           (else 
            (set! lista (cdr lista)) 
            (display "Var not declared")(repl)))) 

        ((equal? inp "SAVE") 
         (set! lista (cdr lista)) 
         (cond 
           ((equal? pop "")(display "Can't SAVE null")) 
           (else  (set! lista (append (list pop) lista))(set! pop ""))) 
         (repl)) 
        ((equal? inp "DUP")(set! lista (cdr lista))(set! lista (append (list (car lista)) lista))(repl)) 
        ((equal? (op? (car lista)) ".")(set! lista (cdr lista)) 
        (cond 
          ((equal? lengtha 1)(if (null? lista) (display "Empty Stack") (display (car lista)))(repl)) 
          (else (displayn (- lengtha 1))(repl)))) 
        ((string->number (car lista)) 
         (cond 
           ((null? (cdr lista))(repl)) 
           ((op? (cadr lista))(repl)) 
           (else (set! lista (cleanup-eval lista))(repl)))) 
        ((equal? (car lista) "define") 
         (set! lista (cdr lista)) 
         (set! sym (append (list (car lista)) sym)) 
         (set! lista (cdr lista)) 
         (cond 
           ((string->number (car lista)) 
            (set! symval (append (list (string->number (car lista))) symval))) 
           (else 
            (set! symval (append (list (car lista)) symval)))) 


         (set! lista (cdr lista)) 
         (repl) ) 
        (else 
         (cond 
           ((search (car lista) sym symval)(set! lista (append (list (cadr res)) (cdr lista))) 
           (if (number? (car lista)) (set! lista (append (list(number->string (car lista))))))) 
           (else 
            (display (car lista))(set! lista (cdr lista)))))) 
            (repl)))) 

编辑: 对于上面的定义,我尝试将其作为替代方案,但它只会导致我的堆栈,rev和另一个命令只是打印出自己的名字......

(define repl
             (lambda()
              (display "\nUofL>")
              (let ((inp (read-command))
                    (lengtha (length com))

2 个答案:

答案 0 :(得分:1)

如果您已阅读过R5RS圣经,则您知道在任何其他表达之后不允许使用本地define。因此:

(define (read-command) 
  (set! com '( '() ))             ;; illegal needs to go after ret1 define
  (set! wl (read-as-list))        ;; illegal needs to go after ret1 define
  (define ret1 (list->string wl))
  (commRead) 
  ret1) 

我不确定全局变量comw1的用途,但您可以稍后设置它们。事实上,您根本不需要define

(define (read-command) 
  (let* ((tmp-w1 (read-as-list))
         (ret1 (list->string tmp-wl)))
    (set! com '( '() ))
    (set! wl tmp-w1)
    (commRead) 
    ret1))

修改

以下是repl的重写:

(define (repl) 
  (display "\nUofL>") 
  (let* ((inp (read-command)) 
         (lengtha (length com))) 
    (cond 
      ((equal? inp "CLEAR")(set! lista '())(repl)) 
      ((equal? inp "REV")(set! lista (cdr lista))(set! lista (rev lista))(repl)) 
      ((equal? inp "STACK")(set! lista (cdr lista))(display lista)(repl)) 
      ((equal? inp "SWAP")(set! lista (cdr lista))(set! lista (append (list (cadr lista)) (list (car lista)) (cddr lista)))(repl)) 
      ((equal? (car lista) "EXIT") (display "Bye.")(set! lista (cdr lista))) 
      ((equal? inp "DROP")(set! lista (cddr lista))(repl)) 
      ((equal? (car lista) "POP") 
       (set! lista (cdr lista)) 
       (cond 
         ((null? lista)(display "Empty Stack")(repl)) 
         ((string->number (car lista))(set! pop (car lista))(set! lista (cdr lista))(repl) ) 
         ((search (car lista) sym symval) 
          (cond 
            ((null? (cdr lista)) (set! lista (cdr lista)) 
                                 (display "Empty Stack") (repl)) 
            (else 
             (addsym (car lista) (cadr lista)) 
             (set! pop (cadr lista)) 
             (set! lista (cddr lista)) 
             (repl)))) 

         (else 
          (set! lista (cdr lista)) 
          (display "Var not declared")(repl)))) 

      ((equal? inp "SAVE") 
       (set! lista (cdr lista)) 
       (cond 
         ((equal? pop "")(display "Can't SAVE null")) 
         (else  (set! lista (append (list pop) lista))(set! pop ""))) 
       (repl)) 
      ((equal? inp "DUP")(set! lista (cdr lista))(set! lista (append (list (car lista)) lista))(repl)) 
      ((equal? (op? (car lista)) ".")(set! lista (cdr lista)) 
                                     (cond 
                                       ((equal? lengtha 1)(if (null? lista) (display "Empty Stack") (display (car lista)))(repl)) 
                                       (else (displayn (- lengtha 1))(repl)))) 
      ((string->number (car lista)) 
       (cond 
         ((null? (cdr lista))(repl)) 
         ((op? (cadr lista))(repl)) 
         (else (set! lista (cleanup-eval lista))(repl)))) 
      ((equal? (car lista) "define") 
       (set! lista (cdr lista)) 
       (set! sym (append (list (car lista)) sym)) 
       (set! lista (cdr lista)) 
       (cond 
         ((string->number (car lista)) 
          (set! symval (append (list (string->number (car lista))) symval))) 
         (else 
          (set! symval (append (list (car lista)) symval)))) 

由于您使用的是R5RS,我在这里也使用了let*,以防有副作用。 let不一定会从左到右评估它的论点,尽管我希望PLT实现这样做。

我相信你可以在这里没有很多副作用。您可以直接传递它们,而不是依赖于全局变量。它将使您的程序更容易测试和调试。

答案 1 :(得分:1)

内部定义只能位于过程的开头(或隐式过程上下文,如let主体)。在任何情况下,它们都是letrec*形式的语法糖,你总是可以用它来重写。