将代码转换为/从字符串

时间:2013-11-08 14:50:44

标签: scheme

麻省理工学院计划有string->input-port,球拍有open-input-string。如何在纯Scheme中实现这一点(没有Racket,Chicken,Gambit或任何特定于实现的扩展)。

3 个答案:

答案 0 :(得分:1)

在最近批准的R7RS中,open-input-string是直接提供的。 (感谢Sylwester提醒我超越R5RS。: - ))


在R5RS中,字符串端口的纯Scheme实现并不简单,因为它要求您重新定义所有标准I / O函数。有关参考实现,请参阅SRFI 6

如果您的实现直接支持字符串端口,那确实更好。

答案 1 :(得分:1)

根据Chis' answer,我们有一个新的Scheme标准R7RS。它已提供open-input-string

对于较旧的R6RS,使用(rnrs io ports (6))库中的make-custom-textual-input-port实现相同的操作非常简单。这是我放在一起的东西:

#!r6rs

(import (rnrs base (6))
        (rnrs io ports (6))
        (rnrs mutable-strings (6))
        (rnrs io simple (6)))

(define (open-input-string str)
  ;; might not be so important to have a different indentifier
  ;; but this will make debugging easier if implementations use the 
  ;; id provided
  (define get-id
    (let ((n 0))
      (lambda (str)
        (set! n (+ n 1))
        (string->symbol 
         (string-append "string-port" str "-"
                        (number->string n))))))

  (let ((len (string-length str))
        (pos 0))
    (make-custom-textual-input-port 
     (get-id str)
     (lambda (string start count)
       (let loop ((cur-dst start)
                  (cur-src pos)
                  (n 0))
         (cond ((or (>= cur-src len)
                    (>= n count))
                (set! pos cur-src)
                n)
               (else
                (string-set! string cur-dst (string-ref str cur-src))
                (loop (+ cur-dst 1)
                      (+ cur-src 1)
                      (+ n 1))))))
     (lambda () pos)
     (lambda (new-pos) (set! pos new-pos))
     #f)))

(define test (open-input-string "(1 2 3 4)(5 6 7 8)"))
(define str (read test))  ; str == (1 2 3 4)
(define str2 (read test)) ; str2 == (5 6 7 8)

使用R5RS除了使用文件外无法执行此操作。

答案 2 :(得分:-2)

将字符串写入(临时)文件,然后返回一个输入端口以将其读回。像这样:

(define (open-input-string string)
  (let ((file "/tmp/foo"))
    (call-with-output-file file
      (lambda (port)
         (display string port)))
    (open-input-file file)))

> (define ps (open-input-string "This is a test; it is only a test"))
> ps
#<input-port (textual) "/tmp/foo">
> (read-line ps)
"This is a test; it is only a test"

请注意,使用file时您需要更加复杂。例如,上面的代码只能工作一次;第二次调用时,“文件存在”将失败。但以上是您问题的简单答案。