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: Tomas Hlavaty
Subject: Re: What's missing in ELisp that makes people want to use cl-lib?
Date: Tue, 14 Nov 2023 18:40:01 +0100

On Tue 14 Nov 2023 at 11:47, João Távora <joaotavora@gmail.com> wrote:
> On Tue, Nov 14, 2023 at 10:55 AM Po Lu <luangruo@yahoo.com> wrote:
> LOOP, pcase, etc, like any other macros, are mini-languages.  Like
> any higher-level language, the more powerful they are, the more
> transformations they will do on your input.  LOOP is pretty powerful,
> and may or may not be suitable for the task at hand, like any other
> language.

The question is if those are "nice" mini-languages or expressing the
code in simple emacs-lisp is nicer.

> At any rate Tomas' translation of the loop is just plain
> wrong.  Where is 'type-spec' being bound?  It needs to be
> destructured:

Thanks, you found a bug in the sketch.  It should have been:

    (puthash (pop f) (comp-type-spec-to-cstr (pop f)) h)

or maybe

    (puthash (car f) (comp-type-spec-to-cstr (cadr f)) h)

> LOOP is a language which is very good
> at expressing this fact concisely in a self-documenting way:
>
>   for (f type-spec) in comp-known-type-specifiers

or

(dolist (x comp-known-type-specifiers)
  (destructuring-bind (f type-spec) x ...))

if emacs-lisp had destructuring-bind.

Note that in this particular example, the variables are not needed at
all.

Also note that comp-known-type-specifiers contains unnecessary cons cell
for each element.

> Here from this one line, without ever having looked at Andrea's
> code I learn that comp-known-type-specifiers is a list of
> 2-element lists, where each such tuple is at least made of
> an 'f' and a 'type-spec'.

Even better feature of destructuring-bind is: when
comp-known-type-specifiers changes structure, destructuring-bind will
fail laudly.

If cl-loop supported keywords, it could be even more strict:

(destructuring-bind (&key f type-spec) comp-known-type-specifiers ...)

Or maybe comp-known-type-specifiers should be a structure?

How strict do we want to be?

> Here, I think dolist + pcase-let/cl-destructuring-case/seq-let
> would also be appropriate.  Though I'm sure someone out there
> would find it insufferably ugly or anti-Elisp as well.

I think dolist would be the right choice.

>   >   (cl-loop
>   >    with comp-ctxt = (make-comp-cstr-ctxt)
>   >    with h = (make-hash-table :test #'eq)
>   >    for (f type-spec) in comp-known-type-specifiers
>   >    for cstr = (comp-type-spec-to-cstr type-spec)
>   >    do (puthash f cstr h)
>   >    finally return h)

That would be something along the lines of:

(let ((h (make-hash-table :test #'eq)))
  (dolist (f comp-known-type-specifiers h)
    (puthash (pop f) (comp-type-spec-to-cstr (pop f)) h)))

which seems the most concise translation of the cl-loop code above

or

(let ((h (make-hash-table :test #'eq)))
  (dolist (f comp-known-type-specifiers h)
    (puthash (car f) (comp-type-spec-to-cstr (cadr f)) h)))

> Anyway Tomas' example, if it were to be corrected, would become
> "ugly" perhaps "uglier" (as if "ugly" were even an objective
> thing)

So I removed the unused variable comp-ctxt, pulled the hash-table out of
cl-loop, and puthash stuff for each element of
comp-known-type-specifiers.

The only ugly thing remaining is destructuring the elements of
comp-known-type-specifiers which plain emacs-lisp does not have a good
way of expressing:

(let ((h (make-hash-table :test #'eq)))
  (dolist (x comp-known-type-specifiers h)
    (destructuring-bind (f type-spec) x
      (puthash f (comp-type-spec-to-cstr type-spec) h))))

or (if emacs-lisp had &key)

(let ((h (make-hash-table :test #'eq)))
  (dolist (x comp-known-type-specifiers h)
    (destructuring-bind (&key f type-spec) x
      (puthash f (comp-type-spec-to-cstr type-spec) h))))

or in plain emacs-lisp:

(let ((h (make-hash-table :test #'eq)))
  (dolist (x comp-known-type-specifiers h)
    (apply (lambda (f type-spec)
             (puthash f (comp-type-spec-to-cstr type-spec) h))
           x)))

or

(defun mapcly (fn seq)
  (mapc (lambda (x) (apply fn x)) seq))

(let ((h (make-hash-table :test #'eq)))
  (mapcly (lambda (f type-spec)
            (puthash f (comp-type-spec-to-cstr type-spec) h))
          comp-known-type-specifiers)
  h)



reply via email to

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