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: Po Lu
Subject: Re: What's missing in ELisp that makes people want to use cl-lib?
Date: Fri, 10 Nov 2023 20:52:32 +0800
User-agent: Gnus/5.13 (Gnus v5.13)

João Távora <joaotavora@gmail.com> writes:

> You're just contradicting yourself.  First, you argue that it's easy
> to replace and has these immediate benefits and then when someone agrees
> with you, you say you don't want to.

I didn't say I don't want to, I said that removing this one instance
will not solve the underlying readiness to resort to _non-preloaded_
files, of which cl-lib is one, and an egregious offender.

> Also btw, it might not be easy to replace at all cl-list* can be used
> with higher order #'apply in contexts where nconc can't.  Perhaps
> you despise the programmer who wrote
>
>   (apply #'cl-list* input-data)
>
> But perhaps they did it to avoid writing a multi-line raw loop choo choo
> train again.
>
> So it's not true what you said originally that everytime you find a
> cl-list* it can be cleanly replaced by nconc.  Not if you understand
> or even appreciate function composition.

I don't appreciate "function combination," whatever that is.

In a language such as C, the function of a single block is clear.  Each
block commences with a list of one declarator for each variable.

Variables are supplied to and operated on by a list of arithmetic or
data operators and procedures, subject to control constructs all
programmers learn, and a value derived from one or more expressions
holding these variables is returned to complete the block's procedure.

Thus as data changes hands between operators, functions and variables,
its movement can be discerned with only a handful of operators and
control constructs in memory.  This is how a computer operates, or what
_you_ do when working out long division on a piece of paper, or when you
set yourself to any other task entailing the observation of a series of
steps while responding to changing circumstances in the process.

Emacs Lisp is well capable of aligning to such requirements as well;
today many would implement the old float-to-string with cl-loop and
floating point numbers with structs, but in the past they were
implemented with cons cells and while loops, without us being any the
worse for wear.

(defun float-to-string (fnum &optional sci)
  "Convert the floating point number to a decimal string.
Optional second argument non-nil means use scientific notation."
  (let* ((value (fabs fnum)) (sign (< (car fnum) 0))
         (power 0) (result 0) (str "") 
         (temp 0) (pow10 _f1))

    (if (f= fnum _f0)
        "0"
      (if (f>= value _f1)                       ; find largest power of 10 <= 
value
          (progn                                ; value >= 1, power is positive
            (while (f<= (setq temp (f* pow10 highest-power-of-10)) value)
              (setq pow10 temp
                    power (+ power decimal-digits)))
            (while (f<= (setq temp (f* pow10 _f10)) value)
              (setq pow10 temp
                    power (1+ power))))
        (progn                          ; value < 1, power is negative
          (while (f> (setq temp (f/ pow10 highest-power-of-10)) value)
            (setq pow10 temp
                  power (- power decimal-digits)))
          (while (f> pow10 value)
            (setq pow10 (f/ pow10 _f10)
                  power (1- power)))))
                                          ; get value in range 100000 to 999999
      (setq value (f* (f/ value pow10) all-decimal-digs-minval)
            result (ftrunc value))
      (let (int)
        (if (f> (f- value result) _f1/2)        ; round up if remainder > 0.5
            (setq int (1+ (fint result)))
          (setq int (fint result)))
        (setq str (int-to-string int))
        (if (>= int 1000000)
            (setq power (1+ power))))

      (if sci                           ; scientific notation
          (setq str (concat (substring str 0 1) "." (substring str 1)
                            "E" (int-to-string power)))

                                          ; regular decimal string
        (cond ((>= power (1- decimal-digits))
                                          ; large power, append zeroes
               (let ((zeroes (- power decimal-digits)))
                 (while (natnump zeroes)
                   (setq str (concat str "0")
                         zeroes (1- zeroes)))))

                                          ; negative power, prepend decimal
              ((< power 0)              ; point and zeroes
               (let ((zeroes (- (- power) 2)))
                 (while (natnump zeroes)
                   (setq str (concat "0" str)
                         zeroes (1- zeroes)))
                 (setq str (concat "0." str))))

              (t                                ; in range, insert decimal point
               (setq str (concat
                          (substring str 0 (1+ power))
                          "."
                          (substring str (1+ power)))))))

      (if sign                          ; if negative, prepend minus sign
          (concat "-" str)
        str))))

If it is to these that you apply the moniker "multi-line raw loop choo
choo trains," then they are precisely what should be written more, not
less.

The "Lisp way" (more felicitously the cl-lib way) is to provide
functions to truckloads of other functions which interface them with one
another.

Each such function is a unique control construct.  To glean what a
function does, one must not only commit each of these control constructs
to memory, but as is all too often the case when the functions provided
to the control constructs are beyond its control, also examine each of
its callers, with labyrinths that put C++ to shame into the bargain,
like pcase-lambda and macros which rewrite the control flow of a form
beyond recognition.

> Be consistent: find the places using simple forms of cl-list* that
> presumably (as you said) are the only motivations for the whole
> cl-lib.el 27kb loading.  I didn't check but this was your opening
> argument after all.  So do that and you'll have effectively and
> consensually helped Emacs's code base.  You'll be closer to your
> dream goal, using Emacs without loading cl-lib.el.   Be consistent
> with your words, else you're just hand-waving and advocating
> for irrationality.  "develop a general aversion"??? I like to think
> of programmers as scientists, not acolytes to some sect.

If such invective and an unwillingness to reason from the specific to
the general is the best response you have, I won't condescend to answer.


reply via email to

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