This is a basic question about the design and intent of functions in
programming languages like VBscript.

I know how to write VBScript functions and to pass parameter variables in
and out of them.

As I've become a smarter programmer, I'm inclined to translate the lousy
code that I wrote when I didn't know what was doing into more granularized
and encapsulated functions and/or classes.

I was revisiting some VBScript browser detection code that looked something
like this:

' check something
' set a variable based on result of check
' check something else
' set a different variable based on result of check
' check something else
' set a different variable based on result of check

The code sets about a dozen different variables of interest. The code was
not organized as a function. It's certainly easy enough to make it a sub or
function and to call it, but the variables that are set internally in the
function don't live outside of the scope of the function.

I want someone to confirm that the "correct" way/only way to make many
variables survive outside of the function is to return an object (e.g. an
array) of values upon the function's completion.

The function could write global vars, but that isn't good practice.

Am I correct in this, or is there another way that I'm missing?

Thank you,
Ken Fine

Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Joe

Joe
Sat Apr 30 20:46:42 CDT 2005

Hi,

<kenfine@u.washington.edu> wrote in message
news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
> This is a basic question about the design and intent of functions in
> programming languages like VBscript.
>
> I know how to write VBScript functions and to pass parameter variables in
> and out of them.
>
> As I've become a smarter programmer, I'm inclined to translate the lousy
> code that I wrote when I didn't know what was doing into more granularized
> and encapsulated functions and/or classes.
>
> I was revisiting some VBScript browser detection code that looked
> something
> like this:
>
> ' check something
> ' set a variable based on result of check
> ' check something else
> ' set a different variable based on result of check
> ' check something else
> ' set a different variable based on result of check
>
> The code sets about a dozen different variables of interest. The code was
> not organized as a function. It's certainly easy enough to make it a sub
> or
> function and to call it, but the variables that are set internally in the
> function don't live outside of the scope of the function.
>
> I want someone to confirm that the "correct" way/only way to make many
> variables survive outside of the function is to return an object (e.g. an
> array) of values upon the function's completion.
>
> The function could write global vars, but that isn't good practice.
>
> Am I correct in this, or is there another way that I'm missing?
>
> Thank you,
> Ken Fine

For my two cents worth ...

You missed a thread a couple of weeks ago where Al Dunbar (one of the MVPs
here) and I had a lengthy "discussion" over a slightly more complex version
of your question.

Given the straightforward nature of your question, I believe that the answer
is clearly "no," and I believe that most VBS scripters would agree, though
perhaps in different ways.

An array return (in scripting, "object" usually refers to a COM object
instance and a specific data subtype) is great for similar multiple items.
But it is the most obscure return, since you don't have the benefit of the
variable name to provide quick identification. And at times you may want to
return quite different values -- both strings and object instances, or
different types of references -- from a single function.

VBS (unlike JS and some other languages) maintains the ByRef/ByVal argument
distinction, and defaults to ByRef. ByRef arguments provide for returns
directly to the calling script, without having to use global variables to
achieve the return. Indeed, there is no functional difference between the
transitory function-name return and a ByRef argument variable return. ByRef
arguments have been the traditional method in BASIC programming, since early
DOS days, to get multiple return items from a subprocedure.

mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)

WMI functions are replete with return arguments -- indeed the WMI registry
access system only works that way.

The "trick", if you will, in using ByRef argument returns is either to
document the function or to use a scope-oriented and functional variable
prefixing system (instead of a simple variable-type system, which may not be
too useful in a pure variant language such as VBS). I strongly prefer real
prefixing. I can tell by looking at the first character of the argument
variable name that I assign whether it's passed ByVal or ByRef, and if
ByRef, whether its preserved, destroyed, coerced to the data type and range
required by the function, requires precise assignment, or set and returned.
The VBS option to use ByRef arguments is very efficient. But to take
advantage of it, you must be willing to coerce or destroy some argument
values, as well as reset some for return. This requires comment or a
meaningful prefixing system, both to preserve your sanity and for reuse of
the function in future scripts.

A ByRef return argument for a function can be analogized to a property
return for a method function. If your writing classes, you should consider
associated property returns. Since most I now write my fundamental
functions as WSC VBS, I again use global variables for multiple return
values, though these are declared in the parent XML script as properties and
returned to the calling script as properties. As you note, it is generally
better not to mix scope and use global variables for multiple return values,
in straight script, since it makes it hard to reuse the functions that you
write.

Regards,
Joe Earnest



Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Ken

Ken
Sat Apr 30 23:30:04 CDT 2005

Great answer, Joe, thank you so very much for your thoughtful reply.

Could I ask one other favor of you? You mention a system/convention of
prefixing that describes the scope of the variable and other useful
attributes to know. Can you show a sample of this convention, or maybe
recommend a book that describes the convention that you use? I'm very
interested.

I've been on a six-month tear of reading through the best comp sci/comp
engineering literature I can find, and it's pretty cool to see all of the
tips, tricks and philosophies I've digested translated into markedly better
code. Your system sounds like something worth internalizing.

-KF


"Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
news:uKp1D%23eTFHA.3344@TK2MSFTNGP12.phx.gbl...
> Hi,
>
> <kenfine@u.washington.edu> wrote in message
> news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
> > This is a basic question about the design and intent of functions in
> > programming languages like VBscript.
> >
> > I know how to write VBScript functions and to pass parameter variables
in
> > and out of them.
> >
> > As I've become a smarter programmer, I'm inclined to translate the lousy
> > code that I wrote when I didn't know what was doing into more
granularized
> > and encapsulated functions and/or classes.
> >
> > I was revisiting some VBScript browser detection code that looked
> > something
> > like this:
> >
> > ' check something
> > ' set a variable based on result of check
> > ' check something else
> > ' set a different variable based on result of check
> > ' check something else
> > ' set a different variable based on result of check
> >
> > The code sets about a dozen different variables of interest. The code
was
> > not organized as a function. It's certainly easy enough to make it a sub
> > or
> > function and to call it, but the variables that are set internally in
the
> > function don't live outside of the scope of the function.
> >
> > I want someone to confirm that the "correct" way/only way to make many
> > variables survive outside of the function is to return an object (e.g.
an
> > array) of values upon the function's completion.
> >
> > The function could write global vars, but that isn't good practice.
> >
> > Am I correct in this, or is there another way that I'm missing?
> >
> > Thank you,
> > Ken Fine
>
> For my two cents worth ...
>
> You missed a thread a couple of weeks ago where Al Dunbar (one of the MVPs
> here) and I had a lengthy "discussion" over a slightly more complex
version
> of your question.
>
> Given the straightforward nature of your question, I believe that the
answer
> is clearly "no," and I believe that most VBS scripters would agree, though
> perhaps in different ways.
>
> An array return (in scripting, "object" usually refers to a COM object
> instance and a specific data subtype) is great for similar multiple items.
> But it is the most obscure return, since you don't have the benefit of the
> variable name to provide quick identification. And at times you may want
to
> return quite different values -- both strings and object instances, or
> different types of references -- from a single function.
>
> VBS (unlike JS and some other languages) maintains the ByRef/ByVal
argument
> distinction, and defaults to ByRef. ByRef arguments provide for returns
> directly to the calling script, without having to use global variables to
> achieve the return. Indeed, there is no functional difference between the
> transitory function-name return and a ByRef argument variable return.
ByRef
> arguments have been the traditional method in BASIC programming, since
early
> DOS days, to get multiple return items from a subprocedure.
>
> mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)
>
> WMI functions are replete with return arguments -- indeed the WMI registry
> access system only works that way.
>
> The "trick", if you will, in using ByRef argument returns is either to
> document the function or to use a scope-oriented and functional variable
> prefixing system (instead of a simple variable-type system, which may not
be
> too useful in a pure variant language such as VBS). I strongly prefer
real
> prefixing. I can tell by looking at the first character of the argument
> variable name that I assign whether it's passed ByVal or ByRef, and if
> ByRef, whether its preserved, destroyed, coerced to the data type and
range
> required by the function, requires precise assignment, or set and
returned.
> The VBS option to use ByRef arguments is very efficient. But to take
> advantage of it, you must be willing to coerce or destroy some argument
> values, as well as reset some for return. This requires comment or a
> meaningful prefixing system, both to preserve your sanity and for reuse of
> the function in future scripts.
>
> A ByRef return argument for a function can be analogized to a property
> return for a method function. If your writing classes, you should
consider
> associated property returns. Since most I now write my fundamental
> functions as WSC VBS, I again use global variables for multiple return
> values, though these are declared in the parent XML script as properties
and
> returned to the calling script as properties. As you note, it is
generally
> better not to mix scope and use global variables for multiple return
values,
> in straight script, since it makes it hard to reuse the functions that you
> write.
>
> Regards,
> Joe Earnest
>
>



One other related Q Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Ken

Ken
Sun May 01 00:53:26 CDT 2005

I have one other related question: if I instantiate a bunch of objects --
say, recordsets -- in the context of a sub or function, will the objects be
exposed to the rest of the page? (It would be nice to have
"OpenPageRecordsets" and "ClosePageRecordsets " so that the page logic would
be succinct and clear.)


"Ken Fine" <kenfine@u.washington.edu> wrote in message
news:d51m0g$o92$1@gnus01.u.washington.edu...
> Great answer, Joe, thank you so very much for your thoughtful reply.
>
> Could I ask one other favor of you? You mention a system/convention of
> prefixing that describes the scope of the variable and other useful
> attributes to know. Can you show a sample of this convention, or maybe
> recommend a book that describes the convention that you use? I'm very
> interested.
>
> I've been on a six-month tear of reading through the best comp sci/comp
> engineering literature I can find, and it's pretty cool to see all of the
> tips, tricks and philosophies I've digested translated into markedly
better
> code. Your system sounds like something worth internalizing.
>
> -KF
>
>
> "Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
> news:uKp1D%23eTFHA.3344@TK2MSFTNGP12.phx.gbl...
> > Hi,
> >
> > <kenfine@u.washington.edu> wrote in message
> > news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
> > > This is a basic question about the design and intent of functions in
> > > programming languages like VBscript.
> > >
> > > I know how to write VBScript functions and to pass parameter variables
> in
> > > and out of them.
> > >
> > > As I've become a smarter programmer, I'm inclined to translate the
lousy
> > > code that I wrote when I didn't know what was doing into more
> granularized
> > > and encapsulated functions and/or classes.
> > >
> > > I was revisiting some VBScript browser detection code that looked
> > > something
> > > like this:
> > >
> > > ' check something
> > > ' set a variable based on result of check
> > > ' check something else
> > > ' set a different variable based on result of check
> > > ' check something else
> > > ' set a different variable based on result of check
> > >
> > > The code sets about a dozen different variables of interest. The code
> was
> > > not organized as a function. It's certainly easy enough to make it a
sub
> > > or
> > > function and to call it, but the variables that are set internally in
> the
> > > function don't live outside of the scope of the function.
> > >
> > > I want someone to confirm that the "correct" way/only way to make many
> > > variables survive outside of the function is to return an object (e.g.
> an
> > > array) of values upon the function's completion.
> > >
> > > The function could write global vars, but that isn't good practice.
> > >
> > > Am I correct in this, or is there another way that I'm missing?
> > >
> > > Thank you,
> > > Ken Fine
> >
> > For my two cents worth ...
> >
> > You missed a thread a couple of weeks ago where Al Dunbar (one of the
MVPs
> > here) and I had a lengthy "discussion" over a slightly more complex
> version
> > of your question.
> >
> > Given the straightforward nature of your question, I believe that the
> answer
> > is clearly "no," and I believe that most VBS scripters would agree,
though
> > perhaps in different ways.
> >
> > An array return (in scripting, "object" usually refers to a COM object
> > instance and a specific data subtype) is great for similar multiple
items.
> > But it is the most obscure return, since you don't have the benefit of
the
> > variable name to provide quick identification. And at times you may
want
> to
> > return quite different values -- both strings and object instances, or
> > different types of references -- from a single function.
> >
> > VBS (unlike JS and some other languages) maintains the ByRef/ByVal
> argument
> > distinction, and defaults to ByRef. ByRef arguments provide for returns
> > directly to the calling script, without having to use global variables
to
> > achieve the return. Indeed, there is no functional difference between
the
> > transitory function-name return and a ByRef argument variable return.
> ByRef
> > arguments have been the traditional method in BASIC programming, since
> early
> > DOS days, to get multiple return items from a subprocedure.
> >
> > mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)
> >
> > WMI functions are replete with return arguments -- indeed the WMI
registry
> > access system only works that way.
> >
> > The "trick", if you will, in using ByRef argument returns is either to
> > document the function or to use a scope-oriented and functional variable
> > prefixing system (instead of a simple variable-type system, which may
not
> be
> > too useful in a pure variant language such as VBS). I strongly prefer
> real
> > prefixing. I can tell by looking at the first character of the argument
> > variable name that I assign whether it's passed ByVal or ByRef, and if
> > ByRef, whether its preserved, destroyed, coerced to the data type and
> range
> > required by the function, requires precise assignment, or set and
> returned.
> > The VBS option to use ByRef arguments is very efficient. But to take
> > advantage of it, you must be willing to coerce or destroy some argument
> > values, as well as reset some for return. This requires comment or a
> > meaningful prefixing system, both to preserve your sanity and for reuse
of
> > the function in future scripts.
> >
> > A ByRef return argument for a function can be analogized to a property
> > return for a method function. If your writing classes, you should
> consider
> > associated property returns. Since most I now write my fundamental
> > functions as WSC VBS, I again use global variables for multiple return
> > values, though these are declared in the parent XML script as properties
> and
> > returned to the calling script as properties. As you note, it is
> generally
> > better not to mix scope and use global variables for multiple return
> values,
> > in straight script, since it makes it hard to reuse the functions that
you
> > write.
> >
> > Regards,
> > Joe Earnest
> >
> >
>
>



