方案(球拍)印刷#void

时间:2017-04-30 14:53:01

标签: scheme racket

我在Scheme中有以下功能(使用Dr. Racket),它是从Scheme到Javascript的模糊翻译。

我似乎无法弄清楚为什么会打印#void。

我猜它与fprintf的返回值有关,但我不确定如何克服这种行为。

有什么想法吗?

(define unparse->js
(lambda (ast output-port)
(cond ((def-exp? ast) (fprintf output-port "const ~a = ~a;" (unparse->js 
(def-exp->var ast) output-port) (unparse->js (def-exp->val ast) output-port)))
      ((cexp? ast)
       (cond ((num-exp? ast) (number->string (num-exp->val ast)))
             ((bool-exp? ast) (if (eq? (bool-exp->val ast) #t) "true" "false"))
             ((str-exp? ast)  (str-exp->val ast))
             ((var-exp? ast)  (symbol->string (var-exp->var ast)))
             ((literal-exp? ast) (list 'quote (literal-exp->val ast)))
             ((proc-exp? ast) (fprintf output-port "(~a) => { ~a }"
                                       (string-join
                                        (map (lambda (b)
                                             (unparse->js b output-port)
                                             )
                                           (proc-exp->params ast)
                                       )
                                      ",")
                                       (string-join
                                      (map (lambda (ast)
                                             (unparse->js ast output-port)
                                             )
                                           (proc-exp->body ast))
                                      ";")))

             ((if-exp? ast) (fprintf output-port "~a ? ~a : ~a"
                                     (unparse->js (if-exp->test ast) output-port)
                                     (unparse->js (if-exp->then ast) output-port)
                                     (unparse->js (if-exp->else ast) output-port)))
             ((let-exp? ast) (fprintf output-port "let ~a; ~a;"
                                     (string-join
                                      (map (lambda (b)
                                             (fprintf output-port "~a = ~a"
                                                      (unparse->js (binding->var b) output-port)
                                                      (unparse->js (binding->val b) output-port)
                                                      )
                                             )
                                           (let-exp->bindings ast)
                                       )
                                      ",")
                                     (string-join
                                      (map (lambda (b)
                                             (unparse->js b output-port)
                                             )
                                           (let-exp->body ast))
                                      ";")

                              )
              )
             ((app-exp? ast) (fprintf output-port "~a(~a)"
                                      (unparse->js (app-exp->rator ast) output-port)
                                      (string-join
                                        (map (
                                              lambda (rand)
                                               (unparse->js rand output-port)
                                              )
                                         (app-exp->rands ast)
                                        )
                                        ",")
                              )
              )
             (else (error "Unknown exp type: " ast))))
      (else (error "Unknown exp type: " ast)))
  )
)

我这样称呼它:

  

(unparse-> js(parse'(if(eq?5 3)1 0))(current-output-port))

预期结果是:

  等等?(5,3)? 1:0

然而,我得到的结果是:

  

eq?(5,3)#<无效> ? 1:0

1 个答案:

答案 0 :(得分:1)

尝试打印到字符串输出端口,看看是否能解决问题。 如果没有生成完整的例子我们可以测试。该错误可能在,例如,unparse-> js或其他功能。

要计算空白的打印位置,请插入

(displayln ast)

之后
 (lambda (ast output-port)

这样,每次调用unparse-> js时都会显示当前的ast。然后你可以找到罪魁祸首的条款。

关于评论,会弹出更多“空洞”。

有两个问题:首先输出端口与repl输出端口相同。这意味着您不打印的值(例如在num-exp子句中)由repl打印。

试试这个

(具有输出到字符串       (lambda()(unparse-> js(解析'(if(eq?5 3)1 0))(current-output-port))))

这将生成一个包含所有内容的字符串。

第二个问题是由于这种打印方式:

 (fprintf output-port "~a ? ~a : ~a"
     (unparse->js (if-exp->test ast) output-port)
     (unparse->js (if-exp->then ast) output-port)
     (unparse->js (if-exp->else ast) output-port)))

由于unparse-js在您使用fprintf的所有子句中返回void(请记住fprintf返回void),如果其中一个子表达式返回void,则会打印void

现在的问题是如何避免这个问题。一种常见的解决方案是将打印分为两部分。第一阶段是建立一个字符串树。打印字符串中的字符串将产生正确的输出。

所以而不是:

 (fprintf output-port "~a ? ~a : ~a"
     (unparse->js (if-exp->test ast) output-port)
     (unparse->js (if-exp->then ast) output-port)
     (unparse->js (if-exp->else ast) output-port)))
你写了

 (list (unparse->js (if-exp->test ast))
       " ? " 
       (unparse->js (if-exp->then ast))
       " : "
       (unparse->js (if-exp->else ast))))

这将使unparse->js返回一个字符串树。

然后简单地创建一个打印机功能,通过树进行递归并打印单个字符串。