Re: Making the new let easier to stomach
Andy Gaynor 12 Feb 1999 00:01 UTC
xxxxxx@Informatik.Uni-Tuebingen.De (Michael Sperber [Mr. Preprocessor]) writes:
> - You're essentially arguing for replacing R5RS let with the one you propose.
> This is totally valid.
>
> As it SRFI, your proposal is still only a suggestion for an addition to the
> language. Why not rename it to something other than let?
I proposed SRFI-5 specifically to patch two little holes that I perceived in
the R5RS let form, inconsistencies with respect to other R5RS features. I like
to think that these little holes are oversights that would have been corrected
at the time the named-let and signature-style define features were introduced,
had they been noticed. Providing the functionality of SRFI-5's let form under
a different name would defeat much of the reason why it was submitted.
> This would also make it easier to use for people dealing with legacy code.
SRFI-5 is backward-compatible with R5RS's let and uses only one syntactic
extension (symbols in the binding list) to implement its two new facets. How
serious can a legacy problem be?
> - Is there a way to define the construct using standard R5RS macros rather
> than explicit renaming (which is only supported by one or two Scheme
> systems)?
Heh heh, R5RS template-style macros? See bottom. I wouldn't be surprised if
a template wizard were able to optimize it a bit, so I'd appreciate it if
someone gave it a sound thrashing. Not heavily tested, but it appears to work.
Regards, [Ag] Andy Gaynor xxxxxx@mail.webspan.net
_______________________________________________________________________________
(define-syntax let
(syntax-rules ()
;; In the (let 0 name normals rest arguments body bindings) form:
;; name: The name to assign to the lambda, or #f if none.
;; normals: The normal parameters of the lambda.
;; rest: The rest parameter for the lambda, or () if none.
;; Using () saves a rule for (normal ... . rest).
;; arguments: The arguments to the lambda.
;; body: The body of the lambda.
;; bindings: Bindings remaining to be processed.
;; Terminating cases
;; No name, use an anonymous lambda call
((let 0 #f (normal ...) rest arguments body ())
((lambda (normal ... . rest) . body) . arguments))
;; Name, use a letrec and call
((let 0 name (normal ...) rest arguments body ())
(letrec ((name (lambda (normal ... . rest) . body))) (name . arguments)))
;; Deconstructing bindings
;; Shuffle a normal binding
((let 0 name (normal ...) () (argument ...) body ((variable value) . bindings))
(let 0 name (normal ... variable) () (argument ... value) body bindings))
;; Shuffle a rest binding (its values are shuffled below)
((let 0 name normals () arguments body (rest-variable . rest-values))
(let 0 name normals rest-variable arguments body rest-values))
;; Shuffle a rest value
((let 0 name normals rest (argument ...) body (rest-value . rest-values))
(let 0 name normals rest (argument ... rest-value) body rest-values))
;; Top-level interface
;; Straight let, no bindings
((let () . body)
(let 0 #f () () () body ()))
;; Straight let, bindings
((let ((variable value) . bindings) . body)
(let 0 #f (variable) () (value) body bindings))
;; Signature-style named let
((let (name . bindings) . body)
(let 0 name () () () body bindings))
;; Non-signature-style named let
((let name bindings . body)
(let 0 name () () () body bindings))))