From f4138971962eba6a8dd94d7ddc1028e187aee41b Mon Sep 17 00:00:00 2001 From: Steve Youngs Date: Mon, 6 Jul 2015 17:18:18 +1000 Subject: [PATCH] Update the docstrings in the cl emodule. This adds/updates the docstrings for the DEFUNs in the cl emodule. I've basically just lifted the doctrings from the equivalent functions/macros in cl*.el. * modules/cl/cl-loop.c (Fcl_loop): Add a docstring. (Fcl_doX): Typo in docstring. (Fcl_dotimes): Update docstring. (Fcl_dolist): Ditto. (Fcl_do_symbols): Ditto. (Fcl_loop_sentence): Direct folks to #'cl:loop docstring. * modules/cl/cl.c (Fcl_pop): Add a docstring. (Fcl_push): Ditto. (Fcl_pushnew): Ditto. (Fcl_eql): Ditto. (Fcl_list_): Ditto. (Fcl_tailp): Ditto. (Fcl_ldiff): Ditto. Signed-off-by: Steve Youngs --- modules/cl/cl-loop.c | 301 +++++++++++++++++++++++++++++++++++++++++-- modules/cl/cl.c | 35 ++++- 2 files changed, 321 insertions(+), 15 deletions(-) diff --git a/modules/cl/cl-loop.c b/modules/cl/cl-loop.c index a59d7d8..a423972 100644 --- a/modules/cl/cl-loop.c +++ b/modules/cl/cl-loop.c @@ -1572,8 +1572,9 @@ cl_loop_perform(cl_loop_sentence_t *lsen) /* ###autoload */ DEFUN("cl:loop-sentence", Fcl_loop_sentence, 0, UNEVALLED, 0, /* -The Common Lisp loop macro. -*/ +Part of The Common Lisp loop macro. +See: `cl:loop' + */ (args)) { Lisp_Object loop_sentence = cl_loop_make_sentence(); @@ -1611,8 +1612,281 @@ Execute LOOP-SENTENCE. } DEFUN("cl:loop", Fcl_loop, 0, UNEVALLED, 0, /* -The Common Lisp loop macro. -*/ +(loop CLAUSE...): The Common Lisp loop macro. + +Overview of valid clauses: + for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, + for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, + for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, + always COND, never COND, thereis COND, collect EXPR into VAR, + append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, + count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, + if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, + finally return EXPR, named NAME. + +The loop macro consists of a series of clauses, which do things like +iterate variables, set conditions for exiting the loop, accumulating values +to be returned as the return value of the loop, and executing arbitrary +blocks of code. Each clause is proceed in turn, and the loop executes its +body repeatedly until an exit condition is hit. + +It's important to understand that loop clauses such as `for' and `while', +which look like loop-establishing constructs, don't actually *establish* a +loop; the looping is established by the `loop' clause itself, which will +repeatedly process its body until told to stop. `while' merely establishes +a condition which, when true, causes the loop to finish, and `for' sets a +variable to different values on each iteration (e.g. successive elements of +a list) and sets an exit condition when there are no more values. This +means, for example, that if two `for' clauses appear, you don't get two +nested loops, but instead two variables that are stepped in parallel, and +two exit conditions, either of which, if triggered, will cause the loop to +end. Similarly for a loop with a `for' and a `while' clause. For example: + +(loop + for x in list + while x + do ...) + +In each successive iteration, X is set to the next element of the list. If +there are no more elements, or if any element is nil (the `while' clause), +the loop exits. Otherwise, the block of code following `do' is executed.) + +This example also shows that some clauses establish variable bindings -- +essentially like a `let' binding -- and that following clauses can +reference these variables. Furthermore, the entire loop is surrounded by a +block named nil (unless the `named' clause is given), so you can return +from the loop using the macro `return'. (The other way to exit the loop is +through the macro `loop-finish'. The difference is that some loop clauses +establish or accumulate a value to be returned, and `loop-finish' returns +this. `return', however, can only return an explicitly-specified value. +NOTE CAREFULLY: There is a loop clause called `return' as well as a +standard Lisp macro called `return'. Normally they work similarly; but if +you give the loop a name with `named', you will need to use the macro +`return-from'.) + +Another extremely useful feature of loops is called "destructuring". If, +in place of VAR, a list (possibly dotted, possibly a tree of arbitary +complexity) is given, the value to be assigned is assumed to have a similar +structure to the list given, and variables in the list will be matched up +with corresponding elements in the structure. For example: + +(loop + for (x y) in '((foo 1) (bar 2) (baz 3)) + do (puthash x y some-hash-table)) + +will add three elements to a hash table, mapping foo -> 1, bar -> 2, and +baz -> 3. As other examples, you can conveniently process alists using + +(loop for (x . y) in alist do ...) + +and plists using + +(loop for (x y) on plist by #'cddr do ...) + +Destructuring is forgiving in that mismatches in the number of elements on +either size will be handled gracefully, either by ignoring or initializing +to nil. + +If you don't understand how a particular loop clause works, create an +example and use `macroexpand-sexp' to expand the macro. + +In greater detail, valid clauses are: + +(NOTE: Keywords in lowercase; slashes separate different possibilities +for keywords, some of which are synonymous; brackets indicate optional +parts of the clause. In all of the clauses with `being', the word `being', +the words `each' or `the', and the difference between singular and plural +keywords are all just syntactic sugar. Stylistically, you should write +either `being each foo' or `being the foos'.) + + for VAR from/upfrom/downfrom NUM1 to/upto/downto/above/below NUM2 [by NUMSTEP] + Step VAR across numbers. `upfrom', `upto', and `below' explicitly + indicate upward stepping; `downfrom', `downto', and `above' explicitly + indicate downward stepping. (If none of these is given, the default is + upward.) `to', `upto', and `downto' cause stepping to include NUM2 as + the last iteration, while `above' and `below' stop just before reaching + NUM2. `by' can be given to indicate a stepping increment other than 1. + + for VAR in LIST [by FUNC] + Step VAR over elements of a LIST. FUNC specifies how to get successive + sublists and defaults to `cdr'. + + for VAR on LIST [by FUNC] + Step VAR over tails of a LIST. FUNC specifies how to get successive + sublists and defaults to `cdr'. + + for VAR in-ref LIST [by FUNC] + Step VAR over elements of a LIST, like `for ... in', except the VAR is + bound using `symbol-macrolet' instead of `let'. In essence, VAR is set + to a "reference" to the list element instead of the element itself; + this us, you can destructively modify the list using `setf' on VAR, and + any changes to the list will "magically" reflect themselves in + subsequent uses of VAR. + + for VAR = INIT [then EXPR] + Set VAR on each iteration of the loop. If only INIT is given, use it + on each iteration. Otherwise, use INIT on the first iteration and EXPR + on subsequent ones. + + for VAR across/across-ref ARRAY + Step VAR across a sequence other than a list (string, vector, bit + vector). If `across-ref' is given, VAR is bound using + `symbol-macrolet' instead of `let' -- see above. + + for VAR being each/the element/elements in/of/in-ref/of-ref SEQUENCE [using (index INDEX-VAR)] + Step VAR across any sequence. A variable can be specified with a + `using' phrase to receive the index, starting at 0. If `in-ref' or + `of-ref' is given, VAR is bound using `symbol-macrolet' instead of + `let' -- see above. + + for VAR being each/the hash-key/hash-keys/hash-value/hash-values in/of HASH-TABLE [using (hash-value/hash-key OTHER-VAR)] + + for VAR being each/the hash-key/hash-keys/hash-value/hash-values in/of HASH-TABLE [using (hash-value/hash-key OTHER-VAR)] + Map VAR over a hash table. The various keywords are synonymous except + those that distinguish between keys and values. The `using' phrase is + optional and allows both key and value to be bound. + + for VAR being each/the symbol/present-symbol/external-symbol/symbols/present-symbols/external-symbols in/of OBARRAY + Map VAR over the symbols in an obarray. All symbol keywords are + currently synonymous. + + for VAR being each/the extent/extents [in/of BUFFER-OR-STRING] [from POS] [to POS] + Map VAR over the extents in a buffer or string, defaulting to the + current buffer, the beginning and the end, respectively. + + for VAR being each/the interval/intervals [in/of BUFFER-OR-STRING] [property PROPERTY] [from POS] [to POS] + Map VAR over the intervals without property change in a buffer or + string, defaulting to the current buffer, the beginning and the end, + respectively. If PROPERTY is given, iteration occurs using + `next-single-property-change'; otherwise, using + `next-property-change'. + + for VAR being each/the window/windows [in/of FRAME] + Step VAR over the windows in FRAME, defaulting to the selected frame. + + for VAR being each/the frame/frames + Step VAR over all frames. + + for VAR being each/the buffer/buffers [by FUNC] + Step VAR over all buffers. This is actually equivalent to + `for VAR in (buffer-list) [by FUNC]'. + + for VAR being each/the key-code/key-codes/key-seq/key-seqs/key-binding/key-bindings in KEYMAP [using (key-code/key-codes/key-seq/key-seqs/key-binding/key-bindings OTHER-VAR)] + Map VAR over the entries in a keymap. Keyword `key-seq' causes + recursive mapping over prefix keymaps occurring in the keymap, with VAR + getting the built-up sequence (a vector). Otherwise, mapping does not + occur recursively. `key-code' and `key-seq' refer to what is bound + (second argument of `define-key'), and `key-binding' what it's bound to + (third argument of `define-key'). + + as VAR ... + `as' is a synonym for `for'. + + and VAR ... + `and' clauses have the same syntax as `for' clauses except that the + variables in the clause are bound in parallel with a preceding + `and'/`for' clause instead of in series. + + with VAR = INIT + Set VAR to INIT once, before doing any iterations. + + repeat NUM + Exit the loop if more than NUM iterations have occurred. + + while COND + Exit the loop if COND isn't true. + + until COND + Exit the loop if COND is true. + + collect EXPR [into VAR] + Push EXPR onto the end of a list of values -- stored either in VAR or a + temporary variable that will be returned as the return value of the + loop if it terminates through an exit condition or a call to + `loop-finish'. + + append EXPR [into VAR] + Append EXPR (a list) onto the end of a list of values, like `collect'. + + nconc EXPR [into VAR] + Nconc EXPR (a list) onto the end of a list of values, like `collect'. + + concat EXPR [into VAR] + Concatenate EXPR (a string) onto the end of a string of values, like + `collect'. + + vconcat EXPR [into VAR] + Concatenate EXPR (a vector) onto the end of a vector of values, like + `collect'. + + bvconcat EXPR [into VAR] + Concatenate EXPR (a bit vector) onto the end of a bit vector of values, + like `collect'. + + sum EXPR [into VAR] + Add EXPR to a value, like `collect'. + + count EXPR [into VAR] + If EXPR is true, increment a value by 1, like `collect'. + + maximize EXPR [into VAR] + IF EXPR is greater than a value, replace the value with EXPR, like + `collect'. + + minimize EXPR [into VAR] + IF EXPR is less than a value, replace the value with EXPR, like + `collect'. + + always COND + If COND is true, continue the loop and set the loop return value (the + same value that's manipulated by `collect' and friends and is returned + by a normal loop exit or an exit using `loop-finish') to t; otherwise, + exit the loop and return nil. The effect is to determine and return + whether a condition is true "always" (all iterations of the loop). + + never COND + If COND is false, continue the loop and set the loop return value (like + `always') to t; otherwise, exit the loop and return nil. The effect + is to determine and return whether a condition is "never" true (all + iterations of the loop). + + thereis COND + If COND is true, exit the loop and return COND. + + if/when COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...] + If COND is true, execute the directly following clause(s); otherwise, + execute the clauses following `else'. + + unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...] + If COND is false, execute the directly following clause(s); otherwise, execute the clauses following `else'. + + do EXPRS... + Execute the expressions (any Lisp forms). + + initially EXPRS... + Execute EXPR once, before doing any iterations, and after values have + been set using `with'. + + finally EXPRS... + Execute EXPR once, directly before the loop terminates. This will not + be executed if the loop terminates prematurely as a result of `always', + `never', `thereis', or `return'. + + return EXPR + Exit from the loop and return EXPR. + + finally return EXPR + Specify the value to be returned when the loop exits. (Unlike `return', + this doesn't cause the loop to immediately exit; it will exit whenever + it normally would have.) This takes precedence over a return value + specified with `collect' and friends or `always' and friends. + + named NAME + Specify the name for block surrounding the loop, in place of nil. + (See `block'.) + */ (args)) { Lisp_Object loop_sentence = Qnil; @@ -1673,7 +1947,7 @@ Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...) /* ###autoload */ DEFUN("cl:do*", Fcl_doX, 2, UNEVALLED, 0, /* -The Common Lisp `do' loop. +The Common Lisp `do*' loop. Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...) */ (args)) @@ -1706,10 +1980,15 @@ Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...) /* ###autoload */ + DEFUN("cl:dotimes", Fcl_dotimes, 1, UNEVALLED, 0, /* The Common Lisp `dotimes' loop. Format is: (dotimes (VAR COUNT [RESULT]) BODY...) -*/ + +Loop a certain number of times. Evaluate BODY with VAR bound to +successive integers from 0, inclusive,to COUNT, exclusive. Then +evaluate RESULT to get return value, default nil. + */ (args)) { /* This function can GC */ @@ -1751,7 +2030,10 @@ Format is: (dotimes (VAR COUNT [RESULT]) BODY...) DEFUN("cl:dolist", Fcl_dolist, 1, UNEVALLED, 0, /* The Common Lisp `dolist' loop. Format is: (dolist (VAR LIST [RESULT]) BODY...) -*/ +loop over a list. +Evaluate BODY with VAR bound to each `car' from LIST, in turn. +Then evaluate RESULT to get return value, default nil. + */ (args)) { /* This function can GC */ @@ -1801,7 +2083,10 @@ extern Lisp_Object check_obarray(Lisp_Object obarray); DEFUN("cl:do-symbols", Fcl_do_symbols, 1, UNEVALLED, 0, /* The Common Lisp `dolist' loop. Format is: (do-symbols (VAR [OBARRAY [RESULT]]) BODY...) -*/ +loop over all symbols. +Evaluate BODY with VAR bound to each interned symbol, or to each symbol +from OBARRAY. + */ (args)) { /* This function can GC */ diff --git a/modules/cl/cl.c b/modules/cl/cl.c index e881780..3750696 100644 --- a/modules/cl/cl.c +++ b/modules/cl/cl.c @@ -59,7 +59,11 @@ PROVIDE(cl); /* ###autoload */ DEFUN("cl:pop", Fcl_pop, 1, UNEVALLED, 0, /* -*/ +(pop PLACE): remove and return the head of the list stored in PLACE. +Analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))), though more +careful about evaluating each argument only once and in the right order. +PLACE may be a symbol, or any generalized variable allowed by `setf'. + */ (args)) { /* This function can GC */ @@ -84,7 +88,13 @@ DEFUN("cl:pop", Fcl_pop, 1, UNEVALLED, 0, /* /* ###autoload */ DEFUN("cl:push", Fcl_push, 2, UNEVALLED, 0, /* -*/ +(push X PLACE): insert X at the head of the list stored in PLACE. +Analogous to (setf PLACE (cons X PLACE)), though more careful about +evaluating each argument only once and in the right order. PLACE may +be a symbol, or any generalized variable allowed by `setf'; that is, +it does not necessarily have to be a list, though `push' is most often +used on lists. + */ (args)) { /* This function can GC */ @@ -108,7 +118,11 @@ DEFUN("cl:push", Fcl_push, 2, UNEVALLED, 0, /* /* ###autoload */ DEFUN("cl:pushnew", Fcl_pushnew, 2, UNEVALLED, 0, /* -*/ +(pushnew X PLACE): insert X at the head of the list stored in PLACE. +Like (push X PLACE), except that the list is unmodified if X is `eql' +to an element already on the list. +Keywords supported: :test :test-not :key + */ (args)) { /* This function can GC */ @@ -142,7 +156,9 @@ int emodcl_eql(Lisp_Object a, Lisp_Object b) /* ###autoload */ DEFUN("cl:eql", Fcl_eql, 2, 2, 0, /* -*/ +Return t if the two args are the same Lisp object. +Floating-point numbers of equal value are `eql', but they may not be `eq'. + */ (a, b)) { if (EMOD_CL_EQL(a, b)) @@ -153,7 +169,10 @@ DEFUN("cl:eql", Fcl_eql, 2, 2, 0, /* /* ###autoload */ DEFUN("cl:list*", Fcl_list_, 1, MANY, 0, /* -*/ +Return a new list with specified args as elements, cons'd to last arg. +Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to +`(cons A (cons B (cons C D)))'. + */ (int nargs, Lisp_Object *args)) { if (nargs == 1) @@ -169,7 +188,8 @@ DEFUN("cl:list*", Fcl_list_, 1, MANY, 0, /* /* ###autoload */ DEFUN("cl:tailp", Fcl_tailp, 2, 2, 0, /* -*/ +Return true if SUBLIST is a tail of LIST. + */ (list, object)) { Lisp_Object trav1 = Qnil, trav2 = Qnil; @@ -209,7 +229,8 @@ DEFUN("cl:tailp", Fcl_tailp, 2, 2, 0, /* /* ###autoload */ DEFUN("cl:ldiff", Fcl_ldiff, 2, 2, 0, /* -*/ +Return a copy of LIST with the tail SUBLIST removed. + */ (list, object)) { Lisp_Object result = Qnil, tmp1 = Qnil, tmp2 = Qnil; -- 2.34.1