Re: One other related Q Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Joe

Joe
Sun May 01 08:39:07 CDT 2005

Hi,

"Ken Fine" <kenfine@u.washington.edu> wrote in message
news:d51qsr$rp8$1@gnus01.u.washington.edu...
>I have one other related question: if I instantiate a bunch of objects --
> say, recordsets -- in the context of a sub or function, will the objects
> be
> exposed to the rest of the page? (It would be nice to have
> "OpenPageRecordsets" and "ClosePageRecordsets " so that the page logic
> would
> be succinct and clear.)
>
>
> "Ken Fine" <kenfine@u.washington.edu> wrote in message
> news:d51m0g$o92$1@gnus01.u.washington.edu...
>> Great answer, Joe, thank you so very much for your thoughtful reply.
>>
>> Could I ask one other favor of you? You mention a system/convention of
>> prefixing that describes the scope of the variable and other useful
>> attributes to know. Can you show a sample of this convention, or maybe
>> recommend a book that describes the convention that you use? I'm very
>> interested.
>>
>> I've been on a six-month tear of reading through the best comp sci/comp
>> engineering literature I can find, and it's pretty cool to see all of the
>> tips, tricks and philosophies I've digested translated into markedly
> better
>> code. Your system sounds like something worth internalizing.
>>
>> -KF
>>
>>
>> "Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
>> news:uKp1D%23eTFHA.3344@TK2MSFTNGP12.phx.gbl...
>> > Hi,
>> >
>> > <kenfine@u.washington.edu> wrote in message
>> > news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
>> > > This is a basic question about the design and intent of functions in
>> > > programming languages like VBscript.
>> > >
>> > > I know how to write VBScript functions and to pass parameter
>> > > variables
>> in
>> > > and out of them.
>> > >
>> > > As I've become a smarter programmer, I'm inclined to translate the
> lousy
>> > > code that I wrote when I didn't know what was doing into more
>> granularized
>> > > and encapsulated functions and/or classes.
>> > >
>> > > I was revisiting some VBScript browser detection code that looked
>> > > something
>> > > like this:
>> > >
>> > > ' check something
>> > > ' set a variable based on result of check
>> > > ' check something else
>> > > ' set a different variable based on result of check
>> > > ' check something else
>> > > ' set a different variable based on result of check
>> > >
>> > > The code sets about a dozen different variables of interest. The code
>> was
>> > > not organized as a function. It's certainly easy enough to make it a
> sub
>> > > or
>> > > function and to call it, but the variables that are set internally in
>> the
>> > > function don't live outside of the scope of the function.
>> > >
>> > > I want someone to confirm that the "correct" way/only way to make
>> > > many
>> > > variables survive outside of the function is to return an object
>> > > (e.g.
>> an
>> > > array) of values upon the function's completion.
>> > >
>> > > The function could write global vars, but that isn't good practice.
>> > >
>> > > Am I correct in this, or is there another way that I'm missing?
>> > >
>> > > Thank you,
>> > > Ken Fine
>> >
>> > For my two cents worth ...
>> >
>> > You missed a thread a couple of weeks ago where Al Dunbar (one of the
> MVPs
>> > here) and I had a lengthy "discussion" over a slightly more complex
>> version
>> > of your question.
>> >
>> > Given the straightforward nature of your question, I believe that the
>> answer
>> > is clearly "no," and I believe that most VBS scripters would agree,
> though
>> > perhaps in different ways.
>> >
>> > An array return (in scripting, "object" usually refers to a COM object
>> > instance and a specific data subtype) is great for similar multiple
> items.
>> > But it is the most obscure return, since you don't have the benefit of
> the
>> > variable name to provide quick identification. And at times you may
> want
>> to
>> > return quite different values -- both strings and object instances, or
>> > different types of references -- from a single function.
>> >
>> > VBS (unlike JS and some other languages) maintains the ByRef/ByVal
>> argument
>> > distinction, and defaults to ByRef. ByRef arguments provide for
>> > returns
>> > directly to the calling script, without having to use global variables
> to
>> > achieve the return. Indeed, there is no functional difference between
> the
>> > transitory function-name return and a ByRef argument variable return.
>> ByRef
>> > arguments have been the traditional method in BASIC programming, since
>> early
>> > DOS days, to get multiple return items from a subprocedure.
>> >
>> > mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)
>> >
>> > WMI functions are replete with return arguments -- indeed the WMI
> registry
>> > access system only works that way.
>> >
>> > The "trick", if you will, in using ByRef argument returns is either to
>> > document the function or to use a scope-oriented and functional
>> > variable
>> > prefixing system (instead of a simple variable-type system, which may
> not
>> be
>> > too useful in a pure variant language such as VBS). I strongly prefer
>> real
>> > prefixing. I can tell by looking at the first character of the
>> > argument
>> > variable name that I assign whether it's passed ByVal or ByRef, and if
>> > ByRef, whether its preserved, destroyed, coerced to the data type and
>> range
>> > required by the function, requires precise assignment, or set and
>> returned.
>> > The VBS option to use ByRef arguments is very efficient. But to take
>> > advantage of it, you must be willing to coerce or destroy some argument
>> > values, as well as reset some for return. This requires comment or a
>> > meaningful prefixing system, both to preserve your sanity and for reuse
> of
>> > the function in future scripts.
>> >
>> > A ByRef return argument for a function can be analogized to a property
>> > return for a method function. If your writing classes, you should
>> consider
>> > associated property returns. Since most I now write my fundamental
>> > functions as WSC VBS, I again use global variables for multiple return
>> > values, though these are declared in the parent XML script as
>> > properties
>> and
>> > returned to the calling script as properties. As you note, it is
>> generally
>> > better not to mix scope and use global variables for multiple return
>> values,
>> > in straight script, since it makes it hard to reuse the functions that
> you
>> > write.
>> >
>> > Regards,
>> > Joe Earnest
>> >

