From b880fc4a14e8f49a0deeb9ff5c0562771d9a70e3 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Fri, 5 Aug 2022 11:41:32 -0700 Subject: refactor(wpcarro/emacs): Remove list.el's dep on dash.el 🎉 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still pruning the dependency tree. Thank you, seq.el, from DWIMing. Change-Id: I797f08abe44853b9d297a99d5ba9e9bde3dcfeec Reviewed-on: https://cl.tvl.fyi/c/depot/+/6040 Reviewed-by: wpcarro Autosubmit: wpcarro Tested-by: BuildkiteCI --- users/wpcarro/emacs/pkgs/list/list.el | 92 +++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 42 deletions(-) (limited to 'users/wpcarro/emacs/pkgs/list/list.el') diff --git a/users/wpcarro/emacs/pkgs/list/list.el b/users/wpcarro/emacs/pkgs/list/list.el index a1822e77ff..2aa226609d 100644 --- a/users/wpcarro/emacs/pkgs/list/list.el +++ b/users/wpcarro/emacs/pkgs/list/list.el @@ -52,9 +52,9 @@ ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'dash) (require 'maybe) (require 'set) +(require 'set) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Library @@ -106,37 +106,31 @@ "Add `X' to the head of `XS'." (cons x xs)) -;; map, filter, reduce +(defun list-filter (p xs) + "Return a subset of XS where predicate P returned t." + (list--assert-instance xs) + (seq-filter p xs)) -;; TODO: Create function adapters like swap. -;; (defun adapter/swap (f) -;; "Return a new function that wraps `F' and swaps the arguments." -;; (lambda (a b) -;; (funcall f b a))) +(defun list-map (f xs) + "Call `F' on each element of `XS'." + (list--assert-instance xs) + (seq-map f xs)) -;; TODO: Make this function work. (defun list-reduce (acc f xs) "Return over `XS' calling `F' on an element in `XS'and `ACC'." - (-reduce-from (lambda (acc x) (funcall f x acc)) acc xs)) - -(defun list-map (f xs) - "Call `F' on each element of `XS'." - (-map f xs)) + (list--assert-instance xs) + (seq-reduce (lambda (acc x) (funcall f x acc)) xs acc)) (defun list-map-indexed (f xs) "Call `F' on each element of `XS' along with its index." - (-map-indexed (lambda (i x) (funcall f x i)) xs)) - -(defun list-filter (p xs) - "Return a subset of XS where predicate P returned t." (list-reverse - (list-reduce - '() - (lambda (x acc) - (if (funcall p x) - (list-cons x acc) - acc)) - xs))) + (cdr + (list-reduce '(0 . nil) + (lambda (x acc) + (let ((i (car acc)) + (result (cdr acc))) + `(,(+ 1 i) . ,(cons (funcall f x i) result)))) + xs)))) (defun list-reject (p xs) "Return a subset of XS where predicate of P return nil." @@ -144,7 +138,8 @@ (defun list-find (p xs) "Return the first x in XS that passes P or nil." - (-find p xs)) + (list--assert-instance xs) + (seq-find p xs)) ;; TODO: Support dedupe. ;; TODO: Should we call this unique? Or distinct? @@ -164,19 +159,17 @@ "Chunk XS into lists of size N." (if (> n (length xs)) (list xs) - (->> xs - (list-reduce '(:curr () :result ()) - (lambda (x acc) - (let ((curr (plist-get acc :curr)) - (result (plist-get acc :result))) - (if (= (- n 1) (length curr)) - `(:curr () :result ,(list-cons (list-reverse (list-cons x curr)) result)) - `(:curr ,(list-cons x curr) :result ,result))))) - (funcall (lambda (xs) - (let ((curr (plist-get xs :curr)) - (result (plist-get xs :result))) - (if curr (list-cons curr result)) result))) - list-reverse))) + (let* ((xs (list-reduce '(:curr () :result ()) + (lambda (x acc) + (let ((curr (plist-get acc :curr)) + (result (plist-get acc :result))) + (if (= (- n 1) (length curr)) + `(:curr () :result ,(list-cons (list-reverse (list-cons x curr)) result)) + `(:curr ,(list-cons x curr) :result + ,result)))) xs)) + (curr (plist-get xs :curr)) + (result (plist-get xs :result))) + (list-reverse (if curr (list-cons curr result) result))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Predicates @@ -194,20 +187,35 @@ Be leery of using this with things like alists. Many data structures in Elisp (defun list-all? (p xs) "Return t if all `XS' pass the predicate, `P'." - (-all? p xs)) + (if (list-empty? xs) + t + (and (maybe-some? (funcall p (car xs))) + (list-all? p (cdr xs))))) (defun list-any? (p xs) "Return t if any `XS' pass the predicate, `P'." - (-any? p xs)) + (if (list-empty? xs) + nil + (or (maybe-some? (funcall p (car xs))) + (list-any? p (cdr xs))))) (defun list-contains? (x xs) "Return t if X is in XS using `equal'." - (maybe-some? (-contains? xs x))) + (list--assert-instance xs) + (maybe-some? (seq-contains xs x))) (defun list-xs-distinct-by? (f xs) "Return t if all elements in XS are distinct after applying F to each." (= (length xs) - (->> xs (-map f) set-from-list set-count))) + (set-count (set-from-list (list-map f xs))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Helpers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun list--assert-instance (xs) + (unless (list-instance? xs) + (error (format "Assertion failed: argument is not a list: %s" xs)))) (provide 'list) ;;; list.el ends here -- cgit 1.4.1