【问题标题】:what is the alternative for internal definition内部定义的替代方法是什么
【发布时间】:2015-04-07 23:34:42
【问题描述】:

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

像下面这两个例子一样给我错误信息

define: 不允许在表达式上下文中:(define inp (read-command))

(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))

【问题讨论】:

    标签: scheme racket r5rs


    【解决方案1】:

    内部定义只能在过程的开头(或隐式过程上下文,如let 主体)。在任何情况下,它们都是 letrec* 表单的语法糖,您可以随时根据它重写。

    【讨论】:

      【解决方案2】:

      如果您阅读过您的 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 实现能够做到这一点。

      我敢肯定,你可以在没有很多副作用的情况下做到这一点。您可以直接传递它们,而不是依赖全局变量。这将使您的程序更容易测试和调试。

      【讨论】:

      • 啊,好吧,我将如何为第二个定义做它(inp,lengtha),当我这样做时它弄乱了我的输出结果,我的输入变量都没有进入堆栈,inp 用于我的商店输入
      • @user3465992 已更新。我使用let* 来确保评估顺序,因为您使用了很多突变。顺便说一句,在问题中编辑掉你的部分代码会使我的答案看起来不对。
      • 好的,谢谢,当我尝试运行完整代码时,STACK 命令正在终止我的程序,而不是从上到下打印出堆栈的当前内容
      • @user3465992 然后你在某个地方有一个错误,所有的突变都使它变得困难,所以你需要使用调试器逐步完成。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-13
      • 2015-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多