The short answer is no. Like all other local variable assignments, object
instances go out of scope when the local procedure goes out of scope. For
this reason, common scripting objects (FSO, Shell, WshShell, etc.) are often
used "against the grain" of the general rule not to use global objects in
local procedures, and are instead declared at the outset and used throughout
the script. Again, if you ever decide to use WSC files as general "utility"
and "include" files, the WSC file can declare the common objects globally on
its instantiation and pass them to the calling script through properties,
avoiding the need for the calling script to declare and instantiate
additional common object instances. But again, to use your WSC file
throughout your script, at both global and local levels, *it* would be
declared as an object in the global code and that global variable would be
used, again "against the grain" of the general rule, in local procedures.

Most sources do not explain COM object scoping and duplication well. The
following is one of my standard "schpeals" based on my own experience, but
also on some terribly useful explanatory posts in the past by Michael Harris
(MVP), Alex Angelopoulos (MVP), Chris Barber and Alexander Mueller.

Regards,
Joe Earnest

-----
When a typical COM class object is "accessed" by the creation of an
"instance" of the object, a pointer to the IDispatch interface and a new
virtual "object" is created as an interface definition of parameters with
assigned memory. Memory is allocated in which the new object's members may
store data. For the typical COM class object, a new pointer and virtual
object are created for each instance of the underlying object accessed.

If the COM class object is a "singleton" object, however, only a single
instance will be created, which will be shared not only by all object
variable instances in the same script, but by all scripts or other processes
accessing the object. In the case of a singleton object, the initiation
process first checks to see if an instance of the underlying object has
already been instantiated and, if so, returns a pointer to the same initial
virtual object. Thus (per the MS documentation): "If an object has
registered itself as a single-instance object, only one instance of the
object is created, no matter how many times CreateObject is executed. With
a single-instance object, GetObject always returns the same instance when
called with the zero-length string syntax, and it causes an error if the
pathname argument is omitted."

When all object access references are fully terminated, VBS runs a cleanup
process that deletes the pointers and begins the process of eliminating the
interface and memory allocation. An object will be disconnected only after
all references to it have been released. Windows may retain certain
references, depending on the object type and how it was instantiated. It is
possible, for example, to lock an object, when employing multiple object
references. Care must be taken with techniques and object types that allow
the object instance to continue beyond its scope in the script or even
beyond the termination of the script.

A review of posts relating to concerns with continued object connections and
"memory leaks" seems to indicate a number of reasonably distinct situations,
including, among others: (1) failure to properly exit a With statement
block by progressing through the End With statement; (2) multiple or
duplicate object references, where object variables in higher levels of
scope are not released; and (3) recursive procedures that create multiple
copies of an object. The most pernicious "memory leaks" appear to involve
EXE or special DLL objects, that are essentially applications, and which,
once initiated, continue independently, despite being released from the
object connections to the script. With these types of objects, it is always
best to try to force them to shut down through internal means, usually a
Quit method, before terminating the object reference.

The VBS process releasing the object references is part of the cleanup
procedures involved anytime that an object reference goes out of scope. For
purposes of an object variable as a reference to an existing object
instance, the going-out-of-scope cleanup is initiated for the existing
object reference whenever: (1) the variable is reset to Nothing or to a
different object reference, or even to a subsequent instance of the same
object reference; (2) the variable is reset to Empty or to a non-object
subtype or value; (3) the script is terminated; (4) a procedure in which the
object instance has been assigned to a local variable is exited; (5) the
inherent CreateObject function is used directly for a transitory instance of
the object, instead of assigning it to a variable; or (6) the CreateObject
function is referenced by a With statement block, and the script progresses
through the End With statement.

Setting unused object variables to Nothing is the "preferred" cross-platform
coding practice, and it is useful to release system resources more quickly,
when the object instance will not otherwise promptly go out of scope, but it
ultimately accomplishes nothing more in VBS than does any other method of
going out of scope.

When passing object instances to multiple scripts and/or multiple hosts, the
object instance will go out of scope whenever the originating script or host
is closed.

The inherent IsObject function simply returns the result of a check for the
appropriate index code in the variable list. It does not tell you if the
variable references any currently instantiated COM class object. For
example, an object variable reset to Nothing will still be returned as an
object variable, as will a variable whose object instance connection has
been terminated or otherwise lost. The intrinsic TypeName function can be
used as a secondary test in these situations. If the variable has been set
to Nothing, Typename will return Nothing; if the variable is connected to an
object instance, TypeName returns the specific object's ProgId, or the
default property subtype, if the object has a default property; and if the
variable is no longer connected to an object instance, TypeName returns the
generic Object status.

The IsObject function should still be used as a primary test for a specific
object, since both the inherent VarType and TypeName functions may return
the data subtype of the object's default property, depending upon the
specific object tested.




Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Joe

Joe
Sun May 01 09:26:29 CDT 2005

Hi,

