Package: emacs;
Reported by: Jambunathan K <kjambunathan <at> gmail.com>
Date: Sun, 9 Dec 2012 09:27:01 UTC
Severity: minor
Merged with 12752
Found in version 24.3.50
Fixed in version 24.3
Done: Glenn Morris <rgm <at> gnu.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Jambunathan K <kjambunathan <at> gmail.com> To: Stefan Monnier <monnier <at> iro.umontreal.ca> Cc: 13126 <at> debbugs.gnu.org Subject: bug#13126: 24.3.50; (WISH) Document pcase in Info manual Date: Thu, 13 Dec 2012 20:31:57 +0530
Stefan Monnier <monnier <at> 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))))
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.