[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

*To*: lisp-forum at MIT-MC*Subject*: LAMBDA syntax counter-proposal*From*: Guy.Steele at CMU-10A*Date*: Tue ,29 Sep 81 17:24:00 EDT

Here is another idea for a more "Lispy" LAMBDA-list syntax that some people here at CMU came up with. It is simpler to parse than &-syntax, but has all the power of &optional, &rest, and &aux. Moreover, it is more concise. It does not extend to other kinds of declaration. [0] A LAMBDA list is a (possibly dotted) list of specifiers, one for each non-rest parameter. [1] An atomic specifier names a required parameter. [2] A non-atomic specifier is of the form (<name> <init> <namep>). The second and third items may be omitted. This describes an optional parameter. [3] A non-() tail must be a symbol. It names a rest parameter. [4] (Optional rule.) All atomic specifiers must precede all non-atomic ones. [5] That's all. &aux variables are handled by the incredibly subtle dodge of using an embedded PROG or LET. Other declarations are handled another way, such as by local DECLARE forms. Here are some comparative examples of the use of this syntax. (DEFUN STRING-POSITION (CH STR (START 0) (END (STRING-LENGTH STR))) (DO ((J START (+ J 1))) ((= J END) ()) (WHEN (CHAR-EQUAL CH (CHAR STR J)) (RETURN J)))) (DEFUN STRING-POSITION (CH STR &OPTIONAL (START 0) (END (STRING-LENGTH STR))) (DO ((J START (+ J 1))) ((= J END) ()) (WHEN (CHAR-EQUAL CH (CHAR STR J)) (RETURN J)))) (DEFUN ASET (NEWVAL ARRAY . SUBSCRIPTS) (LET ((N (ARRAY-RANK ARRAY))) (DO ((J 0 (+ J 1)) (S SUBSCRIPTS (CDR S)) (LIN 0 (+ (* LIN (ARRAY-DIMENSION ARRAY J)) (CAR S)))) ((= J N) (IF (NULL S) (%LINEAR-ASET ARRAY LIN NEWVAL) (TOO-MANY-SUBSCRIPTS))) (IF (NULL S) (TOO-FEW-SUBSCRIPTS))))) (DEFUN ASET (NEWVAL ARRAY &REST SUBSCRIPTS &AUX (N (ARRAY-RANK ARRAY))) (DO ((J 0 (+ J 1)) (S SUBSCRIPTS (CDR S)) (LIN 0 (+ (* LIN (ARRAY-DIMENSION ARRAY J)) (CAR S)))) ((= J N) (IF (NULL S) (%LINEAR-ASET ARRAY LIN NEWVAL) (TOO-MANY-SUBSCRIPTS))) (IF (NULL S) (TOO-FEW-SUBSCRIPTS)))) This representation is very easy to parse, because each LAMBDA-list element corresponds to exactly one parameter. It is also always more concise, with two exceptions. The word &optional is simply omitted, and &rest is replaced by a dot. The word &aux is replaced by "(let (" and two close parentheses, and so is longer by three printing characters plus a bit of whitespace (excption #1). If there are many &optional parameters all defaulting to (), then "&optional x y z ..." must become "(x) (y) (z) ..."; this is less concise if there are more than five such parameters (exception #2). Omitting optional rule [4] permits optional parameters to precede required parameters. This has some limited usefulness: (DEFUN LOG ((BASE 10) NUM) (/ (LN NUM) (LN BASE))) (LOG 2) => 0.301... ;Log base 10 of 2 (LOG 16 2) => 0.25 ;Log base 16 of 2 (DEFUN TURBOPROP (SYM (NEWVAL () NEWP) PROP) ;Can do either GET or PUTPROP (IF NEWP (PUTPROP SYM NEWVAL PROP) (GET SYM PROP))) This idea has been mentioned before, of course. It has the disadvantage of requiring two-pass processing when binding parameters to arguments. I'd be inclined to retain rule [4]. --Guy

- Prev by Date:
**About &parsers** - Next by Date:
**P.S. to previous message (LAMBDA list counter-proposal)** - Previous by thread:
**rational arithmetic** - Next by thread:
**LAMBDA syntax counter-proposal** - Index(es):