Optimize -remove-first a bit

* dash.el (--remove-first): Open code -remove-first using nconc
instead of -concat for speed.  Extend docstring.
(-remove-first): Rewrite in terms of --remove-first.  Extend
docstring.
* dev/examples.el (-remove-first): Extend tests.

* README.md:
* dash.texi: Regenerate docs.
master
Basil L. Contovounesios 5 years ago
parent 6f5888c775
commit db45ee715a
No known key found for this signature in database
GPG Key ID: 205AB54A5D5D8CFF
  1. 23
      README.md
  2. 42
      dash.el
  3. 25
      dash.texi
  4. 17
      dev/examples.el

@ -541,16 +541,19 @@ For similar operations, see also [`-keep`](#-keep-fn-list) and [`-filter`](#-fil
#### -remove-first `(pred list)`
Return a new list with the first item matching `pred` removed.
Alias: `-reject-first`
See also: [`-remove`](#-remove-pred-list), [`-map-first`](#-map-first-pred-rep-list)
```el
(-remove-first 'even? '(1 3 5 4 7 8 10)) ;; => '(1 3 5 7 8 10)
(-remove-first 'stringp '(1 2 "first" "second" "third")) ;; => '(1 2 "second" "third")
(--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10)) ;; => '(1 2 3 5 6 7 8 9 10)
Remove the first item from `list` for which `pred` returns non-nil.
This is a non-destructive operation, but only the front of `list`
leading up to the removed item is a copy; the rest is `list``s
original tail. If no item is removed, then the result is a
complete copy.
Alias: `-reject-first`.
This function's anaphoric counterpart is `--remove-first`.
See also [`-map-first`](#-map-first-pred-rep-list), [`-remove-item`](#-remove-item-item-list), and [`-remove-last`](#-remove-last-pred-list).
```el
(-remove-first #'natnump '(-2 -1 0 1 2)) ;; => '(-2 -1 1 2)
(-remove-first #'stringp '(1 2 "first" "second")) ;; => '(1 2 "second")
(--remove-first (> it 3) '(1 2 3 4 5 6)) ;; => '(1 2 3 5 6)
```
#### -remove-last `(pred list)`

@ -456,24 +456,34 @@ For similar operations, see also `-keep' and `-filter'."
(defalias '-reject '-remove)
(defalias '--reject '--remove)
(defun -remove-first (pred list)
"Return a new list with the first item matching PRED removed.
Alias: `-reject-first'
See also: `-remove', `-map-first'"
(let (front)
(while (and list (not (funcall pred (car list))))
(push (car list) front)
(!cdr list))
(if list
(-concat (nreverse front) (cdr list))
(nreverse front))))
(defmacro --remove-first (form list)
"Anaphoric form of `-remove-first'."
"Remove the first item from LIST for which FORM evals to non-nil.
Each element of LIST in turn is bound to `it' and its index
within LIST to `it-index' before evaluating FORM. This is a
non-destructive operation, but only the front of LIST leading up
to the removed item is a copy; the rest is LIST's original tail.
If no item is removed, then the result is a complete copy.
This is the anaphoric counterpart to `-remove-first'."
(declare (debug (form form)))
`(-remove-first (lambda (it) ,form) ,list))
(let ((front (make-symbol "front"))
(tail (make-symbol "tail")))
`(let ((,tail ,list) ,front)
(--each-while ,tail (not ,form)
(push (pop ,tail) ,front))
(if ,tail
(nconc (nreverse ,front) (cdr ,tail))
(nreverse ,front)))))
(defun -remove-first (pred list)
"Remove the first item from LIST for which PRED returns non-nil.
This is a non-destructive operation, but only the front of LIST
leading up to the removed item is a copy; the rest is LIST's
original tail. If no item is removed, then the result is a
complete copy.
Alias: `-reject-first'.
This function's anaphoric counterpart is `--remove-first'.
See also `-map-first', `-remove-item', and `-remove-last'."
(--remove-first (funcall pred it) list))
(defalias '-reject-first '-remove-first)
(defalias '--reject-first '--remove-first)

@ -528,24 +528,27 @@ For similar operations, see also @code{-keep} (@pxref{-keep}) and @code{-filter}
@anchor{-remove-first}
@defun -remove-first (pred list)
Return a new list with the first item matching @var{pred} removed.
Alias: @code{-reject-first}
See also: @code{-remove} (@pxref{-remove}), @code{-map-first} (@pxref{-map-first})
Remove the first item from @var{list} for which @var{pred} returns non-nil.
This is a non-destructive operation, but only the front of @var{list}
leading up to the removed item is a copy; the rest is @var{list}'s
original tail. If no item is removed, then the result is a
complete copy.
Alias: @code{-reject-first}.
This function's anaphoric counterpart is @code{--remove-first}.
See also @code{-map-first} (@pxref{-map-first}), @code{-remove-item} (@pxref{-remove-item}), and @code{-remove-last} (@pxref{-remove-last}).
@example
@group
(-remove-first 'even? '(1 3 5 4 7 8 10))
@result{} '(1 3 5 7 8 10)
(-remove-first #'natnump '(-2 -1 0 1 2))
@result{} '(-2 -1 1 2)
@end group
@group
(-remove-first 'stringp '(1 2 "first" "second" "third"))
@result{} '(1 2 "second" "third")
(-remove-first #'stringp '(1 2 "first" "second"))
@result{} '(1 2 "second")
@end group
@group
(--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10))
@result{} '(1 2 3 5 6 7 8 9 10)
(--remove-first (> it 3) '(1 2 3 4 5 6))
@result{} '(1 2 3 5 6)
@end group
@end example
@end defun

@ -160,13 +160,16 @@ new list."
(--remove nil '(1)) => '(1))
(defexamples -remove-first
(-remove-first 'even? '(1 3 5 4 7 8 10)) => '(1 3 5 7 8 10)
(-remove-first 'stringp '(1 2 "first" "second" "third")) => '(1 2 "second" "third")
(--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10)) => '(1 2 3 5 6 7 8 9 10)
(-remove-first 'even? '(2 3 4)) => '(3 4)
(-remove-first 'even? '(3 5 7 4)) => '(3 5 7)
(-remove-first 'even? '(2)) => nil
(-remove-first 'even? '(1 3 5 7)) => '(1 3 5 7))
(-remove-first #'natnump '(-2 -1 0 1 2)) => '(-2 -1 1 2)
(-remove-first #'stringp '(1 2 "first" "second")) => '(1 2 "second")
(--remove-first (> it 3) '(1 2 3 4 5 6)) => '(1 2 3 5 6)
(-remove-first #'natnump '(2 3 4)) => '(3 4)
(-remove-first #'natnump '(-3 -2 -1 4)) => '(-3 -2 -1)
(-remove-first #'natnump '(2)) => '()
(-remove-first #'natnump '()) => '()
(-remove-first #'null '(1 3 5 7)) => '(1 3 5 7)
(let ((l (list 1 2))) (setcar (-remove-first #'identity l) 0) l) => '(1 0)
(let ((l (list 1 2))) (setcar (-remove-first #'null l) 0) l) => '(1 2))
(defexamples -remove-last
(-remove-last 'even? '(1 3 5 4 7 8 10 11)) => '(1 3 5 4 7 8 11)

Loading…
Cancel
Save