This page is part of the web mail archives of SRFI 2 from before July 7th, 2015. The new archives for SRFI 2 contain all messages, not just those from before July 7th, 2015.
I like the idea of LAND*; I think I'd use a form like this often. The syntax proposed is clean and clear. Thank you, Oleg! However, the specification of LAND* in the draft SRFI is perhaps not as clear as it could be. I think it's important that the initial SRFI's set a high standard for future authors to follow, so I hope Oleg will not be offended if I explain how I think draft SRFI 2 might be improved. The notation used to describe the LAND* syntax is unfamiliar; it resembles BNF, but uses `cons' in a way I've never seen in any other BNF spec. Whenever possible, I think SRFI's should use existing, well-defined, and widely recognized notations for describing syntax; when that is not possible, the SRFI itself should explain the notation used. The notation used to describe LAND*'s semantics is also unfamiliar. I would suggest that SRFI's should imitate R5RS as closely as possible, when R5RS provides appropriate examples. In the present case, R5RS provides excellent precedents to follow. Thus, looking at how R5RS handles `cond', I would suggest a definition consisting of: - syntax, specified informally, using templates with English restrictions, - semantics, specified informally, in English, and - for derived expression types, a macro definition using R5RS's define-syntax. (Note that using R5RS macros does *not* constrain an implementation to provide LAND* using R5RS macros, or macros of any sort; R5RS macros are simply a well-defined, widely recognized notation for describing the syntax and semantics of expressions.) For example: Syntax: (land* (<clause> ...) <body> ...) Each <clause> should have one of the following forms: (<variable> <expression>) (<expression>) <bound-variable> Each <variable> or <bound-variable> should be an identifier. Each <expression> should be a valid expression. The <body> should be a possibly empty sequence of expressions, like the <body> of a lambda form. Semantics: A LAND* expression is evaluated by evaluating the <expression> or <bound-variable> of each of the <clause>s from left to right. The value of the first <expression> or <bound-variable> that evaluates to a false value is returned; the remaining <expression>s and <bound-variable>s are not evaluated. The <body> forms are evaluated iff all the <expression>s and <bound-variable>s evaluate to true values. The <expression>s and the <body> are evaluated in an environment binding each <variable> of the preceding (<variable> <expression>) clauses to the value of the <expression>. Later bindings shadow earlier bindings. (define-syntax land* (syntax-rules () ((land* () body ...) (begin body ...)) ((land* ((var expr) clauses ...) body ...) (let ((var expr)) (if var (land* (clauses ...) body ...) #f))) ((land* ((expr) clauses ...) body ...) (if expr (land* (clauses ...) body ...) #f)) ((land* (var clauses ...) body ...) (if var (land* (clauses ...) body ...) #f)))) (Note that the define-syntax definition above is untested.) Some further comments: I find the name `land*' a bit obscure; is it `logical and'? Or perhaps `dry land'? Something like `and-let*' might be nicer. I think we should follow the example of `set-car!', not `rplaca'. Isn't a <clause> of the form <bound-variable> equivalent to one of the form (<bound-variable>)? The fact that the list contains only one element shows that no binding should be created. Thus, <bound-variable> clauses seem unnecessary. I wouldn't mind writing (lambda (x y) (land* ((first (car x)) (y)) (do-something first))) instead of (lambda (x y) (land* ((first (car x)) y) (do-something first))) But this is not a big deal.