GNU bug report logs -
#68029
29.1; (elisp) `pcase Macro': misleading mention of `cl-case'
Previous Next
Reported by: Drew Adams <drew.adams <at> oracle.com>
Date: Mon, 25 Dec 2023 16:27:02 UTC
Severity: normal
Found in version 29.1
Done: Stefan Kangas <stefankangas <at> gmail.com>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 68029 in the body.
You can then email your comments to 68029 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#68029
; Package
emacs
.
(Mon, 25 Dec 2023 16:27:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Drew Adams <drew.adams <at> oracle.com>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Mon, 25 Dec 2023 16:27:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
I find this comment misleading/incorrect:
With 'cl-case', you would need to explicitly declare a local variable
'code' to hold the return value of 'get-return-code'. Also 'cl-case' is
difficult to use with strings because it uses 'eql' for comparison.
In fact, with `cl-case' the code is at least as simple:
(let* ((val (get-return-code x)))
(if (stringp val) (message val)
(cl-case val
(success (message "Done!"))
(would-block (message "Sorry, can't do it now"))
(read-only (message "The shmliblick is read-only"))
(access-denied (message "You do not have the needed rights"))
(val (message "You do not have the needed rights")))))
Yes, it's true that comparison is with `eql', so for a string value you
need to test that separately (or intern and then test symbols with
`cl-case'). But there's no need to use any `code' variable.
If you can't come up with a better example to show advantages of `pcase'
over `cl-case' (and that should be easy to do), then don't say anything
about `cl-case'. Or maybe just tell the truth: `cl-case' handles _one
simple `pcase' use case_ in a simpler way. IOW, if you're just testing
equality of the expression's value against particular symbols then
`cl-case' is simpler and clearer.
Even clearer is just this (same for the `pcase' example):
(message
(let* ((val (get-return-code x)))
(if (stringp val) val
(cl-case val
(success "Done!")
(would-block "Sorry, can't do it now")
(read-only "The shmliblick is read-only")
(access-denied "You do not have the needed rights")
(val "You do not have the needed rights")))))
(And you've presumably misspelled schmilblick ;-):
https://en.wikipedia.org/wiki/Schmilblick)
In GNU Emacs 29.1 (build 2, x86_64-w64-mingw32) of 2023-08-02 built on
AVALON
Windowing system distributor 'Microsoft Corp.', version 10.0.19045
System Description: Microsoft Windows 10 Pro (v10.0.2009.19045.3803)
Configured using:
'configure --with-modules --without-dbus --with-native-compilation=aot
--without-compress-install --with-tree-sitter CFLAGS=-O2'
Configured features:
ACL GIF GMP GNUTLS HARFBUZZ JPEG JSON LCMS2 LIBXML2 MODULES NATIVE_COMP
NOTIFY W32NOTIFY PDUMPER PNG RSVG SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP XPM ZLIB
(NATIVE_COMP present but libgccjit not available)
Reply sent
to
Stefan Kangas <stefankangas <at> gmail.com>
:
You have taken responsibility.
(Mon, 25 Dec 2023 16:55:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Drew Adams <drew.adams <at> oracle.com>
:
bug acknowledged by developer.
(Mon, 25 Dec 2023 16:55:02 GMT)
Full text and
rfc822 format available.
Message #10 received at 68029-done <at> debbugs.gnu.org (full text, mbox):
Drew Adams <drew.adams <at> oracle.com> writes:
> I find this comment misleading/incorrect:
>
> With 'cl-case', you would need to explicitly declare a local variable
> 'code' to hold the return value of 'get-return-code'. Also 'cl-case' is
> difficult to use with strings because it uses 'eql' for comparison.
>
> In fact, with `cl-case' the code is at least as simple:
>
> (let* ((val (get-return-code x)))
> (if (stringp val) (message val)
> (cl-case val
> (success (message "Done!"))
> (would-block (message "Sorry, can't do it now"))
> (read-only (message "The shmliblick is read-only"))
> (access-denied (message "You do not have the needed rights"))
> (val (message "You do not have the needed rights")))))
>
> Yes, it's true that comparison is with `eql', so for a string value you
> need to test that separately (or intern and then test symbols with
> `cl-case'). But there's no need to use any `code' variable.
This shows that you do need to use a `code' variable (you named it `val'
though), and that the pcase version is indeed better.
> If you can't come up with a better example to show advantages of `pcase'
> over `cl-case' (and that should be easy to do), then don't say anything
> about `cl-case'. Or maybe just tell the truth: `cl-case' handles _one
> simple `pcase' use case_ in a simpler way. IOW, if you're just testing
> equality of the expression's value against particular symbols then
> `cl-case' is simpler and clearer.
No, the reality is that `pcase' has *many* advantages over `cl-case'.
The example is just intended to showcase some of them.
> Even clearer is just this (same for the `pcase' example):
>
> (message
> (let* ((val (get-return-code x)))
> (if (stringp val) val
> (cl-case val
> (success "Done!")
> (would-block "Sorry, can't do it now")
> (read-only "The shmliblick is read-only")
> (access-denied "You do not have the needed rights")
> (val "You do not have the needed rights")))))
I'm not sure that's indeed easier for a beginner ELisp developer to
follow. So I don't think it's worth making that change.
> (And you've presumably misspelled schmilblick ;-):
> https://en.wikipedia.org/wiki/Schmilblick)
I don't follow, sorry.
So I'm closing this bug report.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#68029
; Package
emacs
.
(Tue, 26 Dec 2023 17:47:02 GMT)
Full text and
rfc822 format available.
Message #13 received at 68029-done <at> debbugs.gnu.org (full text, mbox):
> > I find this comment misleading/incorrect:
> >
> > With 'cl-case', you would need to explicitly declare a
> > local variable 'code' to hold the return value of
> > 'get-return-code'. Also 'cl-case' is difficult to use
> > with strings because it uses 'eql' for comparison.
> >
> > In fact, with `cl-case' the code is at least as simple:
> >
> > (let* ((val (get-return-code x)))
> > (if (stringp val) (message val)
> > (cl-case val
> > (success (message "Done!"))
> > (would-block (message "Sorry, can't do it now"))
> > (read-only (message "The shmliblick is read-only"))
> > (access-denied (message "You do not have the needed rights"))
> > (val (message "You do not have the needed rights")))))
> >
> > Yes, it's true that comparison is with `eql',
> > so for a string value you need to test that
> > separately (or intern and then test symbols
> > with `cl-case'). But there's no need to use
> > any `code' variable.
>
> This shows that you do need to use a `code' variable (you named
> it `val' though), and that the pcase version is indeed better.
Are you missing the fact that with the `pcase'
version you use an `msg' variable, as well as
a `code' variable? And with the `case' version
you have only the `val' variable? 1 var, not 2.
One traditional way of showing variables in Lisp
pattern matching is to use a syntax convention
(sometimes more than a convention - actually
parsed) of, say, a `?' prefix.
The `pcase version is, in effect this, if you
make explicit the symbols bound as vars:
(pcase (get-return-code x)
;; string
((and (pred stringp) ?MSG) ; <===
(message "%s" ?MSG)) ; <===
;; symbol
('success (message "Done!"))
('would-block (message "Sorry, can't do it now"))
('read-only (message "The shmliblick is read-only"))
('access-denied (message "You do not have the needed rights"))
;; default
(?CODE ; <===
(message "Unknown return code %S" ?CODE))) ; <===
`pcase' syntax has chosen to quote non-vars, so
instead of two variables indicated syntactically
with `?' as `?msg' and `?code' it uses the four
quoted non-vars `'success', `'would-block',
`'read-only', and `'access-denied'. More noise
_in this case_, not less.
[You may note, BTW, that `pcase' doesn't quote
non-vars in all contexts: `(pred stringp)',
not `(pred 'stringp)'.]
Again, it's not to say that `pcase's choice of
quoting non-vars instead of using explicit var
syntax is worse. It's to say that this example
_doesn't show off `pcase' as advantageous_ - it
does just the opposite.
I'm not saying the `pcase' syntax can't be a
workable/reasonable choice. That _could be
shown_ with a different example. This example
isn't a good one to show the advantages of
`pcase'. It shows `pcase' as worse, not better.
Try again.
None of the examples given show the advantages
of `pcase'. Such advantages should start with
DESTRUCTURING - the ONE thing you _don't_ have
built-in with the existing Elisp binding forms
or conditional forms. Start with a simple
destructuring example: `case'-like, but with
destructuring. That's my advice.
Destructuring is the easiest & most powerful
`pcase' feature to introduce, and it's not
really shown. It's glossed over, at best.
Show beginners that, to start with.
In a nutshell, `pase-let' vs `let' is really
the place to start. _Then_ add conditional
control into the mix.
It's as if someone only tried to explain away
some of what is particularly confusing about
`pcase', instead of teaching the strengths of
`pcase'.
Looks like doc written after a user complained
that some previous `pcase' doc didn't explain
some complicated aspects, so an attempt was
made to do only that, skipping the basics.
I don't claim that's really how we got the doc
we got. I'm just saying it smells like that.
> > If you can't come up with a better example to
> > show advantages of `pcase' over `cl-case' (and
> > that should be easy to do), then don't say
> > anything about `cl-case'. Or maybe just tell
> > the truth: `cl-case' handles _one simple
> > `pcase' use case_ in a simpler way. IOW, if
> > you're just testing equality of the expression's
> > value against particular symbols then `cl-case'
> > is simpler and clearer.
>
> No, the reality is that `pcase' has *many* advantages over `cl-case'.
> The example is just intended to showcase some of them.
Sure it has advantages over `case'! No one would
argue otherwise. You're missing the point: This
doc _doesn't show_ ANY of the advantages.
Don't show `pcase' trying to compete where `case'
or `if' is clearer & simpler. No-brainer.
Show the strengths of `pcase'. Don't just show
how to translate a trivial `if' form (with single
THEN and single ELSE sexps, no less!) to a more
verbose and complex `pcase' equivalent.
The only thing _shown_ is that `pcase' gives you
more complicated syntax to do what you can do
simpler with `if'! Just the opposite from what,
I assume/hope, we intended to show.
If you don't yet get that this is poor doc, and
it does a big DISservice to `pcase', so be it.
> > > (read-only "The shmliblick is read-only")
> >
> > (And you've presumably misspelled schmilblick ;-):
> > ^ ^^
> > https://en.wikipedia.org/wiki/Schmilblick)
>
> I don't follow, sorry.
Did you try? Is it hard to see those typos?
> I'm not sure that's indeed easier for a beginner
> ELisp developer to follow. So I don't think it's
> worth making that change. So I'm closing this bug report.
Not surprised. With luck, someone with a
different name than mine may help you see.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Wed, 24 Jan 2024 12:24:05 GMT)
Full text and
rfc822 format available.
This bug report was last modified 1 year and 197 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.