[Date Prev][Date Next][Subject Prev][Subject Next][ Date Index][ Subject Index]

Re: Clearsgts



** Reply to message from Harry Binswanger  on Mon, 29 Nov 2004
15:01:55 -0500

>> But surely you don't use the entire range,
>> 555-598, every time? That's 44 permanent S/Gs! Rather
>> than a blunderbuss command to clear all of them, why not
>> clear only the ones actually used?

> What for? What's the cost of the blunderbuss command?
> I do have a S/G that contains a table of all the S/Gs
> used, so I could actually just clear the ones I used
> in the program. But, again, why not clear 'em all?

May I jump in? Carl and Harry are both asking good
questions. Carl's unquoted question is particularly
pertinent: if you "really are using all of them... what on
earth for?" I don't know of any program that requires that
number of *permanent* Save/Gets. One, maybe two, outside
three -- but not 44. That's nuts. The only U2 programs
that run exclusively in permanent Save/Get space are those
which, by analogy with OpSys design, you might call "Ring
Zero" programs: particularly sensitive programs that would
bring everything down if trashed (there are only a handful,
such as a program [CACHE/UNCACHE] that moves Xymemory onto the
hard disk temporarily, and then back again into mem, as
prophylaxis against OOM).

My suggestion would be to RENUMBER the whole program into
transient S/G space, FREEZEing just those few S/Gs that must
be permanent. Then RENUMBER the permanent S/Gs into a
*consecutive* cluster of 3 or 4 numbers or whatever, e.g.
555-557.

OK, what's the cost of the blunderbuss? There is a cost.
You can decide whether you want to pay:

CLEARSGTS does something which is ordinarily impossible.
According to the book, the best you can do with a permanent
Save/Get that you wish to "remove" from memory is to "zero
it out", i.e. remove its content so that length=0: e.g. «SV555,»
But once initialized, you can't *eliminate* a
permanent S/G from the roster of existing Save/Gets until
you Quit the session. However, we found a way to actually
uninitialize permanent Save/Gets, and that's the technique
CLEARSGTS employs (unless you're just clearing an ordinary
Save/Get 0-9 A-Z, in which case CLEARSGTS uses the REMOVE
command). CLEARSGTS deinitializes by deliberately
incurring a logical error:

  «SV555,wanna get rid of this Save/Get»;*;
  «SV01,555»;*;
  «SX01,"«SV"+«IS01»+",«SV"+«IS01»+",»»«PV"+«IS01»+"»«PR »"»«PV01»;*;
which boils down to:
  «SX01,"«SV555,«SV555,»»«PV555»«PR »"»«PV01»
and essentially:

  «SV555,«SV555,»»«PV555»

Alone, each of those two statements is perfectly legal.
When you execute the first -- «SV555,«SV555,»» -- Save/Get
555 simply holds the *string literal* "«SV555,»".  It's
absolutely no different than saying
  «SV555,testing»»
And if, subsequently, you issued «GT555», the effect would
be to put the strings "«SV555,»" or "testing" wherever the
cursor is located in text.  Here, however, we issue «PV555»,
and that is a different matter.  PV is smart, GT is stupid
( ~~ PV is a command processor, GT runs BAT files).  PV
knows all about embedded commands, guillemets, and the like.
PV *evaluates* the content of S/G 555.  If S/G555 were the
$tring "testing", PV works fine:  after all, "SV"-type Save/Gets
are designed to hold string literals, and PV knows all about
that too.  Suppose, on entry, S/G555 = "test$".
        Compare:                        On Exit, S/G555 =
        «SX555,«IS555»»                 "test$"
        «SU555,«SV555,»»«GT555»         null (length=0)
        «SU555,«SV555,»»«PV555»         null (length=0)
        «SV555,»                        null (length=0)
        «SV555»                         (SaVes DeFined Text to S/G555)
        «GT555»                         (puts "test$" in Text)
        «PV555»                         (puts "test$" at cursor pos [CMline|Text])
        «SV555,»«GT555»                 (puts null in Text)
        «SV555,»«PV555»                 (puts null at cursor pos [CMline|Text])
        «SV555,«SV555,»»«GT555»         (puts "«SV555,»" in Text)
        «SV555,«SV555,»»«PV555»         ERROR 147
In short, you can't *set the value of a $tring literal* --
which is the meaning and purpose of the statement «SV555,» --
within a $tring literal environment.  They are incompatible
data types.

So Editor denies this illegal request, kills the Save/Get
completely as if it never existed, and issues error 147,
"Function requires ID and expression".  That eliminates
the S/G from memory totally.  Which is, overall, a good
and desirable thing with permanent Save/Gets, because you
really REALLY don't want useless ones hanging around.
It's a no-no.  When, as often happens, somebody here has a
problem, but nobody else can replicate it, the hidden cause
is often the heap of ordinary (=permanent) Save/Gets they
are lugging around with them from STARTUP.INT onwards, which
make their XPL memory fragile.  Even if you write no
programs at all, even if you think you call or run no XPL
programs, the FACT is that you are using, and needing, XPL
memory *all the time* -- because XyWrite uses it even if you
don't.  This goes double if you use the Menus.  Therefore,
it is very important to keep consumption of XPL memory to
a minimum.  This is a large subject, but I should point out
that there are simple, very effective techniques for reducing
memory consumption.

Back to CLEARSGTS.  We commit a deliberate error, and the
S/G disappears.  But therein lies the rub.  Even if you disable
all of XyWrite's responses to errors (and I do:
wa=0,mb=0,eb=0,0), you still take a hit in terms of extra
processing through the internal error routines.  Clearing
44 permanent Save/Gets might take, oh, a second or so - instead
of a millisecond or three.  One second is nothing if you only
do this once in a while, e.g. at the tail end of a long
routine.  It'll take you one second just to start typing
again.  But in a routine like, say, Stack, where sometimes
you have two calls to Stack on a single keystroke, a 1-
second process is unacceptable.

Which brings us back to the original program that might
require CLEARSGTS, or something like it.  The real point is
not to use permanent S/Gs unless you really must retain data
in memory at all times, which is seldom the case.  You are
asking for OOM if this becomes a habit.  Moreover, if not
all 44 Save/Gets in the range 555-598 are really in use, you
don't want to clear them out using a broad brush, which
might inadvertently initialize S/Gs that never were
initialized to begin with!

However, let's suppose, for the sake of a good argument,
that it really is necessary to clear these 44 S/Gs, but you
don't want to take the time to let CLEARSGTS do it.  And you
also don't want to have the code bloat of
"«SV555,»«SV556,»«SV557,»...«SV598,»".  For one thing, that
looks dumb.  For another, it *is* dumb.  Here's what I'd do:

«SV01,555»«SX02,44»«CUA,02»«SX03,"«SV"+«IS01»+",»"»«PV03»«SX01,«PV01»+1»«LBA»

That's fast and effective.  Run LISTSAVS«Helpkey» afterward,
and see the result.  Here it is, encoded.

XPLeNCODE v2.0
b-gin [UNTITLED]
{«}SV01,555{»}{«}SX02,44{»}{«}CUA,02{»}{«}SX03,"{«}SV"+{«}I
S01{»}+",{»}"{»}{«}PV03{»}{«}SX01,{«}PV01{»}+1{»}{«}LBA{»}
-nd
XPLeNCODE