Skip to content

Instantly share code, notes, and snippets.

@ktakashi
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ktakashi/7fa25f74189a8af509dc to your computer and use it in GitHub Desktop.
Save ktakashi/7fa25f74189a8af509dc to your computer and use it in GitHub Desktop.
Returning value of custom binary output port
#!r6rs
(import (rnrs))
(define (print . args) (for-each display args) (newline))
(define (make-predefined-buffer-output-port buf)
(define left (bytevector-length buf))
(define index 0)
(define (write! bv start count)
(cond ((zero? left) 0)
((> count left)
(let ((size left))
(bytevector-copy! bv start buf index size)
(set! index (+ index left))
(set! left 0)
size))
(else
(bytevector-copy! bv start buf index count)
(set! index (+ index count))
(set! left (- left count))
count)))
(define (close!) #t)
(define (get-position) index)
(make-custom-binary-output-port "predefined buffer port"
write! get-position #f close!))
(define buf (make-bytevector 1))
(define out (make-predefined-buffer-output-port buf))
(print (put-bytevector out #vu8(1 2 3)))
(flush-output-port out)
(print buf)
(flush-output-port (current-output-port))
#|
;; Updated to support port-position
- Mosh and Sagittarius print #vu8(1)
- Vicare went into inifinite loop
- Racket (v6.1.1) raised an error (even port-position is supported)
- Guile also goes to infinte loop (picked up from the comment)
|#
@wingo
Copy link

wingo commented Mar 6, 2015

Guile goes into an infinite loop too

@leppie
Copy link

leppie commented Mar 6, 2015

I guess it is up to the implementation how hard it tries to write all the bytes. write! does not have to write everything it is asked to write, it just needs to return the actual amount of bytes written. In IronScheme (which prints #vu8(1) too), the call is just using .NET's Stream.Write(...).

Raising an error seems wrong though.

@weinholt
Copy link

weinholt commented Mar 6, 2015

leppie: This does seem to be up to the implementation. But if you print #vu8(1), then what happened to the rest of the data? You apparently have data loss. On that basis it seems better to raise an exception.

@leppie
Copy link

leppie commented Mar 9, 2015

weinholt: I thought about it too, perhaps put-XXX should have been defined more specifically. Strictly speaking, an error should be the most desirable behavior. Getting stuck in an infinite loop seems bad though :) I will try implement put-XXX to behave, alternatively, get them to return the actual number of bytes/characters written.

@leppie
Copy link

leppie commented Mar 9, 2015

Here is my final take on this:

Scenario: In the case where not bytes written is less than count.

If get-position is #f, then an error should be raised like it does with Racket.

If get-position is not #f, the procedure calling write! should check if get-position has advanced the same amount as the value returned from write!. If not, raise an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment