将Scheme表达式转换为字符串

时间:2009-11-02 00:34:44

标签: string macros lambda scheme expression

给定一个表达式'(lambda(x)x)如何将其转换为字符串。我认为symbol->字符串可以完成这项工作,但不能没有符号。

例如对于宏到字符串: (to-string(lambda(x)x))这应该返回>> “(lambda(x)x)”

任何想法的人都谢谢

6 个答案:

答案 0 :(得分:7)

标准方案(至少在R5RS意义上)无法做到这一点,所以如果你想要可移植的代码,你需要自己走结构。繁琐但不太复杂(即使是虚线列表)。 但是如果您只想要某些工作版本,那么您应该查看实现手册并搜索执行此操作的方法。答案几乎总是很简单,例如,在PLT Scheme中你使用(format "~s" '(lambda ...))

答案 1 :(得分:4)

表达式'(lambda (x) x)是一个引用列表。

表达式(lambda (x) x)是运行时的某种编译,不透明,可执行的内部对象。

symbol->string只是将符号转换为字符串,这是一个字符序列。

如果您正在使用列表,则可以简单地遍历列表并打印出各个组件。实际上(write '(lambda (x) x))只会打印出列表。

许多方案都有类似于(with-output-to-string ... )的东西,它返回写入标准端口的所有输出的字符串。

但是,如果你(write (lambda (x) x)),你会得到谁知道什么。转储可执行函数类型时,您将获得实现提供的任何内容。有些人可能会打印一个显示源代码的“反汇编”。其他人可能只是打印#function或同样无用的东西。

简而言之,如果你只是想打印出一个列表,那么就有各种各样的机制。

如果你想打印出已编译函数的源代码,这是一个完全不同的问题,非常依赖于实现,而且可能是不可能的。

答案 2 :(得分:1)

你应该走过一些道路。当一个新的缺点开始写“(”,当它结束写“)”并使用符号 - >字符串作为conses内的符号。

您可以使用类型调度来扩展它。方案中也可能存在漂亮的印刷品吗?

答案 3 :(得分:1)

使用pretty-format

(pretty-format v [columns]) → string?

答案 4 :(得分:0)

我认为这是一个简单的代码,可以满足您的要求。
它不使用特定于实现的东西,非常简单。

但是请注意,它不能正确处理字符串中的特殊字符(例如,“ a \” b \“ c”将变为“ a” b” c”)。

(define join
    (lambda (l delim to-str)
      (fold-left
        (lambda (str elem)
          (string-append str delim (to-str elem)))
        (to-str (car l))
        (cdr l))))
(define sexpr->string 
      (lambda (sexpr)
        (cond 
          ((number? sexpr) (number->string sexpr))
          ((symbol? sexpr) (symbol->string sexpr))
          ((boolean? sexpr) (if sexpr "#t" "#f"))
          ((string? sexpr) (string-append "\"" sexpr "\""))
          ((char? sexpr) (string-append "#\\" (string sexpr)))
          ((vector? sexpr) 
           (let ((s-vec (join (vector->list sexpr) " " sexpr->string)))
             (string-append "#(" s-vec ")")))
          ((null? sexpr) "()")
          ((list? sexpr) (string-append "(" (join sexpr " " sexpr->string) ")"))

          ((pair? sexpr) 
           (let ((s-car (sexpr->string (car sexpr)))
                 (s-cdr (sexpr->string (cdr sexpr))))
             (string-append "(" s-car " . " s-cdr ")"))))))

答案 5 :(得分:0)

如果使用的是R6RS兼容方案,则可以将write函数与call-with-string-output-port结合使用。

#!r6rs
(import (rnrs base)
        (rnrs io ports)   ;for call-with-string-output-port
        (rnrs io simple)) ;for write

;; Produces a string representation of the S-Expression e
(define (expr->string e)
  (call-with-string-output-port
   (lambda (out) (write e out))))

一些例子:

> (expr->string '(lambda (x) (+ x 1)))
"(lambda (x) (+ x 1))"
> (expr->string '(lambda (x) (string-append x " and cheese!")))
"(lambda (x) (string-append x \" and cheese!\"))"

顺便说一句,通常也可以将readopen-string-input-port结合使用,朝另一个方向发展。

;; Produces the S-Expression represented by the string.
;; In most cases this will be a left-inverse of expr->string,
;; so that (string->expr (expr->string e)) = e.
;; If the string has multiple S-Expressions represented
;; in it, this only returns the first one.
(define (string->expr s)
  (read (open-string-input-port s)))

一些例子:

> (string->expr "(lambda (x) (+ x 1))")
(lambda (x) (+ x 1))
> (equal? (string->expr "(lambda (x) (+ x 1))")
          '(lambda (x) (+ x 1)))
#t
> (equal? (string->expr (expr->string '(lambda (x) (+ x 1))))
          '(lambda (x) (+ x 1)))
#t
相关问题