"Ken Fine" <kenfine@u.washington.edu> wrote in message
news:d51m0g$o92$1@gnus01.u.washington.edu...
> Great answer, Joe, thank you so very much for your thoughtful reply.
>
> Could I ask one other favor of you? You mention a system/convention of
> prefixing that describes the scope of the variable and other useful
> attributes to know. Can you show a sample of this convention, or maybe
> recommend a book that describes the convention that you use? I'm very
> interested.
>
> I've been on a six-month tear of reading through the best comp sci/comp
> engineering literature I can find, and it's pretty cool to see all of the
> tips, tricks and philosophies I've digested translated into markedly
> better
> code. Your system sounds like something worth internalizing.
>
> -KF
>
>
> "Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
> news:uKp1D%23eTFHA.3344@TK2MSFTNGP12.phx.gbl...
>> Hi,
>>
>> <kenfine@u.washington.edu> wrote in message
>> news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
>> > This is a basic question about the design and intent of functions in
>> > programming languages like VBscript.
>> >
>> > I know how to write VBScript functions and to pass parameter variables
> in
>> > and out of them.
>> >
>> > As I've become a smarter programmer, I'm inclined to translate the
>> > lousy
>> > code that I wrote when I didn't know what was doing into more
> granularized
>> > and encapsulated functions and/or classes.
>> >
>> > I was revisiting some VBScript browser detection code that looked
>> > something
>> > like this:
>> >
>> > ' check something
>> > ' set a variable based on result of check
>> > ' check something else
>> > ' set a different variable based on result of check
>> > ' check something else
>> > ' set a different variable based on result of check
>> >
>> > The code sets about a dozen different variables of interest. The code
> was
>> > not organized as a function. It's certainly easy enough to make it a
>> > sub
>> > or
>> > function and to call it, but the variables that are set internally in
> the
>> > function don't live outside of the scope of the function.
>> >
>> > I want someone to confirm that the "correct" way/only way to make many
>> > variables survive outside of the function is to return an object (e.g.
> an
>> > array) of values upon the function's completion.
>> >
>> > The function could write global vars, but that isn't good practice.
>> >
>> > Am I correct in this, or is there another way that I'm missing?
>> >
>> > Thank you,
>> > Ken Fine
>>
>> For my two cents worth ...
>>
>> You missed a thread a couple of weeks ago where Al Dunbar (one of the
>> MVPs
>> here) and I had a lengthy "discussion" over a slightly more complex
> version
>> of your question.
>>
>> Given the straightforward nature of your question, I believe that the
> answer
>> is clearly "no," and I believe that most VBS scripters would agree,
>> though
>> perhaps in different ways.
>>
>> An array return (in scripting, "object" usually refers to a COM object
>> instance and a specific data subtype) is great for similar multiple
>> items.
>> But it is the most obscure return, since you don't have the benefit of
>> the
>> variable name to provide quick identification. And at times you may want
> to
>> return quite different values -- both strings and object instances, or
>> different types of references -- from a single function.
>>
>> VBS (unlike JS and some other languages) maintains the ByRef/ByVal
> argument
>> distinction, and defaults to ByRef. ByRef arguments provide for returns
>> directly to the calling script, without having to use global variables to
>> achieve the return. Indeed, there is no functional difference between
>> the
>> transitory function-name return and a ByRef argument variable return.
> ByRef
>> arguments have been the traditional method in BASIC programming, since
> early
>> DOS days, to get multiple return items from a subprocedure.
>>
>> mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)
>>
>> WMI functions are replete with return arguments -- indeed the WMI
>> registry
>> access system only works that way.
>>
>> The "trick", if you will, in using ByRef argument returns is either to
>> document the function or to use a scope-oriented and functional variable
>> prefixing system (instead of a simple variable-type system, which may not
> be
>> too useful in a pure variant language such as VBS). I strongly prefer
> real
>> prefixing. I can tell by looking at the first character of the argument
>> variable name that I assign whether it's passed ByVal or ByRef, and if
>> ByRef, whether its preserved, destroyed, coerced to the data type and
> range
>> required by the function, requires precise assignment, or set and
> returned.
>> The VBS option to use ByRef arguments is very efficient. But to take
>> advantage of it, you must be willing to coerce or destroy some argument
>> values, as well as reset some for return. This requires comment or a
>> meaningful prefixing system, both to preserve your sanity and for reuse
>> of
>> the function in future scripts.
>>
>> A ByRef return argument for a function can be analogized to a property
>> return for a method function. If your writing classes, you should
> consider
>> associated property returns. Since most I now write my fundamental
>> functions as WSC VBS, I again use global variables for multiple return
>> values, though these are declared in the parent XML script as properties
> and
>> returned to the calling script as properties. As you note, it is
> generally
>> better not to mix scope and use global variables for multiple return
> values,
>> in straight script, since it makes it hard to reuse the functions that
>> you
>> write.
>>
>> Regards,
>> Joe Earnest

First off, my apologies for the omitted phrases and bad grammer in the last
response. It had been a long day.

Prefixing systems are the type of thing that can create flame posts --
people seem to take them very personally. My system has developed through
DOS to Windows and ASM to scripting. My current system, however, is focused
on VBS, and even underwent a bit of a change a couple of years ago, when I
switched largely to WSCs from straightforward scripting. There are a number
of factors to consider in choosing a prefixing system that may make my
approach unsuitable for you. Probably the two most significant ones are:

1) The peer group where you work or with whom you exchange or mutually work
on code, or a potential successor for a client, or even a publication, may
expect or require a prefixing system that everyone can recognize quickly;
and

2) If you are working in multiple platforms and languages, and particularly
if those multiple platforms or languages are involved in the same code or
project, you may need to adapt your prefixing system to a
least-common-denominator approach that addresses the requirements and quirks
of all the platforms and languages involved.

Also, before I give you my prefixing system, you might want to take a look
at Eric Lippert's blog on type prefixing in VBS. Eric Lippert wrote a
substantial amount of the VBS code for MS.

http://blogs.msdn.com/ericlippert/archive/2003/09/12/52989.aspx

A bit of history that may be useful when reading Eric's blog, or other
people's comments (from Alex Angelopoulos [MVP]):

"Suggested naming conventions abound, most variants of Hungarian Notation
(HN), a standard for variable naming developed at Microsoft in the early
1980's for use in workgroup-based C coding. The real story is not this
convention but the concepts researched by it's father, Charles Simonyi. In
graduate research at Xerox PARC he extensively investigated group-based
coding. He focused heavily on how code can be improved by use of certain
shared conventions. To this day one of the clearer benefits of any naming
standard is ensuring that when you look at code you quickly can see what a
variable represents and what a function does."

Let me say at the ouset that I claim no "divine insight" in my prefixing
system, or that it would work for anyone else. It is not even strictly
logical, but has simply proven to be more useful to me than a strictly
logical system. It will likely not be intuitively recognized by other
scripters. It is optimized for VBS and even for WSC-hosted VBS, with a
secondary focus on mark-up languages (HTML, XML, etc.), so its
cross-platform and cross-language application is questionable.

Regards,
Joe Earnest

