Scheme procedures with variable number of arguments
Monday, June 30th, 2008The pcall procedure has been rewritten to a cleaner form. Some repetitive expressions are now evaluated only once as a procedure argument, avoiding the use of set!. Some raw implementation details are still visible, as I don’t yet want to define or use a lot of procedures…
(pcall
(lambda (x)
(evapply (car x) (cdr x))
)
)
(evapply
(lambda (def args)
(cond
( (eq? (first def) prim-mark) (prim-call (second def) args) )
( (eq? (first def) proc-mark) (proc-call (cdr(cdr(cdr def))) (second def) (third def) args) )
( #t '***undefined*** )
)
)
)
(proc-call
(lambda (body env formals args)
(evseq '***undefined*** body (append (pair formals args) env))
)
)
(prim-call
(lambda (id args)
(cond
( (eq? id 'car) (car (first args)) )
( (eq? id 'cdr) (cdr (first args)) )
( (eq? id 'cons) (cons (first args) (second args)) )
; -- etc. --
( #t '***undefined*** )
)
)
)
I am still thinking about tail call optimization, and realizing the need to abstract/encapsulate the whole argument binding process. So pair becomes bind-args, and the binding of arguments and the extension of an environment becomes a combined function. However, instead of calling it pairlis, I call it add-args.
It turns out that adding the feature of variable number of procedure arguments is easy. One extra test in bind-args is all that’s needed to handle both Scheme syntaxes for this feature. In case you’re not familiar with Scheme syntax, the two syntaxes are…
; z (which can be any identifier) receives the tail of the evaluated argument list ( lambda z <body> ) ; no required arguments ( lambda ( <sequence of identifiers> . z ) <body> ) ; the arguments before "." are required
After looking at my assembly code, it looks like it can be added to the base interpreter without a lot of hassle. So here is the little Scheme code with renamed procedures and the handling of variable length argument lists. (Well, almost. Due to the implementation of (car ′()) and (cdr ′()), required arguments are not enforced anywhere.)…
(proc-call
(lambda (body env formals args)
(evseq '***undefined*** body (add-args formals args env))
)
)
(add-args
(lambda (formals args env)
(append (bind-args formals args) env)
)
)
(bind-args
(lambda (x y)
(cond
( (null? x) '() )
( (symbol? x) (cons (cons x y) '()) )
( #t (cons (cons (car x) (car y)) (bind-args (cdr x) (cdr y))) )
)
)
)