0

MIT スキームには がありstring->input-port、ラケットには がありopen-input-stringます。これを純粋なスキームで実装する方法 (Racket、Chicken、Gambit、または実装固有の拡張機能はありません)。

4

3 に答える 3

1

Chis の回答によると、新しいスキーム標準 R7RS があります。提供してきopen-input-stringた。

古い R6RS の場合、ライブラリからmake-custom-textual-input-portを使用して同じことを実装するのは簡単です。(rnrs io ports (6))ここに私がまとめたものがあります:

#!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ファイルを使用する以外にこれを行う方法はありません。

于 2013-11-08T16:32:35.407 に答える
1

最近承認されたR7RSでは、open-input-stringが直接提供されます。(R5RS の先を見るように思い出させてくれた Sylwester に感謝します。:-))


R5RS では、すべての標準 I/O 関数を再定義する必要があるため、文字列ポートの純粋な Scheme 実装は簡単ではありません。リファレンス実装については、SRFI 6を参照してください。

実装が文字列ポートを直接サポートしている場合は、実際に優れています。

于 2013-11-08T15:26:22.217 に答える
-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。たとえば、上記のコードは一度しか機能しません。2 回目の呼び出しで「ファイルが存在します」で失敗します。しかし、上記はあなたの質問に対する簡単な答えです。

于 2013-11-08T15:18:09.540 に答える