From: Jambunathan K <kjambunathan@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: 13126@debbugs.gnu.org
Subject: bug#13126: 24.3.50; (WISH) Document pcase in Info manual
Date: Thu, 13 Dec 2012 20:31:57 +0530 [thread overview]
Message-ID: <87fw3a2dy2.fsf@gmail.com> (raw)
In-Reply-To: <jwv8v94ae7n.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Tue, 11 Dec 2012 08:55:34 -0500")
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> Thanks. `pcase' seemed a good replacement for `case'.
>
> While it's not a plug-in replacement, it provides a superset of the
> features of case, yes.
pcase also reminds me of CL's case. Btw, you know in what version of
Emacs did pcase made it's appearance.
>> 1. pcase-let, pcase-let*, pcase-dolist (maybe)
>
> pcase-dolist shouldn't be documented (yet?). Maybe pcase-let and
> pcase-let* should be there, indeed.
>
pcase-let reminds me of `destructuring-bind'.
Here is a real-life example of pcase-let in action from midnight.el.
Good for instructive purposes.
(defun midnight-next ()
"Return the number of seconds till the next midnight."
(pcase-let ((`(,sec ,min ,hrs) (decode-time)))
(- (* 24 60 60) (* 60 60 hrs) (* 60 min) sec)))
>> 2. It took some effort to understand that there is a U-PATTERN and a
>> UPATTERN. We don't read out `*-*', do we?
>> ,----
>> | There are two kinds of patterns involved in `pcase', called
>> | _U-patterns_ and _Q-patterns_. The UPATTERN mentioned above are
>> | U-patterns and can take the following forms:
>> `----
Provide a BNF and document TERMINALS before NON-TERMINALS. (Currently it
seems other way round).
Docstring for pcase has more info (pred FUNCTION) apropos the arguments
passed to it. Possibly there are other things...
> What do you suggest instead?
Here is my recommendation.
May be replace the example snippets with a /simple/ and /cohesive/
example. I found Snippet 2 "too abstract" and leaves a lot to the
imagination of the reader.
I just hacked a working REPL based on pcase. See below. We can include
these after
`repl' will act as a good replacement for Snippet 1. `repl-eval' will
act as a good replacement for Snippet 2.
M-x repl RET for a reader to toy with.
,---- Snippet 1
| (pcase (get-return-code x)
| (`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"))
| (code (message "Unknown return code %S" code)))
`----
,---- Snippet 2
| (defun evaluate (exp env)
| (pcase exp
| (`(add ,x ,y) (+ (evaluate x env) (evaluate y env)))
| (`(call ,fun ,arg) (funcall (evaluate fun) (evaluate arg env)))
| (`(fn ,arg ,body) (lambda (val)
| (evaluate body (cons (cons arg val) env))))
| ((pred numberp) exp)
| ((pred symbolp) (cdr (assq exp env)))
| (_ (error "Unknown expression %S" exp))))
`----
(let ((repl-dictionary '()))
(repl-eval '((x = "happy")
(y = "HACKING")
(n = 2013)
(z = (upcase-initials x + space +
(downcase y) + tab + 2013)))))
(defvar repl-dictionary '()
"Symbol table for `repl'.")
(defun repl-eval (exp)
(pcase exp
;; In-built constants.
(`space " ")
(`tab "\t")
;; Add operator. Concatenate.
(`(,x + . ,y) (concat (repl-eval x ) (repl-eval y)))
;; Assignment operator. Update dictionary.
(`(,x = . ,body) (let* ((value (repl-eval body))
(entry (assoc x repl-dictionary)))
(if (not entry)
;; Add variable & value.
(push (cons x value) repl-dictionary)
;; Update value.
(setcdr entry value))
value))
;; Function. Assume it takes a string as it's only arg. Call it.
(`(,(and (pred functionp) f) . ,x) (funcall f (repl-eval x)))
;; Last of body forms. Return it's value.
(`(,x . nil)
(repl-eval x))
;; Body forms. Evaluate in sequence. Return value of last of
;; the forms.
(`(,x . ,y) (repl-eval x) (repl-eval y))
;; String, just return it.
((pred stringp) exp)
;; Number, cast it to string.
((pred numberp) (number-to-string exp))
;; Symbol, lookup it's value in dictionary.
((pred symbolp) (or (cdr (assoc exp repl-dictionary))
(error "Variable `%s' not bound" exp)))
(_ (error "Unknown expression %S" exp))))
(defun repl ()
"Simple REPL for string operations.
Expression syntax:
In-built Constants : space
: tab
Assignment : x = \"hello\"
: y = \"world\"
Casting : n = 2012
Concatenation : x + space + y + space + n
Unary functions : (upcase-initials x)
Commands:
exit => Quit
clear => Unbind all variables
examine => Examine currently defined variables."
(interactive)
(let ((repl-dictionary '())
(prompt "STRING-REPL> ")
(result nil))
(while (pcase (read-from-minibuffer prompt)
(input
(pcase input
("exit" (setq result nil))
("clear" (setq repl-dictionary '()
result "[CLEARED]"))
("examine" (setq result (format "%S" repl-dictionary)))
(_ (let ((exp (read (format "(%s)" input))))
(setq result (condition-case err
(repl-eval exp)
(error (format "%s" err)))))))
(when result
(minibuffer-message
(concat prompt input
(propertize "\t" 'display
(list 'space :align-to 40))
(propertize result 'face 'highlight))))))
(setq result nil))))
next prev parent reply other threads:[~2012-12-13 15:01 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-09 9:28 bug#13126: 24.3.50; (WISH) Document pcase in Info manual Jambunathan K
2012-12-09 17:12 ` Stefan Monnier
2012-12-11 10:20 ` Jambunathan K
2012-12-11 13:55 ` Stefan Monnier
2012-12-13 15:01 ` Jambunathan K [this message]
2012-12-13 17:37 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fw3a2dy2.fsf@gmail.com \
--to=kjambunathan@gmail.com \
--cc=13126@debbugs.gnu.org \
--cc=monnier@iro.umontreal.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.