* Emacs 30.0 warning from `cl-pushnew' and `memql'
@ 2022-12-26 20:38 Emanuel Berg
2022-12-27 6:56 ` Jean Louis
2022-12-27 10:28 ` Michael Heerdegen
0 siblings, 2 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-26 20:38 UTC (permalink / raw)
To: help-gnu-emacs
After the last powerup I see this, it refers to a use of `cl-pushnew'.
Warning: `memql' called with literal string that may never match
(arg 1)
GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, cairo version 1.16.0)
of 2022-12-26 [commit 2ffe1494e16381cfc7fec95a6a0879f268df3e95]
https://dataswamp.org/~incal/conf/.zsh/install-emacs
There were a bunch of other warnings, during installation as well as
during native compilation, next time I'll see if I can fetch those
and get back to you on those as well ...
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-26 20:38 Emacs 30.0 warning from `cl-pushnew' and `memql' Emanuel Berg
@ 2022-12-27 6:56 ` Jean Louis
2022-12-27 10:28 ` Michael Heerdegen
1 sibling, 0 replies; 61+ messages in thread
From: Jean Louis @ 2022-12-27 6:56 UTC (permalink / raw)
To: help-gnu-emacs
* Emanuel Berg <incal@dataswamp.org> [2022-12-27 00:37]:
> After the last powerup I see this, it refers to a use of `cl-pushnew'.
>
> Warning: `memql' called with literal string that may never match
> (arg 1)
I just guess that may be some of new warnings, which is good to
have as it helps in improving the code.
--
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
In support of Richard M. Stallman
https://stallmansupport.org/
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-26 20:38 Emacs 30.0 warning from `cl-pushnew' and `memql' Emanuel Berg
2022-12-27 6:56 ` Jean Louis
@ 2022-12-27 10:28 ` Michael Heerdegen
2022-12-27 11:33 ` Emanuel Berg
2022-12-27 11:39 ` Emanuel Berg
1 sibling, 2 replies; 61+ messages in thread
From: Michael Heerdegen @ 2022-12-27 10:28 UTC (permalink / raw)
To: help-gnu-emacs
Emanuel Berg <incal@dataswamp.org> writes:
> After the last powerup I see this, it refers to a use of `cl-pushnew'.
>
> Warning: `memql' called with literal string that may never match
> (arg 1)
Yes, these new warnings hint at problematic calls. In case of
cl-pushnew you want to specify a :test function to avoid comparing
strings with an inappropriate test function like the default memql.
Michael.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-27 10:28 ` Michael Heerdegen
@ 2022-12-27 11:33 ` Emanuel Berg
2022-12-27 11:39 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-27 11:33 UTC (permalink / raw)
To: help-gnu-emacs
Michael Heerdegen wrote:
>> After the last powerup I see this, it refers to a use of `cl-pushnew'.
>>
>> Warning: `memql' called with literal string that may never match
>> (arg 1)
>
> Yes, these new warnings hint at problematic calls. In case of
> cl-pushnew you want to specify a :test function to avoid comparing
> strings with an inappropriate test function like the
> default memql.
But that's up to `cl-pushnew' to do, and if it can't/don't, it
shouldn't accept strings as indata ...
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-27 10:28 ` Michael Heerdegen
2022-12-27 11:33 ` Emanuel Berg
@ 2022-12-27 11:39 ` Emanuel Berg
2022-12-28 3:23 ` [External] : " Drew Adams
2022-12-28 6:25 ` tomas
1 sibling, 2 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-27 11:39 UTC (permalink / raw)
To: help-gnu-emacs
Michael Heerdegen wrote:
>> After the last powerup I see this, it refers to a use of
>> `cl-pushnew'.
>>
>> Warning: `memql' called with literal string that may never match
>> (arg 1)
>
> Yes, these new warnings hint at problematic calls. In case of
> cl-pushnew you want to specify a :test function to avoid comparing
> strings with an inappropriate test function like the
> default memql.
This does not render the warning
(cl-pushnew "/usr/share/emacs/site-lisp/elpa-src/slime-2.26.1"
load-path
:test #'string=)
but this is not a model I can endorse, this is why you have that
level of abstraction to begin with, i.e., not to be bothered all the
time with implementation details.
Might as well to provide :loop #'cl-dolist how to iterate the
list as well ...
And after that ... is there anything else to specify before we can
get rid of `cl-pushnew' altogether since it amounts to doing
everything manually anyway?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-27 11:39 ` Emanuel Berg
@ 2022-12-28 3:23 ` Drew Adams
2022-12-28 4:23 ` Emanuel Berg
2022-12-28 6:25 ` tomas
1 sibling, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-28 3:23 UTC (permalink / raw)
To: Emanuel Berg, help-gnu-emacs@gnu.org
> (cl-pushnew "/usr/share/emacs/site-lisp/elpa-src/slime-2.26.1"
> load-path
> :test #'string=)
>
> but this is not a model I can endorse, this is why you have that
> level of abstraction to begin with, i.e., not to be bothered all the
> time with implementation details.
>
> Might as well to provide :loop #'cl-dolist how to iterate the
> list as well ...
>
> And after that ... is there anything else to specify before we can
> get rid of `cl-pushnew' altogether since it amounts to doing
> everything manually anyway?
`cl-pushnew' should be an emulation of Common Lisp
`pushnew' - neither more nor less.
I'm not sure what your point is, but `pushnew'
defaults to using `eql', not `equal' (or
`string='). So if you want `pushnew' to compare
strings then yes, you should pass a predicate
such as `string=' (or `equal').
https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node149.html
___
IMHO, it should be the case for _all_ things that
`cl-lib' tries to support. We shouldn't (IMO) be
in the business of adding stuff to `cl-lib' that
has nothing to do with CL. But that's happened.
On the other hand, there's no reason (IMO) that
Elisp can't have its own functions that have the
same name as CL functions (sans `cl-'). In that
case the Elisp functions need not behave the same
as the CL ones. IOW, `cl-lib', and the `cl-'
prefix, should be reserved for CL emulation.
Elisp has `push', for example. It need not be
the same as CL `push' (but I believe it pretty
much is). Emacs could just as well have a `case'
macro, and not require you to load `cl-lib'.
Similarly for other commonly useful macros. Why
does Elisp have one CL thing (without `cl-') and
not another? You might well ask.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 3:23 ` [External] : " Drew Adams
@ 2022-12-28 4:23 ` Emanuel Berg
2022-12-29 22:27 ` Drew Adams
2022-12-30 6:30 ` tomas
0 siblings, 2 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 4:23 UTC (permalink / raw)
To: help-gnu-emacs
Drew Adams wrote:
> `cl-pushnew' should be an emulation of Common Lisp `pushnew' -
> neither more nor less.
>
> I'm not sure what your point is, but `pushnew' defaults to using
> `eql', not `equal' (or `string='). So if you want `pushnew' to
> compare strings then yes, you should pass a predicate such as
> `string=' (or `equal').
It's much better if the function itself checks what type the value
is of and pick a suitable function to compare from that, then the
user don't have to think about that at all.
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-27 11:39 ` Emanuel Berg
2022-12-28 3:23 ` [External] : " Drew Adams
@ 2022-12-28 6:25 ` tomas
2022-12-28 11:59 ` Michael Heerdegen
2022-12-28 12:44 ` Emanuel Berg
1 sibling, 2 replies; 61+ messages in thread
From: tomas @ 2022-12-28 6:25 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 1002 bytes --]
On Tue, Dec 27, 2022 at 12:39:15PM +0100, Emanuel Berg wrote:
> Michael Heerdegen wrote:
>
> >> After the last powerup I see this, it refers to a use of
> >> `cl-pushnew'.
> >>
> >> Warning: `memql' called with literal string that may never match
> >> (arg 1)
> >
> > Yes, these new warnings hint at problematic calls. In case of
> > cl-pushnew you want to specify a :test function to avoid comparing
> > strings with an inappropriate test function like the
> > default memql.
>
> This does not render the warning
>
> (cl-pushnew "/usr/share/emacs/site-lisp/elpa-src/slime-2.26.1"
> load-path
> :test #'string=)
>
> but this is not a model I can endorse, this is why you have that
> level of abstraction to begin with, i.e., not to be bothered all the
> time with implementation details.
I don't understand you. That function is most useful if you can
pass it a custom comparison function. I'd say it's fine as it
is.
Cheers
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 6:25 ` tomas
@ 2022-12-28 11:59 ` Michael Heerdegen
2022-12-28 12:41 ` tomas
` (2 more replies)
2022-12-28 12:44 ` Emanuel Berg
1 sibling, 3 replies; 61+ messages in thread
From: Michael Heerdegen @ 2022-12-28 11:59 UTC (permalink / raw)
To: help-gnu-emacs
<tomas@tuxteam.de> writes:
> I don't understand you. That function is most useful if you can
> pass it a custom comparison function. I'd say it's fine as it
> is.
I think the interpretation of the question "Could there be a better
default comparison function?", in the sense that `eql' is a bit nicer
than `eq' for specific value types, is valid, especially when
considering that `cl-pushnew' is often used for configuration stuff or
other purposes where speed is not crucial.
Michael.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 11:59 ` Michael Heerdegen
@ 2022-12-28 12:41 ` tomas
2022-12-28 12:45 ` Emanuel Berg
` (3 more replies)
2022-12-28 17:54 ` Drew Adams
2022-12-28 20:24 ` Jean Louis
2 siblings, 4 replies; 61+ messages in thread
From: tomas @ 2022-12-28 12:41 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 713 bytes --]
On Wed, Dec 28, 2022 at 12:59:23PM +0100, Michael Heerdegen wrote:
> <tomas@tuxteam.de> writes:
>
> > I don't understand you. That function is most useful if you can
> > pass it a custom comparison function. I'd say it's fine as it
> > is.
>
> I think the interpretation of the question "Could there be a better
> default comparison function?", in the sense that `eql' is a bit nicer
> than `eq' for specific value types, is valid, especially when
> considering that `cl-pushnew' is often used for configuration stuff or
> other purposes where speed is not crucial.
I see. Well, that train has sailed (or something). Backward compat
(especially with user's brains) and things.
Cheers
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 6:25 ` tomas
2022-12-28 11:59 ` Michael Heerdegen
@ 2022-12-28 12:44 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 12:44 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
>> This does not render the warning
>>
>> (cl-pushnew "/usr/share/emacs/site-lisp/elpa-src/slime-2.26.1"
>> load-path
>> :test #'string=)
>>
>> but this is not a model I can endorse, this is why you have that
>> level of abstraction to begin with, i.e., not to be bothered all
>> the time with implementation details.
>
> I don't understand you. That function is most useful if you can
> pass it a custom comparison function. I'd say it's fine as it is.
It's a useful thing to be able to do to but it could default to
a comparison function that works for the data type of the submitted
argument, in this case `string=' for the string.
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 12:41 ` tomas
@ 2022-12-28 12:45 ` Emanuel Berg
2022-12-28 13:19 ` Emanuel Berg
` (2 subsequent siblings)
3 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 12:45 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> I see. Well, that train has sailed (or something).
> Backward compat (especially with user's brains) and things.
It's more intuitive that it uses a function that doesn't work
for the argument just provided so the byte compiler has to
warn about it?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 12:41 ` tomas
2022-12-28 12:45 ` Emanuel Berg
@ 2022-12-28 13:19 ` Emanuel Berg
2022-12-28 14:54 ` Emanuel Berg
2022-12-28 17:57 ` [External] : " Drew Adams
3 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 13:19 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> I see. Well, that train has sailed (or something).
> Backward compat (especially with user's brains) and things.
One can also think of `equal' for lists, instead of `eql',
as, as you know
(equal '(1 2 3) '(1 2 3)) ; t
(eql '(1 2 3) '(1 2 3)) ; nil
Here is one example of that.
;;; -*- lexical-binding: t -*-
;;
;; this file:
;; https://dataswamp.org/~incal/emacs-init/psea.el
(require 'cl-lib)
(require 'math)
(defun string-distance-percentage (str1 str2 &optional str-out)
(let*((len1 (length str1))
(len2 (length str2))
(long (max len1 len2))
(dist (string-distance str1 str2)) )
(percent (- long dist) long str-out) ))
(defun pattern-search (str &optional beg end)
(interactive `(,(read-string "search: ")
,@(when (use-region-p)
(list (region-beginning) (region-end)) )))
(or beg (setq beg (point-min)))
(or end (setq end (point-max)))
(cl-loop
with len = (length str)
for c from beg to (- end len)
with hit
with fallout
do (setq hit (buffer-substring-no-properties c (+ c len)))
(cl-pushnew (list hit
(string-distance hit str)
(string-distance-percentage str hit t) )
fallout :test #'equal)
finally return
(message "%s"
(seq-take (sort fallout (lambda (a b) (< (cadr a) (cadr b)))) 5) )))
(defalias 'psea #'pattern-search)
;; (psea "history" (point-min) (+ 100 (point-min)))
;;
;; his fil 4 42.9%
;; amp.org 5 28.6%
;; this fi 5 28.6%
;; /psea.e 6 14.3%
;; nit/pse 6 14.3%
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 12:41 ` tomas
2022-12-28 12:45 ` Emanuel Berg
2022-12-28 13:19 ` Emanuel Berg
@ 2022-12-28 14:54 ` Emanuel Berg
2022-12-29 22:31 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 17:57 ` [External] : " Drew Adams
3 siblings, 1 reply; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 14:54 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
>> I think the interpretation of the question "Could there be
>> a better default comparison function?", in the sense that
>> `eql' is a bit nicer than `eq' for specific value types, is
>> valid, especially when considering that `cl-pushnew' is
>> often used for configuration stuff or other purposes where
>> speed is not crucial.
>
> I see. Well, that train has sailed (or something).
> Backward compat (especially with user's brains) and things.
But in a way it makes sense since if you write the code the
right way for the same data, it works ...
(require 'cl-lib)
(let ((lst '())
(str "a") )
(cl-pushnew str lst)
(cl-pushnew str lst)
lst) ; ("a")
(let ((lst '()))
(cl-pushnew "a" lst)
(cl-pushnew "a" lst)
lst) ; ("a" "a")
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 11:59 ` Michael Heerdegen
2022-12-28 12:41 ` tomas
@ 2022-12-28 17:54 ` Drew Adams
2022-12-28 18:05 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:21 ` Emanuel Berg
2022-12-28 20:24 ` Jean Louis
2 siblings, 2 replies; 61+ messages in thread
From: Drew Adams @ 2022-12-28 17:54 UTC (permalink / raw)
To: Michael Heerdegen, help-gnu-emacs@gnu.org
> I think the interpretation of the question "Could there be a better
> default comparison function?", in the sense that `eql' is a bit nicer
> than `eq' for specific value types, is valid, especially when
> considering that `cl-pushnew' is often used for configuration stuff or
> other purposes where speed is not crucial.
If Emacs wants to have its own `pushnew' macro
then its definition can and should do whatever
is best for Emacs. But if Emacs wants to have
a macro that emulates CL's `pushnew', and thus
call it `cl-pushnew', then it should behave as
much as possible like CL's `pushnew'. And
that includes defaulting to using `eql'.
IOW, don't think about what default predicate
would be best for Elisp, for `cl-pushnew'.
Think instead about what default predicate CL
uses for `pushnew'. That's what emulation is
about.
BTW, this isn't a guideline to "protect CL" or
something. It's a guideline for the benefit of
Elisp: clearly identify what's CL emulation and
what's not.
And yes, Elisp can and perhaps should directly
include some more CL macros as its own (doing
whatever's best for Elisp, and not bothering
to best emulate the CL version). This could
apply to `pushnew'.
___
And it applies to `case', IMHO. Encouraging or
coercing folks to use `pcase' or `cond' just to
handle the simple and common case of `case' is
overkill.
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 12:41 ` tomas
` (2 preceding siblings ...)
2022-12-28 14:54 ` Emanuel Berg
@ 2022-12-28 17:57 ` Drew Adams
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:24 ` Emanuel Berg
3 siblings, 2 replies; 61+ messages in thread
From: Drew Adams @ 2022-12-28 17:57 UTC (permalink / raw)
To: tomas@tuxteam.de, help-gnu-emacs@gnu.org
> > I think the interpretation of the question "Could there be a better
> > default comparison function?", in the sense that `eql' is a bit nicer
> > than `eq' for specific value types, is valid, especially when
> > considering that `cl-pushnew' is often used for configuration stuff or
> > other purposes where speed is not crucial.
>
> I see. Well, that train has sailed (or something). Backward compat
> (especially with user's brains) and things.
I think that's the wrong way to think about this.
The default for `cl-pushnew' should be `eql'
because the default for CL `pushnew' is `eql'.
End of story.
If a better default predicate exists for Elisp
then Elisp should add its own `pushnew', using
that better predicate as default. It shouldn't
substitute that predicate as the default of
`cl-pushnew'.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 17:54 ` Drew Adams
@ 2022-12-28 18:05 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:35 ` Drew Adams
2022-12-28 19:21 ` Emanuel Berg
1 sibling, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-28 18:05 UTC (permalink / raw)
To: help-gnu-emacs
> And it applies to `case', IMHO. Encouraging or
> coercing folks to use `pcase' or `cond' just to
> handle the simple and common case of `case' is
> overkill.
For those cases handled by `(cl-)case`, `pcase` is just as easy to use
[ apparently even easier for some people who otherwise write (case FOO
('a (do-a)) ('b (do-b) ...)) ], so I don't see what's overkill about it.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 17:57 ` [External] : " Drew Adams
@ 2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:29 ` Emanuel Berg
` (2 more replies)
2022-12-28 19:24 ` Emanuel Berg
1 sibling, 3 replies; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-28 18:10 UTC (permalink / raw)
To: help-gnu-emacs
> If a better default predicate exists for Elisp
> then Elisp should add its own `pushnew', using
> that better predicate as default. It shouldn't
> substitute that predicate as the default of
> `cl-pushnew'.
Won't happen:
- it would break compatibility with packages still using cl.el's `pushnew`.
- when ELisp uses the same name as Common Lisp, there's a lot of human
pressure to preserve as much as possible of the semantics.
So, if we want something with a different default, we'll probably want
to give it another name.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 17:54 ` Drew Adams
2022-12-28 18:05 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-28 19:21 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 19:21 UTC (permalink / raw)
To: help-gnu-emacs
Drew Adams wrote:
> If Emacs wants to have its own `pushnew' macro then its
> definition can and should do whatever is best for Emacs.
> But if Emacs wants to have a macro that emulates CL's
> `pushnew', and thus call it `cl-pushnew', then it should
> behave as much as possible like CL's `pushnew'. And that
> includes defaulting to using `eql' [...]
In so many words, yes.
> Encouraging or coercing folks to use `pcase' or `cond' just
> to handle the simple and common case of `case' is overkill.
Agreed, let's do it!
Overkill is our middle name ...
https://www.youtube.com/watch?v=pbWLvwE8zfw
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 17:57 ` [External] : " Drew Adams
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-28 19:24 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 19:24 UTC (permalink / raw)
To: help-gnu-emacs
Drew Adams wrote:
>> I see. Well, that train has sailed (or something).
>> Backward compat (especially with user's brains) and things.
>
> I think that's the wrong way to think about this.
> The default for `cl-pushnew' should be `eql' because the
> default for CL `pushnew' is `eql'. End of story.
Yeah, it gets easier that way, for sure.
> If a better default predicate exists for Elisp then Elisp
> should add its own `pushnew', using that better predicate
> as default.
Indeed, note that it doesn't have to be a matter of a single
function being the one default, it can be many defaults
depending on the type of the argument value.
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-28 19:29 ` Emanuel Berg
2022-12-28 19:35 ` Drew Adams
2022-12-28 19:36 ` tomas
2 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 19:29 UTC (permalink / raw)
To: help-gnu-emacs
Stefan Monnier via Users list for the GNU Emacs text editor wrote:
>> If a better default predicate exists for Elisp then Elisp
>> should add its own `pushnew', using that better predicate
>> as default. It shouldn't substitute that predicate as the
>> default of `cl-pushnew'.
>
> Won't happen:
> - it would break compatibility with packages still using
> cl.el's `pushnew`.
> - when ELisp uses the same name as Common Lisp, there's
> a lot of human pressure to preserve as much as possible of
> the semantics.
>
> So, if we want something with a different default, we'll
> probably want to give it another name.
`1+'
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 18:05 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-28 19:35 ` Drew Adams
2022-12-29 3:34 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-28 19:35 UTC (permalink / raw)
To: Stefan Monnier, 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 1160 bytes --]
> > And it applies to `case', IMHO. Encouraging or
> > coercing folks to use `pcase' or `cond' just to
> > handle the simple and common case of `case' is
> > overkill.
>
> For those cases handled by `(cl-)case`, `pcase` is just as easy to use
> [ apparently even easier for some people who otherwise write (case FOO
> ('a (do-a)) ('b (do-b) ...)) ], so I don't see what's overkill about it.
Did you mean (case FOO (a (do-a)) (b (do-b) ...))?
^ ^
No need to quote.
And no need to use `or' to match a set of values:
(case FOO ((a b) (do ab)) ((c d e) (do-cde))...)
And no need to fathom all the rest of pcase's
complicated syntax. Complicated syntax is good
when you need to do something complex.
And yes, it's good to have something that handles
lots of cases, even if that makes understanding
the syntax complicated. But that's not a reason
not to _also_ have a simple syntax for a common,
simple use case. `pcase' provides the former;
`case' provides the latter.
IOW, I don't argue that we shouldn't have `pcase'.
I don't see why we shouldn't also have `case'
(sans `cl-'), that's all.
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 14170 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:29 ` Emanuel Berg
@ 2022-12-28 19:35 ` Drew Adams
2022-12-28 19:36 ` tomas
2 siblings, 0 replies; 61+ messages in thread
From: Drew Adams @ 2022-12-28 19:35 UTC (permalink / raw)
To: Stefan Monnier, 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 400 bytes --]
> > If a better default predicate exists for Elisp...
> So, if we want something with a different default,
> we'll probably want to give it another name.
Agree.
I don't see the need for a different default.
It's not hard to add a predicate arg.
To me it makes sense to just include `pushnew'
as it is (with `eql' and without `cl-'), just
as was done for `push' in Emacs 22 (or 21?).
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 13814 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:29 ` Emanuel Berg
2022-12-28 19:35 ` Drew Adams
@ 2022-12-28 19:36 ` tomas
2 siblings, 0 replies; 61+ messages in thread
From: tomas @ 2022-12-28 19:36 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 287 bytes --]
On Wed, Dec 28, 2022 at 01:10:07PM -0500, Stefan Monnier via Users list for the GNU Emacs text editor wrote:
[...]
> So, if we want something with a different default, we'll probably want
> to give it another name.
cl-cl-pushnew?
(no, I'm not serious ;-)
Cheers
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 11:59 ` Michael Heerdegen
2022-12-28 12:41 ` tomas
2022-12-28 17:54 ` Drew Adams
@ 2022-12-28 20:24 ` Jean Louis
2022-12-28 20:56 ` Emanuel Berg
` (2 more replies)
2 siblings, 3 replies; 61+ messages in thread
From: Jean Louis @ 2022-12-28 20:24 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: help-gnu-emacs
* Michael Heerdegen <michael_heerdegen@web.de> [2022-12-28 15:01]:
> I think the interpretation of the question "Could there be a better
> default comparison function?", in the sense that `eql' is a bit nicer
> than `eq' for specific value types, is valid, especially when
> considering that `cl-pushnew' is often used for configuration stuff or
> other purposes where speed is not crucial.
Michael, what is the fastest way to add element on stack of the list
elements?
Let us say I am adding only strings, would this be faster than `push':
(setq my-list '())
(setq my-list (cons (quote "Word") my-list))
By the way, how do I go to make this right?
-------------------------------------------
(setq my-list '())
(benchmark 1000 (setq my-list (cons "My string" my-list)))
as it gives error that "My string" is invalid function.
Do I need to do something like:
(benchmark 1000 (prog1 nil
(setq my-list (cons (quote "Word") my-list))))
(benchmark 10000000 (prog1 nil
(setq my-list (cons (quote "Word") my-list)))) ➜ "Elapsed time: 0.823678s"
(benchmark 10000000 (prog1 nil
(push "Word" my-list))) ➜ "Elapsed time: 0.824388s"
So there is no much difference apparently.
--
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
In support of Richard M. Stallman
https://stallmansupport.org/
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 20:24 ` Jean Louis
@ 2022-12-28 20:56 ` Emanuel Berg
2022-12-28 21:24 ` [External] : " Drew Adams
2022-12-29 10:39 ` Michael Heerdegen
2 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 20:56 UTC (permalink / raw)
To: help-gnu-emacs
Jean Louis wrote:
> (benchmark 10000000 (prog1 nil
> (setq my-list (cons (quote "Word") my-list))))
> → "Elapsed time: 0.823678s"
>
> (benchmark 10000000 (prog1 nil
> (push "Word" my-list)))
> → "Elapsed time: 0.824388s"
Don't hard-code that (** 10 7) ...
> So there is no much difference apparently.
You can try with this as well ...
(defmacro measure-time (&rest body)
"Measure and return the running time of the code block.
http://nullprogram.com/blog/2009/05/28/"
(declare (indent defun))
(let ((start (make-symbol "start")))
`(let ((,start (float-time)))
,@body
(- (float-time) ,start) )))
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 20:24 ` Jean Louis
2022-12-28 20:56 ` Emanuel Berg
@ 2022-12-28 21:24 ` Drew Adams
2022-12-28 22:47 ` Jean Louis
2022-12-29 10:39 ` Michael Heerdegen
2 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-28 21:24 UTC (permalink / raw)
To: Jean Louis, Michael Heerdegen; +Cc: help-gnu-emacs@gnu.org
> Michael, what is the fastest way to add element on stack of the list
> elements?
>
> Let us say I am adding only strings, would this be faster than `push':
>
> (setq my-list '())
> (setq my-list (cons (quote "Word") my-list))
I'm not Michael, but (push "Word" my-list) expands
to just that code. So no, neither is faster.
(macroexpand-1 '(push "Word" mylist))
;; ==> (setq mylist (cons "Word" mylist))
(And no reason to quote either () or a literal string.)
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 21:24 ` [External] : " Drew Adams
@ 2022-12-28 22:47 ` Jean Louis
2022-12-28 23:48 ` Emanuel Berg
2022-12-29 6:03 ` tomas
0 siblings, 2 replies; 61+ messages in thread
From: Jean Louis @ 2022-12-28 22:47 UTC (permalink / raw)
To: Drew Adams; +Cc: Michael Heerdegen, help-gnu-emacs@gnu.org
* Drew Adams <drew.adams@oracle.com> [2022-12-29 00:24]:
> > Michael, what is the fastest way to add element on stack of the list
> > elements?
> >
> > Let us say I am adding only strings, would this be faster than `push':
> >
> > (setq my-list '())
> > (setq my-list (cons (quote "Word") my-list))
>
>
> I'm not Michael, but (push "Word" my-list) expands
> to just that code. So no, neither is faster.
>
> (macroexpand-1 '(push "Word" mylist))
>
> ;; ==> (setq mylist (cons "Word" mylist))
Thanks.
> (And no reason to quote either () or a literal string.)
There was reason. See here:
(setq my-list '())
(benchmark 1000 (setq my-list (cons "Word" my-list)))
Debugger entered--Lisp error: (invalid-function "Word")
("Word")
(closure (t) nil ("Word"))()
benchmark-call((closure (t) nil ("Word")) 1000)
benchmark(1000 ("Word"))
eval((benchmark 1000 (setq my-list (cons "Word" my-list))) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
but then `benchmark` worked only first time, second time it gave
error.
--
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
In support of Richard M. Stallman
https://stallmansupport.org/
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 22:47 ` Jean Louis
@ 2022-12-28 23:48 ` Emanuel Berg
2022-12-29 6:03 ` tomas
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-28 23:48 UTC (permalink / raw)
To: help-gnu-emacs
Jean Louis wrote:
> (setq my-list '())
> (benchmark 1000 (setq my-list (cons "Word" my-list)))
If you use `let' here one can `eval-last-sexp' (which I have
M-9) right in the Gnus article buffer ...
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 19:35 ` Drew Adams
@ 2022-12-29 3:34 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-29 19:06 ` Drew Adams
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-29 3:34 UTC (permalink / raw)
To: help-gnu-emacs
>> > And it applies to `case', IMHO. Encouraging or
>> > coercing folks to use `pcase' or `cond' just to
>> > handle the simple and common case of `case' is
>> > overkill.
>>
>> For those cases handled by `(cl-)case`, `pcase` is just as easy to use
>> [ apparently even easier for some people who otherwise write (case FOO
>> ('a (do-a)) ('b (do-b) ...)) ], so I don't see what's overkill about it.
>
> Did you mean (case FOO (a (do-a)) (b (do-b) ...))?
No, I did mean exactly what I wrote.
> No need to quote.
I know. But lots of users don't and they so quote, hence using the syntax
that would be correct with `pcase` but that has a "subtly" different
meaning for `cl-case`.
That's what I meant by "even easier for some people".
> IOW, I don't argue that we shouldn't have `pcase'.
> I don't see why we shouldn't also have `case'
> (sans `cl-'), that's all.
What's the benefit (other than having to learn 2 subtly different
things instead of just one)?
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 22:47 ` Jean Louis
2022-12-28 23:48 ` Emanuel Berg
@ 2022-12-29 6:03 ` tomas
2022-12-29 6:59 ` Emanuel Berg
` (4 more replies)
1 sibling, 5 replies; 61+ messages in thread
From: tomas @ 2022-12-29 6:03 UTC (permalink / raw)
To: help-gnu-emacs; +Cc: Drew Adams, Michael Heerdegen
[-- Attachment #1: Type: text/plain, Size: 1217 bytes --]
On Thu, Dec 29, 2022 at 01:47:57AM +0300, Jean Louis wrote:
[...]
> > (And no reason to quote either () or a literal string.)
>
> There was reason. See here:
>
> (setq my-list '())
> (benchmark 1000 (setq my-list (cons "Word" my-list)))
>
> Debugger entered--Lisp error: (invalid-function "Word")
> ("Word")
> (closure (t) nil ("Word"))()
[...]
> but then `benchmark` worked only first time, second time it gave
> error.
Read benchmark's doc string carefully :-)
Benchmark is a /function/, so its argument is evaluated first. By
the Rule of Lisp [1], args are evaluated first...
(benchmark (cons "Word" my-list)) =>
(benchmark ("Word")) => ; since list is empty
... and then it tries to evaluate the function application
("Word"), which explains your error message.
If now you look again at the benchmark's docstring it says to
provide a form. This means you have to quote the whole thing
like so:
(benchmark 1000 '(setq my-list (cons "word" my-list)))
If you just quote "Word", you are benchmarking the wrong thing, anyway :)
Cheers
[1] aka "strict order evaluation"
https://en.wikipedia.org/wiki/Evaluation_strategy#Strict_evaluation
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 6:03 ` tomas
@ 2022-12-29 6:59 ` Emanuel Berg
2022-12-29 7:08 ` Emanuel Berg
` (3 subsequent siblings)
4 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 6:59 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> Benchmark is a /function/, so its argument is evaluated
> first. By the Rule of Lisp args are evaluated first [...]
> aka "strict order evaluation"
>
> https://en.wikipedia.org/wiki/Evaluation_strategy#Strict_evaluation
Sure but ... how else would you do it?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 6:03 ` tomas
2022-12-29 6:59 ` Emanuel Berg
@ 2022-12-29 7:08 ` Emanuel Berg
2022-12-29 7:19 ` Emanuel Berg
` (2 subsequent siblings)
4 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 7:08 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> args are evaluated first
And from left to right :)
(defun dis ()
(let ((do-as "Disintegration as a Service"))
do-as) )
(dis (message "Access to the Lisp planet") (/ 1 0))
(dis (/ 1 0) (message "bz-7z [static]"))
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 6:03 ` tomas
2022-12-29 6:59 ` Emanuel Berg
2022-12-29 7:08 ` Emanuel Berg
@ 2022-12-29 7:19 ` Emanuel Berg
2022-12-29 22:41 ` Drew Adams
2022-12-30 6:35 ` tomas
2022-12-29 9:18 ` Jean Louis
2022-12-29 14:47 ` Stefan Monnier via Users list for the GNU Emacs text editor
4 siblings, 2 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 7:19 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> Benchmark is a /function/, so its argument is evaluated
> first. By the Rule of Lisp [1], args are evaluated first...
Applicative order AKA strict evaluation: a function is
undefined if any of its arguments are.
So in practice, that means they are computed first.
And that makes sense! Since a function f(x, y) is very much
a function of x and y ...
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 6:03 ` tomas
` (2 preceding siblings ...)
2022-12-29 7:19 ` Emanuel Berg
@ 2022-12-29 9:18 ` Jean Louis
2022-12-29 10:04 ` Emanuel Berg
` (2 more replies)
2022-12-29 14:47 ` Stefan Monnier via Users list for the GNU Emacs text editor
4 siblings, 3 replies; 61+ messages in thread
From: Jean Louis @ 2022-12-29 9:18 UTC (permalink / raw)
To: tomas; +Cc: help-gnu-emacs, Drew Adams, Michael Heerdegen
Thanks Thomas, after following your corrections:
(setq my-list '()) ➜ nil
(benchmark 10000000 '(setq my-list (cons "Word" my-list))) ➜ "Elapsed time: 5.943843s (4.111302s in 3 GCs)"
It works!
> Read benchmark's doc string carefully :-)
My misunderstanding is with FORM and BODY, when I read FORM, I
understand it is same as BODY. Now I see the difference.
I have found reference in Emacs Lisp manual, but I cannot find
reference that FORM as argument means quoted sexp, if you have that
reference, let me know
--
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
In support of Richard M. Stallman
https://stallmansupport.org/
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 9:18 ` Jean Louis
@ 2022-12-29 10:04 ` Emanuel Berg
2022-12-29 10:12 ` tomas
2022-12-29 10:36 ` Michael Heerdegen
2 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 10:04 UTC (permalink / raw)
To: help-gnu-emacs
Jean Louis wrote:
>> Read benchmark's doc string carefully :-)
>
> My misunderstanding is with FORM and BODY, when I read FORM,
> I understand it is same as BODY. Now I see the difference.
>
> I have found reference in Emacs Lisp manual, but I cannot
> find reference that FORM as argument means quoted sexp
Yeah, I've seen this mistake many times ...
If it says it is a function the args are eval'd, if it is
a macro they aren't.
C-h f benchmark RET
`benchmark' is an autoloaded interactive native-compiled
Lisp function
A bit further down it says also says
For non-interactive use see also `benchmark-run'
C-h f benchmark-run RET
`benchmark-run' is an autoloaded Lisp macro
Compare
(let ((cnt 0))
(benchmark 5 (cl-incf cnt))
cnt) ; 1
(let ((cnt 0))
(benchmark-run 5 (cl-incf cnt))
cnt) ; 5
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 9:18 ` Jean Louis
2022-12-29 10:04 ` Emanuel Berg
@ 2022-12-29 10:12 ` tomas
2022-12-29 10:20 ` Emanuel Berg
2022-12-29 10:26 ` Emanuel Berg
2022-12-29 10:36 ` Michael Heerdegen
2 siblings, 2 replies; 61+ messages in thread
From: tomas @ 2022-12-29 10:12 UTC (permalink / raw)
To: help-gnu-emacs, Drew Adams, Michael Heerdegen
[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]
On Thu, Dec 29, 2022 at 12:18:01PM +0300, Jean Louis wrote:
> Thanks Thomas, after following your corrections:
>
> (setq my-list '()) ➜ nil
> (benchmark 10000000 '(setq my-list (cons "Word" my-list))) ➜ "Elapsed time: 5.943843s (4.111302s in 3 GCs)"
>
> It works!
>
> > Read benchmark's doc string carefully :-)
>
> My misunderstanding is with FORM and BODY, when I read FORM, I
> understand it is same as BODY. Now I see the difference.
>
> I have found reference in Emacs Lisp manual, but I cannot find
> reference that FORM as argument means quoted sexp, if you have that
> reference, let me know
It's a bit subtle, since the point is rather the intention
than the data type itself (the result of an evaluation is
itself a form after all -- that's the magic of Lisp).
The next I came to it (I searched Elisp's manual with `i'
then `form' is "10.1 Introduction to Evaluation":
A Lisp object that is intended for evaluation is
called a “form” or “expression”(1). The fact that
forms are data objects and not merely text is one
of the fundamental differences between Lisp-like
languages and typical programming languages. Any
object can be evaluated [...]
Worth reading :)
Cheers
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 10:12 ` tomas
@ 2022-12-29 10:20 ` Emanuel Berg
2022-12-29 10:26 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 10:20 UTC (permalink / raw)
To: help-gnu-emacs
tomas wrote:
> It's a bit subtle, since the point is rather the intention
> than the data type itself (the result of an evaluation is
> itself a form after all -- that's the magic of Lisp).
>
> The next I came to it (I searched Elisp's manual with `i'
> then `form' is "10.1 Introduction to Evaluation":
>
> A Lisp object that is intended for evaluation is called
> a “form” or “expression”(1). The fact that forms are data
> objects and not merely text is one of the fundamental
> differences between Lisp-like languages and typical
> programming languages. Any object can be evaluated [...]
>
> Worth reading :)
I'd like to read every book on Lisp there is ... from where do
I order them?
I have read these two [last], and another one in Swedish (very
short), and the Emacs 18 manual.
Add to the Lisp book list! (Also add ambitious PDFs with URLs.)
I can help add them, actually, just send the books or other
documents here, no problem.
Emanuel Berg
Ekebyv 21
752 63 Uppsala
Sweden
%%%% Lisp
@book{land-of-lisp,
author = {Conrad Barski},
isbn = 1593272812,
publisher = {No Starch},
title = {Land of Lisp},
year = {2010}
}
@book{lispcraft,
author = {Robert Wilensky},
isbn = 0393954420,
publisher = {Norton},
title = {LISPcraft},
year = {1984}
}
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 10:12 ` tomas
2022-12-29 10:20 ` Emanuel Berg
@ 2022-12-29 10:26 ` Emanuel Berg
1 sibling, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-29 10:26 UTC (permalink / raw)
To: help-gnu-emacs
Also, bold mathematician and contributor to gnu.emacs.help
Marcin ‘mbork’ Borkowski has written a book on Emacs and
Elisp ... B)
https://mbork.pl/2022-08-01_Making_secrets_with_Emacs
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 9:18 ` Jean Louis
2022-12-29 10:04 ` Emanuel Berg
2022-12-29 10:12 ` tomas
@ 2022-12-29 10:36 ` Michael Heerdegen
2 siblings, 0 replies; 61+ messages in thread
From: Michael Heerdegen @ 2022-12-29 10:36 UTC (permalink / raw)
To: help-gnu-emacs
Jean Louis <bugs@gnu.support> writes:
> I have found reference in Emacs Lisp manual, but I cannot find
> reference that FORM as argument means quoted sexp, if you have that
> reference, let me know
No.
The crucial point has already been mentioned: `benchmark' is a function,
so you specify an expression that evaluates to the form you want to
benchmark. Function arguments are evaluated before being passed to the
function.
Michael.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 20:24 ` Jean Louis
2022-12-28 20:56 ` Emanuel Berg
2022-12-28 21:24 ` [External] : " Drew Adams
@ 2022-12-29 10:39 ` Michael Heerdegen
2 siblings, 0 replies; 61+ messages in thread
From: Michael Heerdegen @ 2022-12-29 10:39 UTC (permalink / raw)
To: help-gnu-emacs
Jean Louis <bugs@gnu.support> writes:
> Let us say I am adding only strings, would this be faster than `push':
>
> (setq my-list '())
> (setq my-list (cons (quote "Word") my-list))
`push' forms expand to code like this. `cl-pushnew' is slower
because of the additional tests.
Michael.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 6:03 ` tomas
` (3 preceding siblings ...)
2022-12-29 9:18 ` Jean Louis
@ 2022-12-29 14:47 ` Stefan Monnier via Users list for the GNU Emacs text editor
4 siblings, 0 replies; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-29 14:47 UTC (permalink / raw)
To: help-gnu-emacs
>> but then `benchmark` worked only first time, second time it gave
>> error.
>
> Read benchmark's doc string carefully :-)
>
> Benchmark is a /function/, so its argument is evaluated first. By
> the Rule of Lisp [1], args are evaluated first...
>
> (benchmark (cons "Word" my-list)) =>
> (benchmark ("Word")) => ; since list is empty
Indeed, it's a terrible interface, since it forces the use of quoted
code, yuck!
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 3:34 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-29 19:06 ` Drew Adams
2022-12-29 19:45 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-29 19:06 UTC (permalink / raw)
To: Stefan Monnier, 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 2459 bytes --]
> >> > And it applies to `case', IMHO. Encouraging or
> >> > coercing folks to use `pcase' or `cond' just to
> >> > handle the simple and common case of `case' is
> >> > overkill.
> >>
> >> For those cases handled by `(cl-)case`, `pcase`
> >> is just as easy to use [ apparently even easier
> >> for some people who otherwise write (case FOO
> >> ('a (do-a)) ('b (do-b) ...)) ], so I don't see
> >> what's overkill about it.
> >
> > Did you mean (case FOO (a (do-a)) (b (do-b) ...))?
> No, I did mean exactly what I wrote.
> > No need to quote.
> I know. But lots of users don't and they so quote,
> hence using the syntax that would be correct with
> `pcase` but that has a "subtly" different meaning
> for `cl-case`. That's what I meant by "even easier
> for some people".
Oh, you meant that the simpler `case' syntax might
be harder for some of the people who are used to
the more complex syntax of `pcase', where you need
to quote symbols as values to be compared.
Sure, maybe so. That goes without saying.
Simple can surprise if you're expecting difficult.
`pcase' has to have complicated syntax because it's,
well, complicated - it does much more than simply
test a symbol's value with `eql'.
Likewise, `cond' needs more complex syntax. That's
why Lisp has `if' AND `case' AND `when' AND `or'...
Shades of cl-loop-is-all-you-need-so-use-only-loop
discussion.
> > IOW, I don't argue that we shouldn't have `pcase'.
> > I don't see why we shouldn't also have `case'
> > (sans `cl-'), that's all.
>
> What's the benefit (other than having to learn 2
> subtly different things instead of just one)?
Simpler, for simple cases.
What's the benefit of having both `if' and `cond'
in the language? Or both `pcase' and `cond'?
Or...? Why not just learn one, and not bother
with the others? **`pcase' Cider-House rules!**
I can hardly believe you're asking this. `pcase'
is a useful multi-tool. But sometimes you just
need a tiny pen knife. You can do everything
with just `if', or just `cond', or just...
But why have to?
No one's _obliged_ to learn `case' in addition to
`pcase' (or `cond' or...). Anyone can stick with
just `pcase' (or...).
That you might need to learn the syntax of some
language construct _IF_ you want to use it, seems
obvious. And how hard is it to learn the syntax
of `case' (or even of `cond') compared to that of
`pcase'? Mole hill / mountain.
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 15222 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 19:06 ` Drew Adams
@ 2022-12-29 19:45 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-29 22:00 ` Drew Adams
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-29 19:45 UTC (permalink / raw)
To: help-gnu-emacs
> Oh, you meant that the simpler `case' syntax might
> be harder for some of the people who are used to
> the more complex syntax of `pcase', where you need
> to quote symbols as values to be compared.
No, I mean that even for some people unfamiliar with `pcase` syntax, the
`pcase` syntax is simpler (more natural?) than the cl-`case` syntax: the
incorrect use of `quote` in `cl-case` predates the invention of `pcase` :-)
>> > IOW, I don't argue that we shouldn't have `pcase'.
>> > I don't see why we shouldn't also have `case'
>> > (sans `cl-'), that's all.
>> What's the benefit (other than having to learn 2
>> subtly different things instead of just one)?
> Simpler, for simple cases.
I don't think `case` is objectively simpler.
More specifically, I believe that if you're familiar with neither `cl-case`
nor `pcase` syntax, it's not easier to learn the `case` syntax than the
subset of `pcase` syntax which covers the functionality of `cl-case`.
It may even be objectively easier to learn the `pcase` syntax since it
doesn't suffer from special cases like when you want to distinguish one of
the `nil`, `t`, or `otherwise` values.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 19:45 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-29 22:00 ` Drew Adams
2022-12-29 22:25 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-29 22:00 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 4615 bytes --]
> > Oh, you meant that the simpler `case' syntax might
> > be harder for some of the people who are used to
> > the more complex syntax of `pcase', where you need
> > to quote symbols as values to be compared.
>
> No, I mean that even for some people unfamiliar with `pcase` syntax, the
> `pcase` syntax is simpler (more natural?) than the cl-`case` syntax: the
> incorrect use of `quote` in `cl-case` predates the invention of `pcase`
> :-)
I think you'll need to explain your "incorrect use of
`quote' in `cl-case'". There's no particular use of
`quote' or quoting in `case'.
Are you saying you think `case' should require users
to quote symbols to test for eqlity, i.e., that CL
should have defined `case' so that you need to use
(case FOO
('a "AAA")
(42 (value-for-42)) ; Or maybe use '42?
(('c 'd 'e) (value-for-C-D-or-E))
(('f 'quote) (value-for-F-or-QUOTE))
...)
instead of this?
(case FOO
(a "AAA")
(42 (value-for-42))
((c d e) (value-for-C-D-or-E))
((f quote) (value-for-F-or-QUOTE))
...)
If so, why?
> >> > IOW, I don't argue that we shouldn't have `pcase'.
> >> > I don't see why we shouldn't also have `case'
> >> > (sans `cl-'), that's all.
> >> What's the benefit (other than having to learn 2
> >> subtly different things instead of just one)?
> > Simpler, for simple cases.
>
> I don't think `case` is objectively simpler.
Please show us an example where `pcase' does
only what `case' does, but with simpler syntax.
> More specifically, I believe that if you're familiar
> with neither `cl-case` nor `pcase` syntax, it's not
> easier to learn the `case` syntax than the subset of
> `pcase` syntax which covers the functionality of `cl-case`.
1. It's easier to learn, if only because you
don't have to ALSO learn the non-`case' cases
that `pcase' syntax covers - including patterns
that both bind and match, etc.
You need to at least learn enough of that other
stuff to be able to _not_ fall into it when
you're trying to do just what simple `case'
does: test a value against some atomic values.
2. It's easier to use, for the same reason.
> It may even be objectively easier to learn the
> `pcase` syntax since it doesn't suffer from
> special cases like when you want to distinguish
> one of the `nil`, `t`, or `otherwise` values.
You pepper repeat "objectively", but isn't that
gratuitous? Saying it's so doesn't make it so.
Show da codes, please.
`t' means the same thing as in `cond'. Is it
really hard to grasp? And to be "nicer", `case'
also gives you the synonym `otherwise', which
SHOUTS its meaning of "default", no?
And you can always just use a list for the test
values, including a singleton list. Nothing
obliges one to take advantage of the shorthand
of using just b instead of (b). KISS: always a
list of things to match, or else `otherwise'
for no matches:
(case FOO
((a) "AAA")
((nil) "NIL")
((t) "T")
((otherwise) "Symbol `otherwise'")
((c d e) "C, D, or E")
((f quote) "F-or-QUOTE")
(otherwise "Anything else (default)"))
Sure, the simple, general syntax of using a list
of things to match means that () or nil as the
_list_ of values to match can never match (no
list elements to match). Is that too complex?
It's something Lisp users are used to, no? Even
novice Lisp users learn early on that nil/() is
both a list and a symbol. `case' isn't the only
place where this needs to be understood.
It's common in Lisp programs to distinguish an
empty list of values from a single nil value
(whether viewed as symbol or empty list), by
wrapping the latter in a cons: (nil).
And always using an explicit list of things to
match (or else the atom `otherwise') makes it
very clear that () or nil as that list is useless
- no thing matches nothing. If you really think
some users have trouble with the `case' syntax
then just tell 'em to always use a list of things
to match.
Which (`case' or `pcase') seems simpler might be
just a personal preference on each of our parts.
Lisp provides many ways to do the same thing,
including multiple control constructs (as I
mentioned, and about which you apparently had
nothing to say).
That `pcase' can do what `case' does isn't an
argument for not including `case' in Elisp.
Look at all of the `*-let' stuff that's been
added to Elisp over the last few years. Really
needed? Clearly someone thought that was all
useful for some users...
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 16458 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 22:00 ` Drew Adams
@ 2022-12-29 22:25 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-30 7:29 ` Drew Adams
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-29 22:25 UTC (permalink / raw)
To: help-gnu-emacs
> I think you'll need to explain your "incorrect use of
> `quote' in `cl-case'".
I did at the very beginning:
(case FOO ('a (do-a)) ('b (do-b) ...))
that's an incorrect use of quote, and such incorrect uses of quote in
`cl-case` are very frequent and have been since long before `pcase` existed.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 4:23 ` Emanuel Berg
@ 2022-12-29 22:27 ` Drew Adams
2022-12-30 22:27 ` Emanuel Berg
2022-12-30 6:30 ` tomas
1 sibling, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-29 22:27 UTC (permalink / raw)
To: Emanuel Berg, help-gnu-emacs@gnu.org
> > `cl-pushnew' should be an emulation of Common Lisp `pushnew' -
> > neither more nor less.
> >
> > I'm not sure what your point is, but `pushnew' defaults to using
> > `eql', not `equal' (or `string='). So if you want `pushnew' to
> > compare strings then yes, you should pass a predicate such as
> > `string=' (or `equal').
>
> It's much better if the function itself checks what type the value
> is of and pick a suitable function to compare from that, then the
> user don't have to think about that at all.
Again, `cl-case` came from CL `case' (and that
came from other Lisps).
Elisp is of course free to do whatever it wants.
It could add an optional TEST predicate arg etc.
Checking the "type the value is of" is problematic.
For one thing, you might well want to control the
type of the arg so that it just fit the predicate
you want used (e.g. `eql' in the current case).
And some values are of multiple types. E.g., nil's
a symbol and a list. And some types are subtypes
of other types. E.g. lists are sequences.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 14:54 ` Emanuel Berg
@ 2022-12-29 22:31 ` Stefan Monnier via Users list for the GNU Emacs text editor
2023-01-08 4:18 ` Emanuel Berg
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-29 22:31 UTC (permalink / raw)
To: help-gnu-emacs
> (let ((lst '()))
> (cl-pushnew "a" lst)
> (cl-pushnew "a" lst)
> lst) ; ("a" "a")
It may sometimes return ("a" "a") but it may also return ("a").
Case in point, I think it will do the first when interpreted and the
second when compiled.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 7:19 ` Emanuel Berg
@ 2022-12-29 22:41 ` Drew Adams
2022-12-30 23:03 ` Emanuel Berg
2022-12-30 6:35 ` tomas
1 sibling, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-29 22:41 UTC (permalink / raw)
To: Emanuel Berg, help-gnu-emacs@gnu.org
> Applicative order AKA strict evaluation: a function is
> undefined if any of its arguments are.
>
> So in practice, that means they are computed first.
>
> And that makes sense! Since a function f(x, y) is very much
> a function of x and y ...
Uh, being a function of x and y doesn't imply
that both x and y always need to be known
(calculated).
`if' is a function of all of its args, but in
some cases it need not evaluate all of them.
Same with `*': if one of the args is zero then
no need to calculate the others. Etc.
With normal order evaluation you can evaluate
only the args that are needed, based on what
those args are.
For instance, with applicative order you can't
define `if' as a function. With normal order
you can.
With applicative order some calculations never
end (bottom), while the same function definition
might end with normal order.
And besides never ending, with appl. order you
can do a lot of unnecessary calculation - for
args that the function doesn't end up using.
In general, applicative order is a kludge. But
it's a simple one, and generally efficient.
To make normal order etc. evaluation efficient
you need to make it _fully_ lazy: don't copy
or evaluate the same expression multiple times,
but use graph reduction (sharing) instead.
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-28 4:23 ` Emanuel Berg
2022-12-29 22:27 ` Drew Adams
@ 2022-12-30 6:30 ` tomas
1 sibling, 0 replies; 61+ messages in thread
From: tomas @ 2022-12-30 6:30 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 655 bytes --]
On Wed, Dec 28, 2022 at 05:23:16AM +0100, Emanuel Berg wrote:
[...]
> It's much better if the function itself checks what type the value
> is of and pick a suitable function to compare from that, then the
> user don't have to think about that at all.
Alas, the types don't always carry enough info to know what
comparison that squishy human behind the glass wants. I guess
if they did, they'd be boring to the point of being obnoxious
(perhaps a corollary of Rice's [1] theorem?).
This was the dream of object oriented programming ("Kids, go
compare yourselves").
Cheers
[1] https://en.wikipedia.org/wiki/Rice%27s_theorem
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 7:19 ` Emanuel Berg
2022-12-29 22:41 ` Drew Adams
@ 2022-12-30 6:35 ` tomas
1 sibling, 0 replies; 61+ messages in thread
From: tomas @ 2022-12-30 6:35 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 560 bytes --]
On Thu, Dec 29, 2022 at 08:19:06AM +0100, Emanuel Berg wrote:
> tomas wrote:
>
> > Benchmark is a /function/, so its argument is evaluated
> > first. By the Rule of Lisp [1], args are evaluated first...
>
> Applicative order AKA strict evaluation: a function is
> undefined if any of its arguments are.
>
> So in practice, that means they are computed first.
>
> And that makes sense! Since a function f(x, y) is very much
> a function of x and y ...
Lazy evaluation makes sense, too. It's just not how Emacs
Lisp works.
Cheers
--
t
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 22:25 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-30 7:29 ` Drew Adams
2022-12-30 18:55 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-30 7:29 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 8371 bytes --]
> > I think you'll need to explain your "incorrect
> > use of `quote' in `cl-case'".
>
> I did at the very beginning:
> (case FOO ('a (do-a)) ('b (do-b) ...))
> that's an incorrect use of quote, and such incorrect uses of quote in
> `cl-case` are very frequent and have been since long before `pcase`
> existed.
Oh, so it's not that `case' somehow uses `quote'
incorrectly. It's that some users use `case'
incorrectly. I thought you were trying to say
something else, sorry.
I've never seen anyone misuse the `case' syntax
that way, but I'm sure it's possible.
But "very frequent", really? Any evidence that
that's been the case for the many users of CL
`case' since the mid-80s?
How about comparing that user mistake with user
confusion about `pcase'? Including its use to
handle the simple `case' use case.
[BTW, you still haven't shown the simple `case'
case for `pcase', i.e., correspondences to
`case' examples - e.g., those shown here so far.
Weren't you planning to show how much simpler
it is to use `pcase' for that use case than it
is to use `case'? Let's see apples-to-apples.]
But assuming you're right, do you see only
Elisp users having this misunderstanding, or
have you seen CL users also confused this way?
Maybe it's just that the Emacs description has
some room for improvement. Seems like it
should be clear enough to say that you give it
lists of values and `case' tries to match,
using `eql', the values in those lists against
the result of evaluating its first arg.
The point of `case' is to (1) evaluate a sexp
only once and (2) compare that value against
other values, in a certain order, using `eql'.
(With `cond' you need to (1) use `let' to bind
the result of the sexp evaluation and (2) use
`eql' or `memql' explicitly over and over.)
And maybe it should say that each such list,
and the values in it, are presented _as such_
in the syntax - not evaluated. E.g., not
'(X Y Z), ('X 'Y 'Z), or '('X 'Y 'Z) - just
plain (X Y Z). IOW, as simple as it gets.
And that, for any literal values X, Y, and Z,
including, yes, the symbols nil and t, and
nil's synonym ().
(Of course, since the predicate is `eql' it
generally doesn't make much sense to use
conses or atoms such as strings and vectors as
the list elements - they won't be matched.
But symbols, numbers, chars - such atoms like
`eql' well enough. They're the use case for
`case'.)
The Emacs doc string for `cl-case' talks about
evaluating and evaluating and evaluating...
But it doesn't ever say that the values in
KEYLIST are _NOT_ evaluated. Without that, I
can see how someone reading that doc string
might not get that that's the case.
`C-h f cl-case':
"Eval EXPR and choose among clauses on that value.
[Clauses on a value? (Maybe it means choose
"based" on that value.)]
"Each clause looks like (KEYLIST BODY...).
EXPR is evaluated and compared against each
key in each KEYLIST; the corresponding BODY
is evaluated.
[Where "corresponding" means corresponding to
a clause with a key that is actually `eql'...]
"If no clause succeeds, cl-case returns nil.
A single non-nil atom may be used in place
of a KEYLIST of one atom. A KEYLIST of t
or `otherwise' is allowed only in the final
clause, and matches if no other keys match.
Key values are compared by `eql'."
[It should say that any clauses after the use
of KEYLIST `t' or `otherwise' are just ignored.
If they were really "allowed only in the final
clause" then any clause after them would raise
an error instead of being ignored.]
[And actually, what about just (KEYLIST)?
Does that fit the template (KEYLIST BODY...)?
(KEYLIST) acts the same as (KEYLIST nil) - it
returns nil if one of its keys matches. But
does "BODY..." mean that BODY can be missing
altogether? I can never remember the Emacs
doc convention for this.]
Anyway...
. Eval EXPR. - check!
. EXPR is evaluated. - check!
. The value of EXPR is compared against each
key in each KEYLIST. - Whoa! What's a key?
Just what are those things in KEYLIST? Is
each one a sexp that gets _evaluated_?
No say nada. Bzzzzt!
. The corresponding BODY is evaluated. - check!
. Key matching - Whoa! What's that?
. Key values are compared with `eql'. Hm, that
might be understandable, if we knew what "key
values" were. Does it mean the result of
evaluating a key, i.e., a list element? Or
does it just mean a key - a list element?
The thing that seems to be missing might well
be at the root of the "very frequent" mistake
you report, no?
What's missing here? Keys are _literal values_
to be compared ("matched") using `eql'. They
are not sexps to be evaluated. Seems pretty
important to point that out.
Now what about the Emacs CL manual (node
Conditionals) - is it any better?
"This macro evaluates KEYFORM, then compares
it with the key values listed in the various
CLAUSEs."
[It doesn't compare KEYFORM with the values.
It compares the result of evaluating KEYFORM
with the values. But maybe that's a nit.]
"Whichever clause matches the key is executed;
comparison is done by 'eql'."
What does it mean for a _clause_ to match a
key (a value in the KEYLIST of the clause)?
"The clauses are of the form
(KEYLIST BODY-FORMS...) where KEYLIST is a
list of key values."
A bit better than the doc string. KEYLIST "is"
a list of values, not sexps to be evaluated.
And KEYLIST is a (literal) list, not a sexp to
be evaluated to a list. Maybe users getting
confused would be better off reading the CL
manual than the doc string?
___
Now let's see. What does CLTL2 tell us?
https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html
"If KEY is in the KEYLIST (that is, is `eql'
to any item in the KEYLIST)..."
So KEY is something in KEYLIST (which is a list
presumably). So it's a list element.
"The keys in the keylists are _not_ evaluated;
literal key values must appear in the keylists."
Emphasis on "not". Literal values. Bingo -
pretty clear! (It might also have said that
KEYLIST is a literal list, not a sexp that's
evaluated to give a list.)
BTW, there's also this bit:
"It is an error for the same key to appear in
more than one clause; a consequence is that
the order of the clauses does not affect the
behavior of the case construct."
Apparently Emacs's `cl-case' doesn't raise such
an error. (To emulate CL `case' it should.)
To me, the CLTL2 doc is pretty clear about the
keys and the keylists not being evaluated. This
gives me the idea that maybe Elisp users get
confused about this and CLTL2 readers don't get
confused in the way you reported. A hypothesis.
___
Coming back to the Elisp manual, `cl-case' seems
to be mentioned only in the doc about `pcase'.
(BTW, `cl-case' isn't in the Index, alas.)
There we also say this, which I don't understand,
in the section where it compares `pcase' with
`cl-case'. Dunno whether it's that (1) I don't
understand the English or (2) what it says is
wrong.
It shows a `pcase' example which starts with
this: (pcase (get-return-code x) ...
"With 'cl-case', you would need to explicitly
declare a local variable 'code' to hold the
return value of 'get-return-code'."
Huh? Does that mean you need to use a variable
as the first arg to `cl-case'? If so, that's
not right.
(defun get-return-code (arg)
(if (< arg 42) 'success 'failure))
(let ((x 13))
(cl-case (get-return-code x)
(success (message "Done!"))
(t (message "Unknown!"))))
==> Done!
And with x bound to 56, ==> Unknown!
We didn't "declare a local variable ... to
hold the return value of `get-return-code'."
Dunno what it means to "declare" a variable in
Elisp (except a vacuous defvar: (defvar x)),
but a guess is that it's trying to say you need
to _bind_ a local var to the value returned by
(get-return-code x), and then use that variable
as the first arg to `cl-case'. If so, that's
not true.
It's the value returned from evaluating the
sexp (get-return-code x) that `cl-case' tries
to match (using `eql') against symbol `success'.
`cl-case' doesn't need its first arg to be a
"local variable".
Let me know what I'm missing here.
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 18670 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-30 7:29 ` Drew Adams
@ 2022-12-30 18:55 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-30 22:55 ` Drew Adams
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-30 18:55 UTC (permalink / raw)
To: help-gnu-emacs
> But "very frequent", really? Any evidence that
> that's been the case for the many users of CL
> `case' since the mid-80s?
The only "evidence" I have the number of such errors I've fixed over the
years in other people's ELisp code.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 22:27 ` Drew Adams
@ 2022-12-30 22:27 ` Emanuel Berg
0 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-30 22:27 UTC (permalink / raw)
To: help-gnu-emacs
Drew Adams wrote:
>>> `cl-pushnew' should be an emulation of Common Lisp
>>> `pushnew' - neither more nor less.
>>>
>>> I'm not sure what your point is, but `pushnew' defaults to
>>> using `eql', not `equal' (or `string='). So if you want
>>> `pushnew' to compare strings then yes, you should pass
>>> a predicate such as `string=' (or `equal').
>>
>> It's much better if the function itself checks what type
>> the value is of and pick a suitable function to compare
>> from that, then the user don't have to think about that
>> at all.
>
> Again, `cl-case` came from CL `case' (and that came from
> other Lisps).
Yes, but I say that with respect to that particular function,
if it isn't to be modified for whatever external reasons
that's another discussion you of course are free to carry on
with ...
> Checking the "type the value is of" is problematic. For one
> thing, you might well want to control the type
The function, rather than you, can do this - and pretty
easily so:
(when (stringp arg)
(setq pred #'string=) )
> And some values are of multiple types. E.g., nil's a symbol
> and a list. And some types are subtypes of other types. E.g.
> lists are sequences.
All types that are comparable have a function to do that, that
function is the one to be used.
If they haven't, how are we to determine if they are "new" at
all?
Types whose values cannot be compared even to themself to
determine equality - if such types exist - I don't see how
they can be supported by a 'pushnew' function, really?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-30 18:55 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-30 22:55 ` Drew Adams
2022-12-31 0:08 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-30 22:55 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 1756 bytes --]
> > But "very frequent", really? Any evidence that
> > that's been the case for the many users of CL
^^
Common Lisp
> > `case' since the mid-80s?
>
> The only "evidence" I have the number of such errors
> I've fixed over the years in other people's ELisp code.
Which isn't an indication of such for _CL_ `case',
i.e., in the code of _Common Lisp_ users.
Beyond being perhaps an indication that the Emacs
_doc_ for `cl-case' should be improved, it sounds
like no Elisp problem with `case' has been found.
(Well, I did mention a bug I noticed, of `cl-case'
not raising an error when CL specifies it should.)
And I guess you don't have an example of using
`pcase' to do what `case' does but somehow "simpler".
I doubt that Elisp coders are dumber than CL coders,
in general. If the former are misunderstanding the
no-quoting thing then my guess is that's due to the
lack of doc saying that keylists and their entries
aren't evaluated.
The use case of `case' is simple, yet common. We
should add it to Elisp (with no `cl-' prefix).
___
Note BTW that Common Lisp even adopted _exactly_
the same thing for `typecase' as for `case'. That
wasn't something inherited from other Lisps AFAIK.
They could have done something different, but they
chose the `case' approach, including `otherwise',
`t', and _no evaluation_ of keys:
"The TYPE that appears in each clause is a type
specifier; it is _not evaluated but is a literal_
type specifier."
Clearly they didn't see a problem with not evaling
keys, and opted for a simple syntax for a simple
use case.
https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 15662 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 22:41 ` Drew Adams
@ 2022-12-30 23:03 ` Emanuel Berg
0 siblings, 0 replies; 61+ messages in thread
From: Emanuel Berg @ 2022-12-30 23:03 UTC (permalink / raw)
To: help-gnu-emacs
Drew Adams wrote:
>> Applicative order AKA strict evaluation: a function is
>> undefined if any of its arguments are.
>>
>> So in practice, that means they are computed first.
>>
>> And that makes sense! Since a function f(x, y) is very much
>> a function of x and y ...
>
> Uh, being a function of x and y doesn't imply that both
> x and y always need to be known (calculated).
>
> `if' is a function of all of its args, but in some cases it
> need not evaluate all of them.
Not unlike the Stanley Cup Playoffs - they are best-of-7, not
first-to-4.
Or wait ... should it be the other way around?
> Same with `*': if one of the args is zero then no need to
> calculate the others. Etc.
`or' short-circuiting for that matter.
> To make normal order etc. evaluation efficient you need to
> make it _fully_ lazy: don't copy or evaluate the same
> expression multiple times, but use graph reduction
> (sharing) instead.
Disintegrate everything to fragments.
Filter out duplicates and compute.
Put it back together, with copies for the blanks?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-30 22:55 ` Drew Adams
@ 2022-12-31 0:08 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-31 2:45 ` Drew Adams
0 siblings, 1 reply; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-31 0:08 UTC (permalink / raw)
To: help-gnu-emacs
>> > But "very frequent", really? Any evidence that
>> > that's been the case for the many users of CL
> ^^
> Common Lisp
>> > `case' since the mid-80s?
>>
>> The only "evidence" I have the number of such errors
>> I've fixed over the years in other people's ELisp code.
>
> Which isn't an indication of such for _CL_ `case',
> i.e., in the code of _Common Lisp_ users.
AFAIK this is an Emacs discussion group, so yes, I'm talking about
ELisp, and I used these errors I've corrected over the years as
"objective evidence" that, at least for some coders, the `pcase` syntax
is more intuitive than the `cl-case` syntax (which is also the syntax of
`case` in Common Lisp).
So far I haven't seen anyone show any kind of "objective evidence" that
the `cl-case` syntax is easier to learn or use. Just unsubstantiated
statements that it's simpler as if it were just obvious. Obviously it's
objectively more concise. But the argument in favor of `cl-case` has
never been about concision, AFAICT, always about some notion of being
easier to use. AFAICT its "simplicity" is just the fact that it's a lot
more restrictive, so you can get the same simplicity by resisting the
urge to use the extra features of `pcase`, without having to learn
another syntax.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* RE: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-31 0:08 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2022-12-31 2:45 ` Drew Adams
2022-12-31 4:53 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 1 reply; 61+ messages in thread
From: Drew Adams @ 2022-12-31 2:45 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'
[-- Attachment #1: Type: text/plain, Size: 3958 bytes --]
> AFAICT [`case's] "simplicity" is just the fact
> that it's a lot more restrictive, so you can
> get the same simplicity by resisting the
> urge to use the extra features of `pcase`,
> without having to learn another syntax.
That's what you've been claiming, and what I've
been requesting examples of. Please show, for
the "restrictive" use case that `case' fulfills,
corresponding examples of `case' and `pcase'
that demonstrate, in your eyes, that `pcase' is
simpler (or even as simple).
Examples head-to-head for that simple case will
show the differences. So far, you've given only
non-examples of non-`case' syntax, to show the
misunderstanding you've encountered. I've shown
some `case' examples. Please show equivalent,
but in-your-eyes simpler, `pcase' ones. Or show
other examples for the same simple use-case.
It's not about comparing/contrasting `case' and
`pcase' in general. It's about the particular
use case that `case' was designed to address.
How does `pcase' excel there by being simpler?
I haven't argued that `pcase' should go away.
I argue that `case' is better for what it does:
that simple, common, "restrictive" use case.
Please show us otherwise.
But more generally, and perhaps less as a matter
of preference or personal taste, I argue that
it's good to offer _both_ `pcase' and `case' as
part of Emacs, i.e., to treat `case' the way we
treat `cond', `if', `when', ... and `pcase'.
I'm not surprised that some Emacs users have
incorrectly thought that the keylists and keys
get evaluated, and so have mistakenly quoted
them - because, as I just discovered and pointed
out, the Emacs _doc doesn't say_ that they're
not evaluated.
How is a user to know whether something gets
evaluated or not by a macro, if the doc doesn't
speak to that? Do we expect a user discovering
a control structure to immediately macroexpand
guess uses to see what the expansions give? Or
to analyze the macro's definition?
It's perfectly understandable that someone
might just assume evaluation everywhere,
especially since the doc here keeps repeating
"evaluates". The only parts for which it
doesn't say anything about evaluation are the
parts it really needs to say something about:
keys aren't evaluated.
On the other hand, the Common Lisp doc points
out clearly (and even emphasizes) that keys
aren't evaluated.
That doc difference alone could explain why
you've see some Elisp users confused and
mistaken, and why I've never seen that among
CL users (and you apparently haven't either).
Maybe the problem you've noticed was just
caused by our poor `cl-case' doc.
How about we fix the doc and also raise `case'
to first-class citizenship along with its
compatriots?
___
You haven't responded to specific points I've
made - that's your right. But could you at
least please speak to this, which to me seems
to be a bug in the `pcase' node in the Elisp
manual, where it compares `pcase' and `cl-case':
It shows a `pcase' example which starts with
this: (pcase (get-return-code x) ...
"With 'cl-case', you would need to explicitly
declare a local variable 'code' to hold the
return value of 'get-return-code'."
Huh? Does that mean you need to use a variable
as the first arg to `cl-case'? If so, that's
not right.
(defun get-return-code (arg)
(if (< arg 42) 'success 'failure))
(let ((x 13))
(cl-case (get-return-code x)
(success (message "Done!"))
(t (message "Unknown!"))))
==> Done!
And with x bound to 56, ==> Unknown!
We didn't "declare a local variable ... to
hold the return value of `get-return-code'."
...
It's the value returned from evaluating the
sexp (get-return-code x) that `cl-case' tries
to match (using `eql') against symbol `success'.
`cl-case' doesn't need its first arg to be a
"local variable".
Let me know what I'm missing here.
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 17074 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [External] : Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-31 2:45 ` Drew Adams
@ 2022-12-31 4:53 ` Stefan Monnier via Users list for the GNU Emacs text editor
0 siblings, 0 replies; 61+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2022-12-31 4:53 UTC (permalink / raw)
To: help-gnu-emacs
> That's what you've been claiming, and what I've
> been requesting examples of. Please show, for
> the "restrictive" use case that `case' fulfills,
> corresponding examples of `case' and `pcase'
> that demonstrate, in your eyes, that `pcase' is
> simpler (or even as simple).
You've got it backwards. The onus is on you to demonstrate that
`cl-case` syntax is simpler.
You're the one who advocates to have both `pcase` and `cl-case`, based
on the unsubstantiated claim that `cl-case`s syntax is simpler:
> And yes, it's good to have something that handles lots of cases, even
> if that makes understanding the syntax complicated. But that's not
> a reason not to _also_ have a simple syntax for a common, simple use
> case. `pcase' provides the former; `case' provides the latter.
Stefan
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2022-12-29 22:31 ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2023-01-08 4:18 ` Emanuel Berg
2023-01-08 18:54 ` Andreas Eder
0 siblings, 1 reply; 61+ messages in thread
From: Emanuel Berg @ 2023-01-08 4:18 UTC (permalink / raw)
To: help-gnu-emacs
Stefan Monnier via Users list for the GNU Emacs text editor wrote:
>> (let ((lst '()))
>> (cl-pushnew "a" lst)
>> (cl-pushnew "a" lst)
>> lst) ; ("a" "a")
>
> It may sometimes return ("a" "a") but it may also return
> ("a"). Case in point, I think it will do the first when
> interpreted and the second when compiled.
What's the deal with all that, can it be explained easily?
Why is it different?
That's not a good thing, right? I always thought of compiled
as just faster in execution, but computes faster ...
The compiler has some optimization scheme with recurring data
in space and time so the same data ends up at the same place
so is just pushed once?
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: Emacs 30.0 warning from `cl-pushnew' and `memql'
2023-01-08 4:18 ` Emanuel Berg
@ 2023-01-08 18:54 ` Andreas Eder
0 siblings, 0 replies; 61+ messages in thread
From: Andreas Eder @ 2023-01-08 18:54 UTC (permalink / raw)
To: help-gnu-emacs
On So 08 Jan 2023 at 05:18, Emanuel Berg <incal@dataswamp.org> wrote:
> Stefan Monnier via Users list for the GNU Emacs text editor wrote:
>
>>> (let ((lst '()))
>>> (cl-pushnew "a" lst)
>>> (cl-pushnew "a" lst)
>>> lst) ; ("a" "a")
>>
>> It may sometimes return ("a" "a") but it may also return
>> ("a"). Case in point, I think it will do the first when
>> interpreted and the second when compiled.
>
> What's the deal with all that, can it be explained easily?
>
> Why is it different?
>
> That's not a good thing, right? I always thought of compiled
> as just faster in execution, but computes faster ...
>
> The compiler has some optimization scheme with recurring data
> in space and time so the same data ends up at the same place
> so is just pushed once?
I'm nit sure how it is specified to work in elisp. But for common lisp
you are in undefined territory. Since '() is a constant, then after
modifying lst y are generating undefined behaviour.
'Andreas
^ permalink raw reply [flat|nested] 61+ messages in thread
end of thread, other threads:[~2023-01-08 18:54 UTC | newest]
Thread overview: 61+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-26 20:38 Emacs 30.0 warning from `cl-pushnew' and `memql' Emanuel Berg
2022-12-27 6:56 ` Jean Louis
2022-12-27 10:28 ` Michael Heerdegen
2022-12-27 11:33 ` Emanuel Berg
2022-12-27 11:39 ` Emanuel Berg
2022-12-28 3:23 ` [External] : " Drew Adams
2022-12-28 4:23 ` Emanuel Berg
2022-12-29 22:27 ` Drew Adams
2022-12-30 22:27 ` Emanuel Berg
2022-12-30 6:30 ` tomas
2022-12-28 6:25 ` tomas
2022-12-28 11:59 ` Michael Heerdegen
2022-12-28 12:41 ` tomas
2022-12-28 12:45 ` Emanuel Berg
2022-12-28 13:19 ` Emanuel Berg
2022-12-28 14:54 ` Emanuel Berg
2022-12-29 22:31 ` Stefan Monnier via Users list for the GNU Emacs text editor
2023-01-08 4:18 ` Emanuel Berg
2023-01-08 18:54 ` Andreas Eder
2022-12-28 17:57 ` [External] : " Drew Adams
2022-12-28 18:10 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:29 ` Emanuel Berg
2022-12-28 19:35 ` Drew Adams
2022-12-28 19:36 ` tomas
2022-12-28 19:24 ` Emanuel Berg
2022-12-28 17:54 ` Drew Adams
2022-12-28 18:05 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:35 ` Drew Adams
2022-12-29 3:34 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-29 19:06 ` Drew Adams
2022-12-29 19:45 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-29 22:00 ` Drew Adams
2022-12-29 22:25 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-30 7:29 ` Drew Adams
2022-12-30 18:55 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-30 22:55 ` Drew Adams
2022-12-31 0:08 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-31 2:45 ` Drew Adams
2022-12-31 4:53 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-28 19:21 ` Emanuel Berg
2022-12-28 20:24 ` Jean Louis
2022-12-28 20:56 ` Emanuel Berg
2022-12-28 21:24 ` [External] : " Drew Adams
2022-12-28 22:47 ` Jean Louis
2022-12-28 23:48 ` Emanuel Berg
2022-12-29 6:03 ` tomas
2022-12-29 6:59 ` Emanuel Berg
2022-12-29 7:08 ` Emanuel Berg
2022-12-29 7:19 ` Emanuel Berg
2022-12-29 22:41 ` Drew Adams
2022-12-30 23:03 ` Emanuel Berg
2022-12-30 6:35 ` tomas
2022-12-29 9:18 ` Jean Louis
2022-12-29 10:04 ` Emanuel Berg
2022-12-29 10:12 ` tomas
2022-12-29 10:20 ` Emanuel Berg
2022-12-29 10:26 ` Emanuel Berg
2022-12-29 10:36 ` Michael Heerdegen
2022-12-29 14:47 ` Stefan Monnier via Users list for the GNU Emacs text editor
2022-12-29 10:39 ` Michael Heerdegen
2022-12-28 12:44 ` Emanuel Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).