Преобразование выражения Scheme в строку - PullRequest
5 голосов
/ 02 ноября 2009

Учитывая выражение '(лямбда (х) х), как я могу перевести это в строку. Я думал, что символ-> строка сделает работу, но нет, это не символ.

например, для макроса в строку: (to-string (lambda (x) x)) это должно вернуть >> "(lambda (x) x)"

Любые люди идеи Спасибо

Ответы [ 6 ]

7 голосов
/ 02 ноября 2009

Стандартная схема (по крайней мере, в смысле R5RS) не имеет возможности сделать это, поэтому, если вы хотите переносимый код, вам нужно пройтись по структуре самостоятельно. Утомительно, но не слишком сложно (даже для пунктирных списков). Но если вы просто хотите некоторую рабочую версию, то вам следует заглянуть в руководство по реализации и найти способ сделать это. Ответ почти всегда будет простым, например, в схеме PLT вы будете использовать (format "~s" '(lambda ...))

4 голосов
/ 02 ноября 2009

Выражение '(lambda (x) x) является списком в кавычках.

Выражение (lambda (x) x) является неким скомпилированным, непрозрачным, исполняемым внутренним объектом среды выполнения.

symbol->string просто преобразует символ в строку, представляющую собой последовательность символов.

Если вы работаете со списком, вы можете просто просмотреть список и распечатать отдельные компоненты. На самом деле (write '(lambda (x) x)) просто распечатает список.

Во многих схемах есть что-то похожее на (with-output-to-string ... ), которое возвращает строку всех выходных данных, записанных в стандартный порт.

Однако, если вы сделаете (write (lambda (x) x)), вы получите, кто что знает. Вы получите все, что обеспечивает реализация при выводе типа исполняемой функции. Некоторые могут распечатать «разборку» с указанием исходного кода. Другие могут просто напечатать #function или что-то такое же бесполезное.

Короче говоря, если вы просто хотите распечатать список, для этого есть все виды механизмов.

Если вы хотите распечатать исходный код скомпилированной функции, это совершенно другая проблема, сильно зависящая от реализации и вполне может быть невозможной.

1 голос
/ 02 ноября 2009

Использование pretty-format:

(pretty-format v [columns]) → string?
1 голос
/ 02 ноября 2009

Тебе следует пройти сквозь конусы. Когда новый минус начинает писать, напишите «(», когда он закончится, напишите «)» и используйте символ-> строку для символов внутри консов.

Вы можете расширить это с помощью диспетчеризации типов. Может быть, в схеме тоже есть красивый принт?

0 голосов
/ 17 сентября 2018

Если вы используете 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!\"))"

Кстати, обычно можно пойти и в другом направлении, используя read в сочетании с open-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
0 голосов
/ 17 сентября 2018

Это простой код, который, я думаю, делает то, что вы хотите.
Он не использует специфические для реализации вещи и довольно прост.

Обратите внимание, однако, что он неправильно обрабатывает специальные символы в строках (например, "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 ")"))))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...