GNU bug report logs - #13126
24.3.50; (WISH) Document pcase in Info manual

Previous Next

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.

Full log


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




This bug report was last modified 12 years and 112 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.