emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: What's missing in ELisp that makes people want to use cl-lib?


From: João Távora
Subject: Re: What's missing in ELisp that makes people want to use cl-lib?
Date: Wed, 15 Nov 2023 12:14:43 +0000

[replying to both subthreads here]

On Wed, Nov 15, 2023 at 1:28 AM Dmitry Gutov <dmitry@gutov.dev> wrote:

> > But say I did that seq-do, then what is the seq-contains-p generic good
> > for then?  Why some many redundant generics that the user learns the
> > hard way have to be consistent with each other?
> So any new type gets a lot of functions implemented very easily, and
> could add specialized implementations for performance.

Fair enough.  Except, as you noted, those optimizations can be
completely nullified overnight, when trying to optimize something
else.

> the switchover would tank the performance of its callers.
> As long as the observable behavior stays the same (aside from
> performance), that seems fine.

I don't think this is "fine" at all to tank user code performance,
not from any library, much less such a basic foundation library.

> > (seq-difference '(:m6-sparse 1 2 :double-o-seven 4) '(7)) ;; => (1 2 0 0 4)

> Very clever. I'm not thinking too well this time of night, but the first
> part of the reply in this email probably answers the question (there is
> a certain set of generics that must be implemeneted).

Alright, if you must have them, they're all very trivial and I don't
think it'll add much to your analysis.  Here's the full
compressed/sparse/lazy list impl:

(cl-defmethod seq-do (function (l (head :m6-sparse)))
  (mapc (lambda (e)
          (if (eq e :double-o-seven) (mapc function '(0 0 7))
            (funcall function e)))
        (cdr l)))

(cl-defmethod seq-reverse ((l (head :m6-sparse)))
  (let (res) (seq-do (lambda (e) (push e res)) l) res))

(cl-defmethod seq-elt ((l (head :m6-sparse)) n) (elt (nreverse
(seq-reverse l)) n))
(cl-defmethod seq-length ((l (head :m6-sparse))) (length (nreverse
(seq-reverse l))))
(cl-defmethod seqp ((_l (head :m6-sparse))) t)
(cl-defmethod seq-into-sequence ((l (head :m6-sparse))) (nreverse
(seq-reverse l)))
(cl-defmethod seq-subseq ((l (head :m6-sparse)) start &optional end)
  (cl-subseq (nreverse (seq-reverse l)) start end))
(cl-defmethod seq-copy ((l (head :m6-sparse))) (nreverse (seq-reverse l)))
(cl-defmethod seq-into ((l (head :m6-sparse)) type)
  (cl-call-next-method (nreverse (seq-reverse l)) type))

(defvar my-compressed-list '(:m6-sparse 1 2 :double-o-seven 4
:double-o-seven 9 10 11))

(seq-difference my-compressed-list '(7)) ;; => (1 2 0 0 4 0 0 9 10 11)
(seq-elt my-compressed-list 0)           ;; => 1
(seq-elt my-compressed-list 4)           ;; => 7
(seq-elt my-compressed-list 5)           ;; => 4
(seq-elt my-compressed-list 10)          ;; => 10
(seq-elt my-compressed-list 1)           ;; => 2
(seq-elt my-compressed-list 3)           ;; => 0
(seq-elt my-compressed-list 13)          ;; => nil
(seq-length my-compressed-list)          ;; => 12
(seqp my-compressed-list)                ;; => t
(seq-subseq my-compressed-list 2 5)      ;; => (0 0 7)
(seq-copy my-compressed-list)            ;; => (1 2 0 0 7 4 0 0 7 9 10 11)
(seq-into my-compressed-list 'vector)    ;; => [1 2 0 0 7 4 0 0 7 9 10 11]
(seq-into-sequence my-compressed-list)   ;; => (1 2 0 0 7 4 0 0 7 9 10 11)


;; non consing version
(cl-defmethod seq-elt ((l (head :m6-sparse)) n)
  (cl-loop for e in (cdr l)
           for diff = (- n i)
           while (cl-plusp diff)
           sum (if (eq e :double-o-seven) 3 1) into i
           finally return
           (cond ((eq e :double-o-seven) 0)
                 ((cl-minusp diff) (elt '(7 0 0) (- (1+ diff))))
                 ((zerop diff) e)
                 (t nil))))
;; non consing version
(cl-defmethod seq-length ((l (head :m6-sparse)))
  (cl-loop for e in (cdr l)
           sum (if (eq e :double-o-seven) 3 1)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]