unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#68029: 29.1; (elisp) `pcase Macro': misleading mention of `cl-case'
@ 2023-12-25 16:26 Drew Adams
  2023-12-25 16:53 ` Stefan Kangas
  0 siblings, 1 reply; 3+ messages in thread
From: Drew Adams @ 2023-12-25 16:26 UTC (permalink / raw)
  To: 68029

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)






^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#68029: 29.1; (elisp) `pcase Macro': misleading mention of `cl-case'
  2023-12-25 16:26 bug#68029: 29.1; (elisp) `pcase Macro': misleading mention of `cl-case' Drew Adams
@ 2023-12-25 16:53 ` Stefan Kangas
  2023-12-26 17:46   ` Drew Adams
  0 siblings, 1 reply; 3+ messages in thread
From: Stefan Kangas @ 2023-12-25 16:53 UTC (permalink / raw)
  To: Drew Adams, 68029-done

Drew Adams <drew.adams@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.





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#68029: 29.1; (elisp) `pcase Macro': misleading mention of `cl-case'
  2023-12-25 16:53 ` Stefan Kangas
@ 2023-12-26 17:46   ` Drew Adams
  0 siblings, 0 replies; 3+ messages in thread
From: Drew Adams @ 2023-12-26 17:46 UTC (permalink / raw)
  To: Stefan Kangas, 68029-done@debbugs.gnu.org

> > 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.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-12-26 17:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-25 16:26 bug#68029: 29.1; (elisp) `pcase Macro': misleading mention of `cl-case' Drew Adams
2023-12-25 16:53 ` Stefan Kangas
2023-12-26 17:46   ` Drew Adams

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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).