comparison man/lispref/specifiers.texi @ 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 05ed51332340
children ec2d1e636272
comparison
equal deleted inserted replaced
1868:1c5756d02f31 1869:11812ec0334c
36 particular value is valid. 36 particular value is valid.
37 * Retrieving Specifications:: Querying a specifier's specifications. 37 * Retrieving Specifications:: Querying a specifier's specifications.
38 * Specifier Tag Functions:: Working with specifier tags. 38 * Specifier Tag Functions:: Working with specifier tags.
39 * Specifier Instancing Functions:: 39 * Specifier Instancing Functions::
40 Functions to instance a specifier. 40 Functions to instance a specifier.
41 * Specifier Example:: Making all this stuff clearer. 41 * Specifier Examples:: Making all this stuff clearer.
42 * Creating Specifiers:: Creating specifiers for your own use. 42 * Creating Specifiers:: Creating specifiers for your own use.
43 * Specifier Validation Functions:: 43 * Specifier Validation Functions::
44 Validating the components of a specifier. 44 Validating the components of a specifier.
45 * Other Specification Functions:: 45 * Other Specification Functions::
46 Other ways of working with specifications. 46 Other ways of working with specifications.
1044 @var{specifier}. If the instantiation fails, @var{default} is returned. 1044 @var{specifier}. If the instantiation fails, @var{default} is returned.
1045 In most circumstances, you should not use this function; use 1045 In most circumstances, you should not use this function; use
1046 @code{specifier-instance} instead. 1046 @code{specifier-instance} instead.
1047 @end defun 1047 @end defun
1048 1048
1049 @node Specifier Example 1049 @node Specifier Examples
1050 @section Example of Specifier Usage 1050 @section Examples of Specifier Usage
1051 1051
1052 Now let us present an example to clarify the theoretical discussions we 1052 Now let us present an example to clarify the theoretical discussions we
1053 have been through. In this example, we will use the general specifier 1053 have been through. In this example, we will use the general specifier
1054 functions for clarity. Keep in mind that many types of specifiers, and 1054 functions for clarity. Keep in mind that many types of specifiers, and
1055 some other types of objects that are associated with specifiers 1055 some other types of objects that are associated with specifiers
1118 call the instantiation method for colors. This time, the X server 1118 call the instantiation method for colors. This time, the X server
1119 our window is on recognizes the color @samp{moccasin}, and so the 1119 our window is on recognizes the color @samp{moccasin}, and so the
1120 instantiation method succeeds and returns a color instance. 1120 instantiation method succeeds and returns a color instance.
1121 @end enumerate 1121 @end enumerate
1122 1122
1123 Here's another example, which implements something like GNU Emacs's
1124 ``frame-local'' variables.
1125
1126 @example
1127 ;; Implementation
1128
1129 ;; There are probably better ways to write this macro
1130 ;; Heaven help you if VAR is a buffer-local; you will become very
1131 ;; confused. Probably should error on that.
1132 (defmacro define-frame-local-variable (var)
1133 "Make the unbound symbol VAR become a frame-local variable."
1134 (let ((val (if (boundp var) (symbol-value var) nil)))
1135 `(progn
1136 (setq ,var (make-specifier 'generic))
1137 (add-spec-to-specifier ,var ',val 'global))))
1138
1139 ;; I'm not real happy about this terminology, how can `setq' be a defun?
1140 ;; But `frame-set' would have people writing "(frame-set 'foo value)".
1141 (defun frame-setq (var value &optional frame)
1142 "Set the local value of VAR to VALUE in FRAME.
1143
1144 FRAME defaults to the selected frame."
1145 (and frame (not (framep frame))
1146 (error 'invalid-argument "FRAME must be a frame", frame))
1147 (add-spec-to-specifier var value (or frame (selected-frame))))
1148
1149 (defun frame-value (var &optional frame)
1150 "Get the local value of VAR in FRAME.
1151
1152 FRAME defaults to the selected frame."
1153 (and frame (not (framep frame))
1154 (error 'invalid-argument "FRAME must be a frame", frame))
1155 ;; this is not just a map from frames to values; it also falls back
1156 ;; to the global value
1157 (specifier-instance var (or frame (selected-frame))))
1158
1159 ;; for completeness
1160 (defun frame-set-default (var value)
1161 "Set the default value of frame-local variable VAR to VALUE."
1162 (add-spec-to-specifier var value 'global))
1163
1164 (defun frame-get-default (var)
1165 "Get the default value of frame-local variable VAR."
1166 (car (specifier-specs var 'global)))
1167 @end example
1168
1169 Now you can execute the above definitions (eg, with @code{eval-last-sexp})
1170 and switch to @file{*scratch*} to play. Things will work differently if
1171 you already have a variable named @code{foo}.
1172
1173 @example
1174 ;; Usage
1175
1176 foo
1177 @error{} Symbol's value as variable is void: foo
1178
1179 (define-frame-local-variable foo)
1180 @result{} nil
1181
1182 ;; the value of foo is a specifier, which is an opaque object;
1183 ;; you must use accessor functions to get values
1184
1185 foo
1186 @result{} #<generic-specifier global=(nil) 0x4f5cb>
1187
1188 ;; since no frame-local value is set, the global value (which is the
1189 ;; constant `nil') is returned
1190 (frame-value foo)
1191 @result{} nil
1192
1193 ;; get the default explicitly
1194 (frame-get-default foo)
1195 @result{} nil
1196
1197 ;; get the whole specification list
1198 (specifier-specs foo 'global)
1199 @result{} (nil)
1200
1201 ;; give foo a frame-local value
1202
1203 (frame-setq foo 'bar)
1204 @result{} nil
1205
1206 ;; access foo in several ways
1207
1208 ;; Note that the print function for this kind of specifier only
1209 ;; gives you the global setting. To get the full list of specs for
1210 ;; debugging or study purposes, you must use specifier-specs or
1211 ;; specifier-spec-list.
1212 foo
1213 @result{} #<generic-specifier global=(nil) 0x4f5cb>
1214
1215 ;; get the whole specification list
1216 (specifier-specs foo)
1217 @result{} ((#<x-frame "Message" 0x1bd66> (nil . bar)) (global (nil)))
1218
1219 ;; get the frame-local value
1220 (frame-value foo)
1221 @result{} bar
1222
1223 ;; get the default explicitly
1224 (frame-get-default foo)
1225 @result{} nil
1226
1227 ;; Switch to another frame and evaluate:
1228 ;; C-x 5 o M-: (frame-setq foo 'baz) RET M-: (frame-value foo) RET
1229 @result{} baz
1230
1231 ;; Switch back.
1232 ;; C-x 5 o
1233 (specifier-specs foo)
1234 @result{} ((#<x-frame "emacs" 0x28ec> (nil . baz))
1235 (#<x-frame "Message" 0x1bd66> (nil . bar))
1236 (global (nil)))
1237
1238 (frame-value foo)
1239 @result{} bar
1240
1241 (frame-get-default foo)
1242 @result{} nil
1243 @end example
1244
1245 Note that since specifiers generalize both frame-local and buffer-local
1246 variables in a sensible way, XEmacs is not likely to put a high priority
1247 on implementing frame-local variables.
1248 @c Thanks to Jerry James for the following explanation. He is not
1249 @c responsible for its use here, Stephen Turnbull is.
1250 In fact, some developers think that frame-local variables are evil for
1251 the same reason that buffer-local variables are evil: the declaration is
1252 both global and invisible. That is, you cannot tell whether a variable
1253 is ``normal,'' buffer-local, or frame-local just by looking at it. So
1254 if you have namespace management problems, and some other Lisp package
1255 happens to use a variable name that you already declared frame- or
1256 buffer-local, weird stuff happens, and it is extremely hard to track
1257 down.
1258
1259
1123 @node Creating Specifiers 1260 @node Creating Specifiers
1124 @section Creating New Specifier Objects 1261 @section Creating New Specifier Objects
1125 1262
1126 @defun make-specifier type 1263 @defun make-specifier type
1127 This function creates a new specifier. 1264 This function creates a new specifier.