Scheme is a programming language: if you don't have a procedure you need you can usually write one.
In this case I don't know what the arguments to writeln
should be but I am going to say they should be
- the destination;
- and any number of things to write.
The way to specify this kind of argument list in Scheme is either (lambda things ...)
or, if there are a fixed number of initial arguments followed by a 'rest' argument then (lambda (thing1 thing2 ... thingn . things) ...)
. The equivalent fancy define
syntax is (define (f thing1 thing2 ... . things) ...)
.
So:
(define (writeln to . things)
...)
what does the body look like? Well, there are two cases:
- if
things
is empty, write a newline and stop;
- if
things
is not, display
the first thing and then write the rest of the things.
Well, there's a classic 'impedence match' problem here: I'd like to use writeln
to write the rest of the things but the way I've specified it it takes a variable number of arguments, not a list of things. You can use apply
to get around this but that's horrible: a better approach is a little auxiliary function. The natural way to specify that here is named let
: (let name (...) ...)
defines name
as a procedure which can be called within its body.
So, here is the final thing:
(define (writeln to . things)
(let write-things ((remaining things))
(if (null? remaining)
(newline to)
(begin
(display (car remaining) to)
(write-things (cdr remaining))))))
And
> (writeln (current-output-port) 1 " " 2 " " 3)
1 2 3
This should work in R5RS Schemes but I have only tested it in Racket's R5RS language.