changeset 1869:11812ec0334c

[xemacs-hg @ 2004-01-21 09:03:42 by stephent] email change <87vfn5zndg.fsf@tleepslib.sk.tsukuba.ac.jp> specifier example <8765f62dl0.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Wed, 21 Jan 2004 09:03:47 +0000
parents 1c5756d02f31
children 375ec21c9374
files man/ChangeLog man/lispref/lispref.texi man/lispref/specifiers.texi man/xemacs-faq.texi
diffstat 4 files changed, 155 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/man/ChangeLog	Tue Jan 20 22:51:19 2004 +0000
+++ b/man/ChangeLog	Wed Jan 21 09:03:47 2004 +0000
@@ -1,3 +1,15 @@
+2004-01-20  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* lispref/specifiers.texi (Specifier Examples): Add new example,
+	pluralize node name and section title.
+	(Specifiers): Pluralize "Specifier Examples" in menu.
+
+	* lispref/lispref.texi (Top): Pluralize "Specifier Examples" in menu.
+
+2003-11-04  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* xemacs-faq.texi: Fix Tony Rossini's address.
+
 2003-12-15  Steve Youngs  <sryoungs@bigpond.net.au>
 
 	* lispref/customize.texi (Defining New Types): New node.
--- a/man/lispref/lispref.texi	Tue Jan 20 22:51:19 2004 +0000
+++ b/man/lispref/lispref.texi	Wed Jan 21 09:03:47 2004 +0000
@@ -946,7 +946,7 @@
 * Retrieving Specifications::	Querying a specifier's specifications.
 * Specifier Instancing Functions::
 				Functions to instance a specifier.
-* Specifier Example::		Making all this stuff clearer.
+* Specifier Examples::		Making all this stuff clearer.
 * Creating Specifiers::		Creating specifiers for your own use.
 * Specifier Validation Functions::
 				Validating the components of a specifier.
--- a/man/lispref/specifiers.texi	Tue Jan 20 22:51:19 2004 +0000
+++ b/man/lispref/specifiers.texi	Wed Jan 21 09:03:47 2004 +0000
@@ -38,7 +38,7 @@
 * Specifier Tag Functions::     Working with specifier tags.
 * Specifier Instancing Functions::
                                 Functions to instance a specifier.
-* Specifier Example::           Making all this stuff clearer.
+* Specifier Examples::          Making all this stuff clearer.
 * Creating Specifiers::         Creating specifiers for your own use.
 * Specifier Validation Functions::
                                 Validating the components of a specifier.
@@ -1046,8 +1046,8 @@
 @code{specifier-instance} instead.
 @end defun
 
-@node Specifier Example
-@section Example of Specifier Usage
+@node Specifier Examples
+@section Examples of Specifier Usage
 
 Now let us present an example to clarify the theoretical discussions we
 have been through.  In this example, we will use the general specifier
@@ -1120,6 +1120,143 @@
 instantiation method succeeds and returns a color instance.
 @end enumerate
 
