diff --git a/CHANGELOG.md b/CHANGELOG.md index cbb52553..70def5b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,23 @@ This document describes the user-facing changes to Loopy. simplify the code and remove an inconsistency between them and the other commands. +- `:result-type` is deprecated. This feature was taken from Common Lisp's + Iterate. While useful, this can be done more directly using named + accumulation variables (such as `loopy-result`) in special macro arguments, + such as `finally-return`. Because of `accum-opt`, using named variables is + more flexible, + + ```elisp + ;; Can't be done using only `:result-type'. + ;; => ([2 4 6] [3 6 9]) + (loopy (accum-opt doubles triples) + (list i '(1 2 3)) + (collect doubles (* i 2)) + (collect triples (* i 3)) + (finally-return (cl-coerce doubles 'vector) + (cl-coerce triples 'vector))) + ``` + ### Command Improvements - To produce faster code, some commands now avoid creating an intermediate diff --git a/README.org b/README.org index 3d5e90a1..a0de6fd6 100644 --- a/README.org +++ b/README.org @@ -44,6 +44,8 @@ please let me know. more like accumulation commands, such as =(always [VAR] VAL &key into)=. This will simplify the code and remove an inconsistency between them and the other commands. + - =:result-type= is deprecated. Instead, use coercion functions in + special macro arguments, possibly with =accum-opt=. - Versions 0.11.1 and 0.11.2: None. Bug fixes. - Version 0.11.0: - More incorrect destructured bindings now correctly signal an error. diff --git a/doc/loopy-doc.org b/doc/loopy-doc.org index 9b08d33b..02ec699b 100644 --- a/doc/loopy-doc.org +++ b/doc/loopy-doc.org @@ -2280,15 +2280,6 @@ all described below. - =init= :: The initial value of =VAR=. For explicitly named variables, one can use this argument or the =with= special macro argument. -#+cindex: accumulation keyword result-type -- =result-type= :: A sequence type into which =VAR= is converted /after the - loop is over/. These types need not be quoted. For example, ='vector= and - =vector= are both valid ways to specify the vector data type. Commands using - the same variable must use the same type coercion. - - This argument can be more convenient than writing out a call to ~cl-coerce~ - or ~seq-into~. - The arguments to the =test= and =key= parameters can be quoted functions or variables, just like when using ~cl-union~, ~cl-adjoin~, and so on. ~loopy~ knows how to expand efficiently for either case. @@ -2521,7 +2512,7 @@ Sequence accumulation commands are used to join lists (such as =union= and #+findex: adjoin #+findex: adjoining -- =(adjoin VAR EXPR &key at test key init result-type)= :: Repeatedly add =EXPR= +- =(adjoin VAR EXPR &key at test key init)= :: Repeatedly add =EXPR= to =VAR= if it is not already present in the list. This command also has the alias =adjoining=. @@ -2548,14 +2539,14 @@ Sequence accumulation commands are used to join lists (such as =union= and ;; Coerced to a vector /after/ the loop ends. ;; => [1 2 3 4] (loopy (list i '(1 2 3 3 4)) - (adjoin my-var i :result-type 'vector) + (adjoin my-var i) (when (vectorp my-var) (return 'is-vector)) (finally-return my-var)) ;; => [4 3 2 1] (loopy (list i '(1 2 3 3 4)) - (adjoin my-var i :result-type 'vector :at 'start) + (adjoin my-var i :at 'start) (finally-return my-var)) #+end_src @@ -2579,7 +2570,7 @@ Sequence accumulation commands are used to join lists (such as =union= and #+findex: collect #+findex: collecting -- =(collect VAR EXPR &key result-type at)= :: Collect the value of =EXPR= into +- =(collect VAR EXPR &key at)= :: Collect the value of =EXPR= into the list =VAR=. By default, elements are added to the end of the list. This command also has the alias =collecting=. @@ -2618,9 +2609,7 @@ Sequence accumulation commands are used to join lists (such as =union= and This command also has the alias =concating=. - =VAR= is a string throughout the loop. This differs from the behavior of - commands with the keyword argument =result-type=, which coerces the resulting - sequence of accumulated values into a new type /after/ the loop completes. + =VAR= is a string throughout the loop. #+BEGIN_SRC emacs-lisp ;; => "abc" @@ -2783,10 +2772,7 @@ Sequence accumulation commands are used to join lists (such as =union= and This command also has the alias =vconcating=. - =VAR= is a vector throughout the loop. This differs from the behavior of - commands with the keyword argument =result-type=, which coerces the - resulting sequence of accumulated values into a new type /after/ the loop - completes. + =VAR= is a vector throughout the loop. #+BEGIN_SRC emacs-lisp ;; => [1 2 3 4 5 6] @@ -4340,16 +4326,14 @@ For accumulation commands, you might also wish to place values in the following: commands need to update the variable one final time after ending the loop. Some examples are: 1. Correcting the order of elements in a list that was constructed in reverse. - 2. Coercing the variable into a new sequence type, for commands with the - ~:result-type~ argument. + 2. Coercing the variable into a new sequence type. + 3. Appending a list of lists. Each accumulation variable can only be updated once, in a single way. For example, a variable cannot be reversed according to the needs of one command and then coerced into a new type according to the needs of another. Commands acting on the same accumulation variable must require the same final update, - including if they require no final update. For example, a command that uses - =:result-type= to coerce ~loopy-result~ into a vector is incompatible with a - command that does not require (and so does not expect) a final update. + including if they require no final update. Loopy will attempt to produce efficient code, and will not attempt to set up diff --git a/doc/loopy.texi b/doc/loopy.texi index 8647c435..ee1fd59f 100644 --- a/doc/loopy.texi +++ b/doc/loopy.texi @@ -688,7 +688,7 @@ You should keep in mind that commands are evaluated in order. This means that attempting to do something like the below example might not do what you expect, as @samp{i} is assigned a value from the list after collecting @samp{i} into @samp{coll}. -@float Listing,org09f2c80 +@float Listing,orgd0ad0bd @lisp ;; => (nil 1 2) (loopy (collect coll i) @@ -810,7 +810,7 @@ the flag @samp{dash} provided by the package @samp{loopy-dash}. Below are two examples of destructuring in @code{cl-loop} and @code{loopy}. -@float Listing,org1a7fe46 +@float Listing,orgb08dfe3 @lisp ;; => (1 2 3 4) (cl-loop for (i . j) in '((1 . 2) (3 . 4)) @@ -825,7 +825,7 @@ Below are two examples of destructuring in @code{cl-loop} and @code{loopy}. @caption{Destructuring values in a list.} @end float -@float Listing,orgbe30df0 +@float Listing,orgfadf3de @lisp ;; => (1 2 3 4) (cl-loop for elem in '((1 . 2) (3 . 4)) @@ -2454,18 +2454,6 @@ The initial value of @samp{VAR}. For explicitly named variables, one can use this argument or the @samp{with} special macro argument. @end table -@cindex accumulation keyword result-type -@table @asis -@item @samp{result-type} -A sequence type into which @samp{VAR} is converted @emph{after the -loop is over}. These types need not be quoted. For example, @samp{'vector} and -@samp{vector} are both valid ways to specify the vector data type. Commands using -the same variable must use the same type coercion. - -This argument can be more convenient than writing out a call to @code{cl-coerce} -or @code{seq-into}. -@end table - The arguments to the @samp{test} and @samp{key} parameters can be quoted functions or variables, just like when using @code{cl-union}, @code{cl-adjoin}, and so on. @code{loopy} knows how to expand efficiently for either case. @@ -2714,7 +2702,7 @@ Sequence accumulation commands are used to join lists (such as @samp{union} and @findex adjoin @findex adjoining @table @asis -@item @samp{(adjoin VAR EXPR &key at test key init result-type)} +@item @samp{(adjoin VAR EXPR &key at test key init)} Repeatedly add @samp{EXPR} to @samp{VAR} if it is not already present in the list. @@ -2742,14 +2730,14 @@ This command also has the alias @samp{adjoining}. ;; Coerced to a vector /after/ the loop ends. ;; => [1 2 3 4] (loopy (list i '(1 2 3 3 4)) - (adjoin my-var i :result-type 'vector) + (adjoin my-var i) (when (vectorp my-var) (return 'is-vector)) (finally-return my-var)) ;; => [4 3 2 1] (loopy (list i '(1 2 3 3 4)) - (adjoin my-var i :result-type 'vector :at 'start) + (adjoin my-var i :at 'start) (finally-return my-var)) @end lisp @end table @@ -2778,7 +2766,7 @@ This command also has the alias @samp{appending}. @findex collect @findex collecting @table @asis -@item @samp{(collect VAR EXPR &key result-type at)} +@item @samp{(collect VAR EXPR &key at)} Collect the value of @samp{EXPR} into the list @samp{VAR}. By default, elements are added to the end of the list. @@ -2821,9 +2809,7 @@ Repeatedly @code{concat} the value of @samp{EXPR} onto This command also has the alias @samp{concating}. -@samp{VAR} is a string throughout the loop. This differs from the behavior of -commands with the keyword argument @samp{result-type}, which coerces the resulting -sequence of accumulated values into a new type @emph{after} the loop completes. +@samp{VAR} is a string throughout the loop. @lisp ;; => "abc" @@ -3004,10 +2990,7 @@ command @samp{concat}. This command also has the alias @samp{vconcating}. -@samp{VAR} is a vector throughout the loop. This differs from the behavior of -commands with the keyword argument @samp{result-type}, which coerces the -resulting sequence of accumulated values into a new type @emph{after} the loop -completes. +@samp{VAR} is a vector throughout the loop. @lisp ;; => [1 2 3 4 5 6] @@ -4008,7 +3991,7 @@ using the @code{let*} special form. This method recognizes all commands and their aliases in the user option @code{loopy-aliases}. -@float Listing,orgd37df25 +@float Listing,org1d6cd86 @lisp ;; => ((1 2 3) (-3 -2 -1) (0)) (loopy-iter (arg accum-opt positives negatives other) @@ -4841,17 +4824,16 @@ Some examples are: @item Correcting the order of elements in a list that was constructed in reverse. @item -Coercing the variable into a new sequence type, for commands with the -@code{:result-type} argument. +Coercing the variable into a new sequence type. +@item +Appending a list of lists. @end enumerate Each accumulation variable can only be updated once, in a single way. For example, a variable cannot be reversed according to the needs of one command and then coerced into a new type according to the needs of another. Commands acting on the same accumulation variable must require the same final update, -including if they require no final update. For example, a command that uses -@samp{:result-type} to coerce @code{loopy-result} into a vector is incompatible with a -command that does not require (and so does not expect) a final update. +including if they require no final update. @end table diff --git a/loopy-commands.el b/loopy-commands.el index e8817fe0..8582db6f 100644 --- a/loopy-commands.el +++ b/loopy-commands.el @@ -1691,7 +1691,16 @@ you can use in the instructions: (setq opts cons-cell args (nreverse args-holding)) (setq args parser-args))) + (ignore args opts) + + (when (plist-member opts :result-type) + (warn "Loopy: `%s': Use of `:result-type' is deprecated. +Instead, use a coercing function like `seq-into' in a special +macro argument, such as `finally-return'. See also `accum-opt' at the Info node +`(loopy)Optimizing Accumulations'." + name)) + (let ((arg-length (length args))) (cond ((= arg-length ,implicit-num-args) @@ -1861,9 +1870,9 @@ RESULT-TYPE can be used to `cl-coerce' the return value." (loopy--update-accum-place-count loopy--loop-name var pos) `((loopy--main-body (loopy--optimized-accum '( :cmd ,cmd :name ,name - :var ,var :val ,val - :test ,test :key ,key :at ,pos - :result-type ,result-type))))) + :var ,var :val ,val + :test ,test :key ,key :at ,pos + :result-type ,result-type))))) (loopy--check-accumulation-compatibility loopy--loop-name var 'list cmd) `((loopy--accumulation-vars (,var nil)) @@ -1916,9 +1925,9 @@ RESULT-TYPE can be used to `cl-coerce' the return value." (loopy--update-accum-place-count loopy--loop-name var pos) `((loopy--main-body (loopy--optimized-accum '( :cmd ,cmd :name ,name - :var ,var :val ,val - :test ,test :key ,key :at ,pos - :result-type ,result-type))) + :var ,var :val ,val + :test ,test :key ,key :at ,pos + :result-type ,result-type))) (loopy--implicit-return ,var)))) ;;;;;;; Append