Skip to content

Commit

Permalink
Warn that :result-type is deprecated.
Browse files Browse the repository at this point in the history
We have a more flexible approach with coercion functions an `accum-opt`.

Removal is tracked in #154.
  • Loading branch information
okamsn committed Aug 12, 2023
1 parent 270c2bf commit 3146186
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 63 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
34 changes: 9 additions & 25 deletions doc/loopy-doc.org
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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=.
Expand All @@ -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

Expand All @@ -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=.
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
46 changes: 14 additions & 32 deletions doc/loopy.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand All @@ -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))
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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


Expand Down
21 changes: 15 additions & 6 deletions loopy-commands.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 3146186

Please sign in to comment.