2015-10-21 23 views

回答

3

不能在普通列表中打印逗號,但我們可以用流的內容構建一個字符串,用逗號分隔。這將工作,假設該字符串包含數字

(define (print-first-n stream1 n) 
    (cond ((= n 1) 
     (number->string (stream-car stream1))) 
     (else 
     (string-append 
      (number->string (stream-car stream1)) ", " 
      (print-first-n (stream-cdr stream1) (- n 1)))))) 

上述解決辦法是罰款的n一個很小的值,而是非常低效的大值(大量的臨時字符串將被創建,與O(n^2)複雜爲追加操作)。爲了更有效的實現,可以考慮使用SRFI-13的串聯程序,就像這樣:

(require srfi/13) 

(define (print-first-n stream1 n) 
    (let loop ((strm stream1) (n n) (acc '())) 
    (if (= n 1) 
     (string-concatenate-reverse 
     (cons (number->string (stream-car strm)) acc)) 
     (loop (stream-cdr strm) 
       (sub1 n) 
       (list* ", " (number->string (stream-car strm)) acc))))) 

無論哪種方式:讓我們說integers是起始於1整數的無限流,這是它會怎樣看:

(print-first-n integers 5) 
=> "1, 2, 3, 4, 5" 

如果流包含其他某種數據類型,請使用適當的過程將每個元素轉換爲字符串。

+0

是那個數字 - >字符串是用於將數字轉換爲字符串到字符串 – sageArt

+0

@sageArt:沒錯!如果您的流包含不同類型的元素,請查找並使用相應的過程將其轉換爲字符串。 –

+0

@ ChrisJester-Young夠公平的,我更新了我的答案:)。但'string-append'對於初學者來說更容易使用,它是構建字符串時自然遞歸的方式。如果效率問題,我同意你的看法。我想知道,使用'(apply string-append acc)'會沒問題,或者'string-concatenate'總是更好的選擇? –

2

如果功能只是打印流內容,並不需要建立一個字符串(如奧斯卡的答案),這是我對其採取(使用SRFI 41流):

(define (print-first-n stream n) 
    (stream-for-each (lambda (delim item) 
        (display delim) 
        (display item)) 
        (stream-cons "" (stream-constant ", ")) 
        (stream-take n stream))) 

例子:

> (define natural (stream-cons 1 (stream-map (lambda (x) (+ x 1)) natural))) 
> (print-first-n natural 10) 
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 

輸出到一個字符串(如奧斯卡的答案),只是包裝在一個字符串端口整個事情:

(define (print-first-n stream n) 
    (call-with-output-string 
    (lambda (out) 
    (stream-for-each (lambda (delim item) 
         (display delim out) 
         (display item out)) 
         (stream-cons "" (stream-constant ", ")) 
         (stream-take n stream)))))