help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: [External] : Re: How to make M-x TAB not work on (interactive) decla


From: Ruijie Yu
Subject: Re: [External] : Re: How to make M-x TAB not work on (interactive) declaration?
Date: Sat, 11 Feb 2023 12:38:30 +0800
User-agent: mu4e 1.8.13; emacs 29.0.60

Hello Jean,

It seems to me that you still have some lingering questions regarding
this topic.  See below for my attempt to answer them.

Jean Louis <bugs@gnu.support> writes:

> * Nick Dokos <ndokos@gmail.com> [2023-01-17 19:27]:
>> The "empty sum" and "empty product" conventions are described in the
>> corresponding articles in Wikipedia too - they might help:
>>
>>    https://en.wikipedia.org/wiki/Empty_sum
>>    https://en.wikipedia.org/wiki/Empty_product
>
> Thanks much.
>
> I understand that "summation" is not equal to "addition" as summation
> is the addition of a sequence of any kind of numbers, called addends
> or summands; the result is their sum or total:
> https://en.wikipedia.org/wiki/Summation
>
> Then back to: https://en.wikipedia.org/wiki/Empty_sum
> where it says:
>
> In mathematics, an empty sum, or nullary sum,[1] is a summation where
> the number of terms is zero. The natural way to extend non-empty
> sums[2] is to let the empty sum be the additive identity.
>
> Basically function `+' deals with summation, not with addition. But
> that is conclusion I can draw alone with help of your references,
> without confirmation by docstring, manual or some references.
>
> Though I do not understand why it has to deal with summation, and not
> straight with addition? What is use in Lisp?

IIUC, are you asking why, within Emacs codebase, there is no 2-argument
"addition" function, in addition to the variadic summation function
known as `+'?  And similarly, why there is no 2-argument
"multiplication" function, in addition to the variadic product function
known as `*'?

IMO, the answer is threefold.  I believe most, if not all, of them have
been mentioned in previous messages of this thread, but hopefully by
listing them below side by side, it makes a bit more sense to you.

First, we can all agree that some sort of addition is needed, either
2-arg or variadic, in order to support the most basic functionalities
like motions within a buffer and making calculations.

Second, there should be plenty of cases (which I have not verified
within the codebase) where summing up a list of numbers is needed.  If
the variadic "summation" function is not available, then each such
library (first or third party) have to either implement their own
summation function, or use something like `(cl-reduce #'add-two-numbers
input-list :initial-value 0)'.

Third, if it is determined that a "summation" function is needed, then
the "addition" function is a strict subset of the summation function and
no longer necessary.  Suppose we have the two functions `add' (2-arg
only) and `sum' (variadic), I hope you can agree that these two
expressions are always equivalent in terms of their results:

    (add 1 2) ;=> 3
    (sum 1 2) ;=> 3

Because of the reasons above, IMO, the Emacs maintainers made a consious
decision that implementing the summation function as `+' is enough for
all its use cases, and it would be no longer necessary to have a
separate "addition" function.  Similarly, they decided to implement the
product function as `*'.

Admittedly, they could have implemented the following summation function
and have made `+' only accept 2 arguments, but not doing so is their
decision to make and do not introduce real functional differences:

    (defun sum (nums) (cl-reduce #'+ nums :initial-value 0))

The reason Emacs gets to make this decision (as opposed to, for example,
C) is because `+' and `*' are ordinary functions.  Consider C:
arithmetic expressions are made with an operator, a left-hand-side
expression and a right-hand-side expression.  There are no other
"sides".  Therefore, without introducing more complexity to the language
(e.g. special-casing a "sum" function which takes generic, variadic
arguments), it is only feasible for C to have 2-arg arithmetic
operators.

> In this other reference: https://en.wikipedia.org/wiki/Empty_product
> the issue with Lisp is mentioned, and we can read, that in many
> programming languages it is so, like in Python, Lisp, but in Perl is
> not so, then it says:
>
> Multiplication is an infix operator and therefore a binary operator,
> complicating the notation of an empty product. Some programming
> languages handle this by implementing variadic functions. For example,
> the fully parenthesized prefix notation of Lisp languages gives rise
> to a natural notation for nullary functions:
>
> (* 2 2 2)   ; evaluates to 8
> (* 2 2)     ; evaluates to 4
> (* 2)       ; evaluates to 2
> (*)         ; evaluates to 1
>
> and:
>
> In mathematics and in computer programming, a variadic function is a
> function of indefinite arity, i.e., one which accepts a variable
> number of arguments. Support for variadic functions differs widely
> among programming languages.
>
> I may alone assume, while still needing confirmation, that Emacs Lisp,
> Common Lisp use those variadic function. Not that I have got stable
> feeling with it.
>
> Though that still does not tell me why?
>
> I have excluded the purpose for `apply' and similar functions as that
> is handled properly with PicoLisp where (*) ➜ NIL -- and maybe I am
> wrong, but with all references I came closer some reasoning. But all
> the reasoning is not confirmed in Lisp books.

I don't have an answer for why other lisp dialects have different
defaults.

> What I understand from C is thet if number of args nargs is 0 is that
> result shall be 1 -- that alone does not explain why and how is it
> useful in Lisp.
>
> DEFUN ("*", Ftimes, Stimes, 0, MANY, 0,
>        doc: /* Return product of any number of arguments, which are numbers 
> or markers.
> usage: (* &rest NUMBERS-OR-MARKERS)  */)
>   (ptrdiff_t nargs, Lisp_Object *args)
> {
>   if (nargs == 0)
>     return make_fixnum (1);
>   Lisp_Object a = check_number_coerce_marker (args[0]);
>   return nargs == 1 ? a : arith_driver (Amult, nargs, args, a);
> }

Regarding why the default values of summation and product are 0 and 1
respectively, here is a concrete example use case (with analysis) where
said default values are needed:

    Consider you want to sum up *all values* inside a nested list to get
    a single value:

        (setq foo
              '((1 2 3 4) ;=> 10
                ()        ;=> 0
                (1))      ;=> 1

    To sum it manually, you see that this is essentially summing up the
    list '(1 2 3 4 1) to get 11.

    You can also write the following expression to calculate the sum:

        (apply #'+ (mapcar (lambda (lst) (apply #'+ lst)) foo))
        ;=> 11

    Notice how you have skipped the empty sublist.  In a sense, because
    this sublist is empty, you *don't add anything* to the accumulated
    result.  Mathematically, that is the same as adding 0.  Therefore,
    the only natural default value for summation is 0.

    This analysis can also be made for the default value of product,
    where when you skip an empty sublist, you *don't multiple anything*
    to the accumulated result, which is mathematically equivalent to
    multiplying by 1, which we can then conclude should be the natural
    default value for product.

Hope that helps.

Best,


RY



reply via email to

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