+Here's another example, which implements something like GNU Emacs's
+``frame-local'' variables.
+
+@example
+;; Implementation
+
+;; There are probably better ways to write this macro
+;; Heaven help you if VAR is a buffer-local; you will become very
+;; confused.  Probably should error on that.
+(defmacro define-frame-local-variable (var)
+  "Make the unbound symbol VAR become a frame-local variable."
+  (let ((val (if (boundp var) (symbol-value var) nil)))
+    `(progn
+      (setq ,var (make-specifier 'generic))
+      (add-spec-to-specifier ,var ',val 'global))))
+
+;; I'm not real happy about this terminology, how can `setq' be a defun?
+;; But `frame-set' would have people writing "(frame-set 'foo value)".
+(defun frame-setq (var value &optional frame)
+  "Set the local value of VAR to VALUE in FRAME.
+
+FRAME defaults to the selected frame."
+  (and frame (not (framep frame))
+       (error 'invalid-argument "FRAME must be a frame", frame))
+  (add-spec-to-specifier var value (or frame (selected-frame))))
+
+(defun frame-value (var &optional frame)
+  "Get the local value of VAR in FRAME.
+
+FRAME defaults to the selected frame."
+  (and frame (not (framep frame))
+       (error 'invalid-argument "FRAME must be a frame", frame))
+  ;; this is not just a map from frames to values; it also falls back
+  ;; to the global value
+  (specifier-instance var (or frame (selected-frame))))
+
+;; for completeness
+(defun frame-set-default (var value)
+  "Set the default value of frame-local variable VAR to VALUE."
+  (add-spec-to-specifier var value 'global))
+
+(defun frame-get-default (var)
+  "Get the default value of frame-local variable VAR."
+  (car (specifier-specs var 'global)))
+@end example
+
+Now you can execute the above definitions (eg, with @code{eval-last-sexp})
+and switch to @file{*scratch*} to play.  Things will work differently if
+you already have a variable named @code{foo}.
+
+@example
+;; Usage
+
+foo
+@error{} Symbol's value as variable is void: foo
+
+(define-frame-local-variable foo)
+@result{} nil
+
+;; the value of foo is a specifier, which is an opaque object;
+;; you must use accessor functions to get values
+
+foo
+@result{} #<generic-specifier global=(nil) 0x4f5cb>
+
+;; since no frame-local value is set, the global value (which is the
+;; constant `nil') is returned
+(frame-value foo)
+@result{} nil
+
+;; get the default explicitly
+(frame-get-default foo)
+@result{} nil
+
+;; get the whole specification list
+(specifier-specs foo 'global)
+@result{} (nil)
+
+;; give foo a frame-local value
+
+(frame-setq foo 'bar)
+@result{} nil
+
+;; access foo in several ways
+
+;; Note that the print function for this kind of specifier only
+;; gives you the global setting.  To get the full list of specs for
+;; debugging or study purposes, you must use specifier-specs or
+;; specifier-spec-list.
+foo
+@result{} #<generic-specifier global=(nil) 0x4f5cb>
+
+;; get the whole specification list
+(specifier-specs foo)
+@result{} ((#<x-frame "Message" 0x1bd66> (nil . bar)) (global (nil)))
+
+;; get the frame-local value
+(frame-value foo)
+@result{} bar
+
+;; get the default explicitly
+(frame-get-default foo)
+@result{} nil
+
+;; Switch to another frame and evaluate:
+;; C-x 5 o M-: (frame-setq foo 'baz) RET M-: (frame-value foo) RET
+@result{} baz
+
+;; Switch back.
+;; C-x 5 o
+(specifier-specs foo)
+@result{} ((#<x-frame "emacs" 0x28ec> (nil . baz))
+    (#<x-frame "Message" 0x1bd66> (nil . bar))
+    (global (nil)))
+
+(frame-value foo)
+@result{} bar
+
+(frame-get-default foo)
+@result{} nil
+@end example
+
+Note that since specifiers generalize both frame-local and buffer-local
+variables in a sensible way, XEmacs is not likely to put a high priority
+on implementing frame-local variables.
+@c Thanks to Jerry James for the following explanation.  He is not
+@c responsible for its use here, Stephen Turnbull is.
+In fact, some developers think that frame-local variables are evil for
+the same reason that buffer-local variables are evil: the declaration is
+both global and invisible.  That is, you cannot tell whether a variable
+is ``normal,'' buffer-local, or frame-local just by looking at it.  So
+if you have namespace management problems, and some other Lisp package
+happens to use a variable name that you already declared frame- or
+buffer-local, weird stuff happens, and it is extremely hard to track
+down.
+
+
 @node Creating Specifiers
 @section Creating New Specifier Objects
 
--- a/man/xemacs-faq.texi	Tue Jan 20 22:51:19 2004 +0000
+++ b/man/xemacs-faq.texi	Wed Jan 21 09:03:47 2004 +0000
@@ -7,9 +7,9 @@
 @finalout
 @titlepage
 @title XEmacs FAQ
-@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2003/10/10 12:39:27 $
+@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2004/01/21 09:03:42 $
 @sp 1
-@author Tony Rossini <rossini@@biostat.washington.edu>
+@author Tony Rossini <rossini@@u.washington.edu>
 @author Ben Wing <ben@@xemacs.org>
 @author Chuck Thompson <cthomp@@xemacs.org>
 @author Steve Baur <steve@@xemacs.org>