【问题标题】:Scheme (Racket) printing #void方案(球拍)打印#void
【发布时间】:2017-09-28 04:43:46
【问题描述】:

我在 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))

预期结果是:

eq?(5,3) ? 1 : 0

但是,我得到的结果是:

eq?(5,3) # ? 1 : 0

【问题讨论】:

    标签: scheme racket


    【解决方案1】:

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

    要确定打印空白的位置,请插入

    (displayln ast)
    

    紧接着

     (lambda (ast output-port)
    

    这样每次调用 unparse->js 时都会打印当前的 ast。然后你可以找到罪魁祸首的 cond 子句。

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

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

    试试这个

    (with-output-to-string (lambda () (unparse->js (parse '(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 返回一个字符串树。

    然后简单地创建一个在树中递归并打印单个字符串的打印机函数。

    【讨论】:

    • 很抱歉让您感到困惑。上面写的函数是 unparse->js。现在修好了。
    • (parse '(if (eq? 5 3) 1 0)) 的结果是什么
    • '(if-exp (app-exp (var-exp eq?) ((num-exp 5) (num-exp 3))) (num-exp 1) (num-exp 0 )) 基本上,这些“表达式”是使用另一个模块翻译的,即“解析器”
    • 添加了新建议。
    • 太棒了!谢谢。我得到以下输出: (if-exp (app-exp (var-exp eq?) ((num-exp 5) (num-exp 3))) (num-exp 1) (num-exp 0) ) -|- (app-exp (var-exp eq?) ((num-exp 5) (num-exp 3)))-|- (var-exp eq?)-|- (num-exp 5)- |- (num-exp 3)-|- eq?(5,3)(num-exp 1)-|- (num-exp 0)-|- # ? 1 : 0-|- 虽然不是很可读,所以我添加了行分隔符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-27
    • 2017-01-28
    • 1970-01-01
    • 2012-11-12
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多