Package: emacs;
Reported by: "Drew Adams" <drew.adams <at> oracle.com>
Date: Fri, 9 Jul 2010 15:53:01 UTC
Severity: minor
Found in version 24.0.50
Done: Chong Yidong <cyd <at> stupidchicken.com>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: MON KEY <monkey <at> sandpframing.com> To: 6591 <at> debbugs.gnu.org Subject: bug#6591: 24.0.50; incorrect doc for `catch' Date: Sat, 10 Jul 2010 01:44:40 -0400
,---- | The description is not consistent and clear. In particular, this | part: | | "With the return point in effect, `catch' evaluates the forms of | the BODY in textual order. If the forms execute normally (without | error or nonlocal exit) the value of the last body form is | returned from the `catch'." | | "The forms of the BODY" is problematic - which BODY? And it's | incorrect. The forms within a BODY are not necessarily evaled in | textual order. `---- Given that the Emacs Lisp dialect is described as being derived from Maclisp and being a Lisp2 in some respects resembles Common Lisp the following excerpts may of interest/relevance: ---- Following from the Pitmanual "Sunday Morning Edition" The Revised Maclisp Manual Page A-5 :SOURCE (URL `http://maclisp.info/pitmanual/contro.html#5.13.3') CATCH Special Form (CATCH form [tag]) CATCH is an archaic (destined to become obsolete) special form for doing structured non-local exits. See documentation on its replacement, *CATCH. CATCH forms can be translated to *CATCH as follows: old new (CATCH form tag) (*CATCH 'tag form) (CATCH form) (*CATCH NIL form). Historically, (CATCH form) evolved to handle the fact that programmers were using (ERRSET (...(ERR)...)) to accomplish non-local returns since there was once no other way to get that functionality. CATCH and THROW were introduced so that programmers could write (CATCH (...(THROW val)...)) instead where there was really no error condition. However, it was found that confusion would often result using unlabelled CATCH/THROW because an unlablled CATCH could catch a throw it hadn't intended to. This is why named CATCH was invented. It is strongly recommended, therefore, that if you are re-writing (CATCH form) to a *CATCH according to the above rules, you also go to the extra trouble to choose some tag. This is not as easy because it involves changing related THROW's in the same module to all use the same tag (and perhaps other CATCH's, or even some *THROW's and/or *CATCH's), but it'll enhance the reliability of your code quite a lot. See also: *CATCH, CATCH-BARRIER, CATCHALL, THROW, ERRSET THROW Special Form (THROW form [tag]) THROW is an archaic (destined to become obsolete) special form. See documentation on its replacement, *THROW. THROW forms can be translated to *THROW as follows: old new (THROW form tag) (*THROW 'tag form). (THROW form) (*THROW NIL form). See also: *THROW, CATCH, ERR ;;; ============================== Following from an unofficial version of dpans3-texi of ANSI Common Lisp: catch (Special Operator) Syntax: -- Special Form: catch TAG {form}* → {result}* Arguments and Values: TAG--a catch tag; evaluated. FORMS--an implicit progn. RESULTS--if the FORMS exit normally, the values returned by the FORMS; if a throw occurs to the TAG, the values that are thrown. Description: ‘catch’ is used as the destination of a non-local control transfer by ‘throw’. TAGS are used to find the ‘catch’ to which a ‘throw’ is transferring control. ‘(catch 'foo form)’ catches a ‘(throw 'foo form)’ but not a ‘(throw 'bar form)’. The order of execution of ‘catch’ follows: 1. TAG is evaluated. It serves as the name of the ‘catch’. 2. FORMS are then evaluated as an implicit ‘progn’, and the results of the last FORM are returned unless a ‘throw’ occurs. 3. If a ‘throw’ occurs during the execution of one of the FORMS, control is transferred to the ‘catch’ form whose TAG is ‘eq’ to the tag argument of the ‘throw’ and which is the most recently established ‘catch’ with that TAG. No further evaluation of FORMS occurs. 4. The TAG established by ‘catch’ is disestablished just before the results are returned. If during the execution of one of the FORMS, a ‘throw’ is executed whose tag is ‘eq’ to the ‘catch’ tag, then the values specified by the ‘throw’ are returned as the result of the dynamically most recently established ‘catch’ form with that tag. The mechanism for ‘catch’ and ‘throw’ works even if ‘throw’ is not within the lexical scope of ‘catch’. ‘throw’ must occur within the dynamic extent of the evaluation of the body of a ‘catch’ with a corresponding TAG. Examples: (catch 'dummy-tag 1 2 (throw 'dummy-tag 3) 4) → 3 (catch 'dummy-tag 1 2 3 4) → 4 (defun throw-back (tag) (throw tag t)) → THROW-BACK (catch 'dummy-tag (throw-back 'dummy-tag) 2) → T ;; Contrast behavior of this example with corresponding example of BLOCK. (catch 'c (flet ((c1 () (throw 'c 1))) (catch 'c (c1) (print 'unreachable)) 2)) → 2 Exceptional Situations: An error of type ‘control-error’ is signaled if ‘throw’ is done when there is no suitable ‘catch’ TAG. See Also: throw Notes: It is customary for symbols to be used as TAGS, but any object is permitted. However, numbers should not be used because the comparison is done using ‘eq’. ‘catch’ differs from ‘block’ in that ‘catch’ tags have dynamic scope while ‘block’ names have lexical scope. -- throw (Special Operator) Syntax: -- Special Form: throw tag result-form →| Arguments and Values: TAG--a catch tag; evaluated. RESULT-FORM--a form; evaluated as described below. Description: ‘throw’ causes a non-local control transfer to a ‘catch’ whose tag is ‘eq’ to TAG. TAG is evaluated first to produce an object called the throw tag; then RESULT-FORM is evaluated, and its results are saved. If the RESULT-FORM produces multiple values, then all the values are saved. The most recent outstanding ‘catch’ whose TAG is ‘eq’ to the throw tag is exited; the saved results are returned as the value or values of ‘catch’. The transfer of control initiated by ‘throw’ is performed as described in Section 5.2. Examples: (catch 'result (setq i 0 j 0) (loop (incf j 3) (incf i) (if (= i 3) (throw 'result (values i j))))) → 3, 9 (catch nil (unwind-protect (throw nil 1) (throw nil 2))) → 2 The consequences of the following are undefined because the ‘catch’ of ‘b’ is passed over by the first ‘throw’, hence portable programs must assume that its dynamic extent is terminated. The binding of the catch tag is not yet disestablished and therefore it is the target of the second ‘throw’. (catch 'a (catch 'b (unwind-protect (throw 'a 1) (throw 'b 2)))) The following prints "‘The inner catch returns :SECOND-THROW’" and then returns ‘:outer-catch’. (catch 'foo (format t "The inner catch returns ~s.~%" (catch 'foo (unwind-protect (throw 'foo :first-throw) (throw 'foo :second-throw)))) :outer-catch) ▷ The inner catch returns :SECOND-THROW → :OUTER-CATCH Exceptional Situations: If there is no outstanding catch tag that matches the throw tag, no unwinding of the stack is performed, and an error of type ‘control-error’ is signaled. When the error is signaled, the dynamic environment is that which was in force at the point of the ‘throw’. See Also: block, catch, return-from, unwind-protect Notes: ‘catch’ and ‘throw’ are normally used when the exit point must have dynamic scope (e.g., the ‘throw’ is not lexically enclosed by the ‘catch’), while ‘block’ and ‘return’ are used when lexical scope is sufficient. -- /s_P\
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.