-----
Modified mark-up language "camel" casing is employed for all user-defined
names; external objects, properties and methods; and constants. The initial
name segment is fully lowercased, while the initial character of
non-delimited secondary name segments is capitalized. All inherent VBS
keywords and function names fully lowercased. Entities and names created
through XML and HTML methods are named as if they were created through VBS
methods.

All procedures are declared as functions, even if they provide no return and
are designed to be called only as statements. Unexposed functions are
prefixed with an initial "fn" segment. Exposed methods and properties, and
their corresponding functions, are not prefixed, unless a conflict with an
inherent VBS name requires the internal function to be prefixed. Unexposed
components (loosely, the WSC file equivalent of classes) are designated with
an initial "cp" segment, while exposed components are named to provide a
recognizable call.

All script is "Option Explicit". Variables are declared when and where
required. The VBS "Const" statement is never used. The underscore
character is not used in variable names, unless use is compelled by context,
but is, instead, reserved solely for line continuations.

All variable names are prefixed, except for object variables that access
unexposed components. This allows the variable name to be used as an
exposed property.

My peculiar variable prefixing is oriented toward identifying scope and
usage, as well as identifying data subtype, when useful. Variables are
given concise name segments to differentiate them and generally identify
their content in context. Pluralized names are used for totals, as well as
for transitory variables that may change subtypes between arrays and string
lists. For example, in a hypothetical procedure, "viFile" could be a local
counter or iteration of files, "viFiles" could be a local reference to the
total number of files, "vaFiles(...)" could be a local array of file
objects, "vsFileName" would be a local file name string, and "vsFileNames"
would be a local string list of file names that could be changed back and
forth, to and from, an array, using the VBS "Split" and "Join" functions.

Prefixing involves two characters: (1) the first indicates scope and
argument usage, or is omitted for global variables; (2) the second indicates
type and usage, to the extent that I have found it useful.

Variable Scope Prefix

none e.g., sFile
Globally defined.

v e.g., vsFile
Locally defined or ByVal argument. Both local definitions and ByVal
argument variable values go out of scope when the procedure is exited. All
ByVal arguments are internally coerced to the procedure's required data
subtype and/or range, but, because it is ByVal, the value passed is
preserved. Note that, in VBS, object instances are always passed ByRef,
even if there is a ByVal argument statement.

r e.g., rsFile
ByRef argument returned. The value passed is modified in the procedure for
return to the calling script. If an initial value is required, the data
passed will be internally coerced to the required data subtype and/or range.

u e.g., usFile
ByRef argument unchecked. Data for the argument must be passed as the
anticipated subtype and/or range, to avoid an error in the procedure. The
value passed is preserved.

p e.g., psFile
ByRef argument preserved. The data passed is coerced to the anticipated
subtype and/or range without destruction, so that the value passed is
preserved.

c e.g., csFile
ByRef argument coerced and destroyed. The data passed is coerced to the
anticipated subtype and/or range, destroying the data passed.

Variable Type and Usage Prefix

The final variable prefix character indicates the variable's type and/or
usage. All categories include an initial "Empty" data subtype, as well as
any data subtype passed through a function's argument, or returned from a
function, method or property, until the anticipated data type can be
coerced. These categories have developed historically and idiosyncratically
over time, and have simply proved useful to me. They don't necessarily make
sense.

a e.g., aFile, vaAmount
Array. A variable that is declared and maintained solely as an array.
Transitory string-list arrays may have an "s" prefix. Transitory
string-lists that convert to arrays with mixed data types may have an "x"
prefix. Note that this prefix does not articulate the data subtype(s) or
any other aspects of its elements.

f e.g., fErr, vfExists
Boolean or numeric flag. A Boolean subtype, or a (long) integer numeric
subtype with a value of "0" or "-1".

i e.g., iRep, viItem, viItems, viInStrChr, viBit
Integer or long integer. A (long) integer subtype used in a uniquely
"integer" manner, as an instance, counter, pointer, address, element number,
position, bitwise, sequential or other numeric code, etc., or, with a plural
name, the total instances or the UBound of an array.

n e.g., nHt, vnAmount
A numeric subtype. Any other numeric data subtype or numeric usage.

s e.g., sFile, vsName, vsFileList
String. Any string data subtype or usage. May also include transitory
string lists that are changed back and forth to or from arrays.

o e.g., oFso, voShell, uoWshShell
Object. An object instance data subtype or usage. Because VBS requires
that object variables be passed ByRef, all object variables passed to a
user-defined procedure should have a prefix indicating ByRef status.
Scriptlet object variables that are exposed as properties in order to allow
access to unexposed components, are not prefixed, so that the variable name
may be used as an exposed property name.

d e.g., dFileDate, vdToday
Date. A date-time data subtype or usage.

k e.g., kVersion, kSomeBitFlag
Constant. Data of any subtype that is intended to be fixed and unchanged,
once determined. Rarely used, but almost always global in scope, when used.
The VBS "Const" statement is not used, as such.

x e.g., xUtility, vxArgCode, vxValueList
Other, transitory or multi-type. A data subtype such as "Null" or "Error",
a transitory utility variable, a transitory string list that is converted to
or from a mixed data-type array, or an argument that may be validly assigned
different data subtypes.



Re: basic Q: Only one way to make vars live outside of the scope of a function without globals? by Ken

Ken
Sun May 01 11:35:15 CDT 2005


Thank you for your generous responses, Joe. This is excellent.

Regards,
Ken Fine

"Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
news:OFDlZllTFHA.3140@TK2MSFTNGP14.phx.gbl...
> Hi,
>
> "Ken Fine" <kenfine@u.washington.edu> wrote in message
> news:d51m0g$o92$1@gnus01.u.washington.edu...
> > Great answer, Joe, thank you so very much for your thoughtful reply.
> >
> > Could I ask one other favor of you? You mention a system/convention of
> > prefixing that describes the scope of the variable and other useful
> > attributes to know. Can you show a sample of this convention, or maybe
> > recommend a book that describes the convention that you use? I'm very
> > interested.
> >
> > I've been on a six-month tear of reading through the best comp sci/comp
> > engineering literature I can find, and it's pretty cool to see all of
the
> > tips, tricks and philosophies I've digested translated into markedly
> > better
> > code. Your system sounds like something worth internalizing.
> >
> > -KF
> >
> >
> > "Joe Earnest" <jearnest3-SPAM@earthlink.net> wrote in message
> > news:uKp1D%23eTFHA.3344@TK2MSFTNGP12.phx.gbl...
> >> Hi,
> >>
> >> <kenfine@u.washington.edu> wrote in message
> >> news:eGg2QRdTFHA.616@TK2MSFTNGP12.phx.gbl...
> >> > This is a basic question about the design and intent of functions in
> >> > programming languages like VBscript.
> >> >
> >> > I know how to write VBScript functions and to pass parameter
variables
> > in
> >> > and out of them.
> >> >
> >> > As I've become a smarter programmer, I'm inclined to translate the
> >> > lousy
> >> > code that I wrote when I didn't know what was doing into more
> > granularized
> >> > and encapsulated functions and/or classes.
> >> >
> >> > I was revisiting some VBScript browser detection code that looked
> >> > something
> >> > like this:
> >> >
> >> > ' check something
> >> > ' set a variable based on result of check
> >> > ' check something else
> >> > ' set a different variable based on result of check
> >> > ' check something else
> >> > ' set a different variable based on result of check
> >> >
> >> > The code sets about a dozen different variables of interest. The code
> > was
> >> > not organized as a function. It's certainly easy enough to make it a
> >> > sub
> >> > or
> >> > function and to call it, but the variables that are set internally in
> > the
> >> > function don't live outside of the scope of the function.
> >> >
> >> > I want someone to confirm that the "correct" way/only way to make
many
> >> > variables survive outside of the function is to return an object
(e.g.
> > an
> >> > array) of values upon the function's completion.
> >> >
> >> > The function could write global vars, but that isn't good practice.
> >> >
> >> > Am I correct in this, or is there another way that I'm missing?
> >> >
> >> > Thank you,
> >> > Ken Fine
> >>
> >> For my two cents worth ...
> >>
> >> You missed a thread a couple of weeks ago where Al Dunbar (one of the
> >> MVPs
> >> here) and I had a lengthy "discussion" over a slightly more complex
> > version
> >> of your question.
> >>
> >> Given the straightforward nature of your question, I believe that the
> > answer
> >> is clearly "no," and I believe that most VBS scripters would agree,
> >> though
> >> perhaps in different ways.
> >>
> >> An array return (in scripting, "object" usually refers to a COM object
> >> instance and a specific data subtype) is great for similar multiple
> >> items.
> >> But it is the most obscure return, since you don't have the benefit of
> >> the
> >> variable name to provide quick identification. And at times you may
want
> > to
> >> return quite different values -- both strings and object instances, or
> >> different types of references -- from a single function.
> >>
> >> VBS (unlike JS and some other languages) maintains the ByRef/ByVal
> > argument
> >> distinction, and defaults to ByRef. ByRef arguments provide for
returns
> >> directly to the calling script, without having to use global variables
to
> >> achieve the return. Indeed, there is no functional difference between
> >> the
> >> transitory function-name return and a ByRef argument variable return.
> > ByRef
> >> arguments have been the traditional method in BASIC programming, since
> > early
> >> DOS days, to get multiple return items from a subprocedure.
> >>
> >> mainNumRtn= myFunction(useValue1, useValue2, rtnObjVar, rtnStrVar)
> >>
> >> WMI functions are replete with return arguments -- indeed the WMI
> >> registry
> >> access system only works that way.
> >>
> >> The "trick", if you will, in using ByRef argument returns is either to
> >> document the function or to use a scope-oriented and functional
variable
> >> prefixing system (instead of a simple variable-type system, which may
not
> > be
> >> too useful in a pure variant language such as VBS). I strongly prefer
> > real
> >> prefixing. I can tell by looking at the first character of the
argument
> >> variable name that I assign whether it's passed ByVal or ByRef, and if
> >> ByRef, whether its preserved, destroyed, coerced to the data type and
> > range
> >> required by the function, requires precise assignment, or set and
> > returned.
> >> The VBS option to use ByRef arguments is very efficient. But to take
> >> advantage of it, you must be willing to coerce or destroy some argument
> >> values, as well as reset some for return. This requires comment or a
> >> meaningful prefixing system, both to preserve your sanity and for reuse
> >> of
> >> the function in future scripts.
> >>
> >> A ByRef return argument for a function can be analogized to a property
> >> return for a method function. If your writing classes, you should
> > consider
> >> associated property returns. Since most I now write my fundamental
> >> functions as WSC VBS, I again use global variables for multiple return
> >> values, though these are declared in the parent XML script as
properties
> > and
> >> returned to the calling script as properties. As you note, it is
> > generally
> >> better not to mix scope and use global variables for multiple return
> > values,
> >> in straight script, since it makes it hard to reuse the functions that
> >> you
> >> write.
> >>
> >> Regards,
> >> Joe Earnest
>
> First off, my apologies for the omitted phrases and bad grammer in the
last
> response. It had been a long day.
>
> Prefixing systems are the type of thing that can create flame posts --
> people seem to take them very personally. My system has developed through
> DOS to Windows and ASM to scripting. My current system, however, is
focused
> on VBS, and even underwent a bit of a change a couple of years ago, when I
> switched largely to WSCs from straightforward scripting. There are a
number
> of factors to consider in choosing a prefixing system that may make my
> approach unsuitable for you. Probably the two most significant ones are:
>
> 1) The peer group where you work or with whom you exchange or mutually
work
> on code, or a potential successor for a client, or even a publication, may
> expect or require a prefixing system that everyone can recognize quickly;
> and
>
> 2) If you are working in multiple platforms and languages, and
particularly
> if those multiple platforms or languages are involved in the same code or
> project, you may need to adapt your prefixing system to a
> least-common-denominator approach that addresses the requirements and
quirks
> of all the platforms and languages involved.
>
> Also, before I give you my prefixing system, you might want to take a look
> at Eric Lippert's blog on type prefixing in VBS. Eric Lippert wrote a
> substantial amount of the VBS code for MS.
>
> http://blogs.msdn.com/ericlippert/archive/2003/09/12/52989.aspx
>
> A bit of history that may be useful when reading Eric's blog, or other
> people's comments (from Alex Angelopoulos [MVP]):
>
> "Suggested naming conventions abound, most variants of Hungarian Notation
> (HN), a standard for variable naming developed at Microsoft in the early
> 1980's for use in workgroup-based C coding. The real story is not this
> convention but the concepts researched by it's father, Charles Simonyi.
In
> graduate research at Xerox PARC he extensively investigated group-based
> coding. He focused heavily on how code can be improved by use of certain
> shared conventions. To this day one of the clearer benefits of any naming
> standard is ensuring that when you look at code you quickly can see what a
> variable represents and what a function does."
>
> Let me say at the ouset that I claim no "divine insight" in my prefixing
> system, or that it would work for anyone else. It is not even strictly
> logical, but has simply proven to be more useful to me than a strictly
> logical system. It will likely not be intuitively recognized by other
> scripters. It is optimized for VBS and even for WSC-hosted VBS, with a
> secondary focus on mark-up languages (HTML, XML, etc.), so its
> cross-platform and cross-language application is questionable.
>
> Regards,
> Joe Earnest
>
> -----
> Modified mark-up language "camel" casing is employed for all user-defined
> names; external objects, properties and methods; and constants. The
initial
> name segment is fully lowercased, while the initial character of
> non-delimited secondary name segments is capitalized. All inherent VBS
> keywords and function names fully lowercased. Entities and names created
> through XML and HTML methods are named as if they were created through VBS
> methods.
>
> All procedures are declared as functions, even if they provide no return
and
> are designed to be called only as statements. Unexposed functions are
> prefixed with an initial "fn" segment. Exposed methods and properties,
and
> their corresponding functions, are not prefixed, unless a conflict with an
> inherent VBS name requires the internal function to be prefixed.
Unexposed
> components (loosely, the WSC file equivalent of classes) are designated
with
> an initial "cp" segment, while exposed components are named to provide a
> recognizable call.
>
> All script is "Option Explicit". Variables are declared when and where
> required. The VBS "Const" statement is never used. The underscore
> character is not used in variable names, unless use is compelled by
context,
> but is, instead, reserved solely for line continuations.
>
> All variable names are prefixed, except for object variables that access
> unexposed components. This allows the variable name to be used as an
> exposed property.
>
> My peculiar variable prefixing is oriented toward identifying scope and
> usage, as well as identifying data subtype, when useful. Variables are
> given concise name segments to differentiate them and generally identify
> their content in context. Pluralized names are used for totals, as well
as
> for transitory variables that may change subtypes between arrays and
string
> lists. For example, in a hypothetical procedure, "viFile" could be a
local
> counter or iteration of files, "viFiles" could be a local reference to the
> total number of files, "vaFiles(...)" could be a local array of file
> objects, "vsFileName" would be a local file name string, and "vsFileNames"
> would be a local string list of file names that could be changed back and
> forth, to and from, an array, using the VBS "Split" and "Join" functions.
>
> Prefixing involves two characters: (1) the first indicates scope and
> argument usage, or is omitted for global variables; (2) the second
indicates
> type and usage, to the extent that I have found it useful.
>
> Variable Scope Prefix
>
> none e.g., sFile
> Globally defined.
>
> v e.g., vsFile
> Locally defined or ByVal argument. Both local definitions and ByVal
> argument variable values go out of scope when the procedure is exited.
All
> ByVal arguments are internally coerced to the procedure's required data
> subtype and/or range, but, because it is ByVal, the value passed is
> preserved. Note that, in VBS, object instances are always passed ByRef,
> even if there is a ByVal argument statement.
>
> r e.g., rsFile
> ByRef argument returned. The value passed is modified in the procedure
for
> return to the calling script. If an initial value is required, the data
> passed will be internally coerced to the required data subtype and/or
range.
>
> u e.g., usFile
> ByRef argument unchecked. Data for the argument must be passed as the
> anticipated subtype and/or range, to avoid an error in the procedure. The
> value passed is preserved.
>
> p e.g., psFile
> ByRef argument preserved. The data passed is coerced to the anticipated
> subtype and/or range without destruction, so that the value passed is
> preserved.
>
> c e.g., csFile
> ByRef argument coerced and destroyed. The data passed is coerced to the
> anticipated subtype and/or range, destroying the data passed.
>
> Variable Type and Usage Prefix
>
> The final variable prefix character indicates the variable's type and/or
> usage. All categories include an initial "Empty" data subtype, as well as
> any data subtype passed through a function's argument, or returned from a
> function, method or property, until the anticipated data type can be
> coerced. These categories have developed historically and
idiosyncratically
> over time, and have simply proved useful to me. They don't necessarily
make
> sense.
>
> a e.g., aFile, vaAmount
> Array. A variable that is declared and maintained solely as an array.
> Transitory string-list arrays may have an "s" prefix. Transitory
> string-lists that convert to arrays with mixed data types may have an "x"
> prefix. Note that this prefix does not articulate the data subtype(s) or
> any other aspects of its elements.
>
> f e.g., fErr, vfExists
> Boolean or numeric flag. A Boolean subtype, or a (long) integer numeric
> subtype with a value of "0" or "-1".
>
> i e.g., iRep, viItem, viItems, viInStrChr, viBit
> Integer or long integer. A (long) integer subtype used in a uniquely
> "integer" manner, as an instance, counter, pointer, address, element
number,
> position, bitwise, sequential or other numeric code, etc., or, with a
plural
> name, the total instances or the UBound of an array.
>
> n e.g., nHt, vnAmount
> A numeric subtype. Any other numeric data subtype or numeric usage.
>
> s e.g., sFile, vsName, vsFileList
> String. Any string data subtype or usage. May also include transitory
> string lists that are changed back and forth to or from arrays.
>
> o e.g., oFso, voShell, uoWshShell
> Object. An object instance data subtype or usage. Because VBS requires
> that object variables be passed ByRef, all object variables passed to a
> user-defined procedure should have a prefix indicating ByRef status.
> Scriptlet object variables that are exposed as properties in order to
allow
> access to unexposed components, are not prefixed, so that the variable
name
> may be used as an exposed property name.
>
> d e.g., dFileDate, vdToday
> Date. A date-time data subtype or usage.
>
> k e.g., kVersion, kSomeBitFlag
> Constant. Data of any subtype that is intended to be fixed and unchanged,
> once determined. Rarely used, but almost always global in scope, when
used.
> The VBS "Const" statement is not used, as such.
>
> x e.g., xUtility, vxArgCode, vxValueList
> Other, transitory or multi-type. A data subtype such as "Null" or
"Error",
> a transitory utility variable, a transitory string list that is converted
to
> or from a mixed data-type array, or an argument that may be validly
assigned
> different data subtypes.
>
>