将Scheme表达式转换为字符串

问题描述 投票:5回答:6

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

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

任何想法的人都谢谢

string macros lambda scheme expression
6个回答
7
投票

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


4
投票

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

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

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

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

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

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

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

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


1
投票

使用pretty-format

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

1
投票

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

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


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

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
© www.soinside.com 2019 - 2024. All rights reserved.