Mid() function crippled?

K

Ken VdB

Hi everyone,

Is there a reason why the Mid() function only works in one direction in
VBScript? This code works in VB6 but not in VBScript? Is there a way
around it? I am trying to create an ASP page which produces a fixed width
text file for import into a third party legacy application which I don't
have control over.

--code sample--
Dim strSomeString

strSomeString = Space(100)

Mid(strSomeString, 1, 4) = "test"
Mid(strSomeString, 10, 20) = "Something else"
--end sample--

Thanks,

Ken.
 
E

Evertjan.

Ken VdB wrote on 02 apr 2004 in microsoft.public.inetserver.asp.general:
Mid(strSomeString, 1, 4) = "test"
Mid(strSomeString, 10, 20) = "Something else"

Not in VBScript. Please read the specs.

the script languages vbscript and jscript only handle complete strings.

However you can make a function like that:

function toMid(insert,inserted,start)
toMid = left(inserted,start) &_
insert & mid(inserted,start+len(insert))
end function
 
J

Joe Earnest

Hi,

Ken VdB said:
Hi everyone,

Is there a reason why the Mid() function only works in one direction in
VBScript? This code works in VB6 but not in VBScript? Is there a way
around it? I am trying to create an ASP page which produces a fixed width
text file for import into a third party legacy application which I don't
have control over.

--code sample--
Dim strSomeString

strSomeString = Space(100)

Mid(strSomeString, 1, 4) = "test"
Mid(strSomeString, 10, 20) = "Something else"
--end sample--

To add a bit to Evertjan's reply, using the same terminology as the MS
documentation:

The Mid "function" (i.e., x= mid(...) ) works in VBS exactly as it does in
VB (or, for that matter, QB). The Mid "statement" (i.e., mid(...)= ... ),
however, is not available in VBS.

Joe Earnest
 
E

Evertjan.

Joe Earnest wrote on 03 apr 2004 in
microsoft.public.inetserver.asp.general:
To add a bit to Evertjan's reply, using the same terminology as the MS
documentation:

The Mid "function" (i.e., x= mid(...) ) works in VBS exactly as it
does in VB (or, for that matter, QB). The Mid "statement" (i.e.,
mid(...)= ... ), however, is not available in VBS.

The problem is Microsoft in its Basics systematically tries to obscure
the difference between a statement and a function.

Making the "Let" (1980?) statement and the "Call" (1995?) statement both
be default is part off this.

Newbees, those that started programming after those days that is, will
never get a deep understanding of the exact meanings, if they are not
historically inclined.

=============

The mid() statement is specially usefull if the stringvariable can be
internally manipulated, thereby improving speed [= processortime
consumption] and space [= memory consumption]. In interpreted [= script]
language kernels this is not as useful as in assembling language [pre]
processing.

A nice inbetween is the Forth language [kernel dependent, of cource]
where a string variable can only be manipulated "in place", if the result
gets a shorter, or keeps the same length.

The mid() function, on the other hand, is not crippled at all.
 
J

Joe Earnest

Hi,

Evertjan. said:
Joe Earnest wrote on 03 apr 2004 in
microsoft.public.inetserver.asp.general:
To add a bit to Evertjan's reply, using the same terminology as the MS
documentation:

The Mid "function" (i.e., x= mid(...) ) works in VBS exactly as it
does in VB (or, for that matter, QB). The Mid "statement" (i.e.,
mid(...)= ... ), however, is not available in VBS.

The problem is Microsoft in its Basics systematically tries to obscure
the difference between a statement and a function.

Making the "Let" (1980?) statement and the "Call" (1995?) statement both
be default is part off this.

Newbees, those that started programming after those days that is, will
never get a deep understanding of the exact meanings, if they are not
historically inclined.

=============

The mid() statement is specially usefull if the stringvariable can be
internally manipulated, thereby improving speed [= processortime
consumption] and space [= memory consumption]. In interpreted [= script]
language kernels this is not as useful as in assembling language [pre]
processing.

A nice inbetween is the Forth language [kernel dependent, of cource]
where a string variable can only be manipulated "in place", if the result
gets a shorter, or keeps the same length.

The mid() function, on the other hand, is not crippled at all.

Good points. From past experience, I tend to think of what the compiler is
looking at when it's parsing, and tend to forget that many scripters don't
think that way. The Mid function and statement are obviously two entirely
separate underlying code routines, "masked" (if you will) by the use of the
same inherent name (or keyword in some versions of BASIC), but recognized by
placement relative to the equals sign.

Omitting Let and Call never bothered me, since the parsing syntax still
seems obvious to scan (left-versus-right side of the equals sign, or no
equals sign). I think the Call omission must have occurred prior to 1995 --
as best I can recall, you could omit it in all minor versions of QuickBASIC
4, *if* you declared the procedure at the outset. (ca. 1990-92 ??)

I've never used Forth. The result sounds curiously like an old DOS compiled
QuickBASIC trick, which was to access the data heap directly, by getting the
data heap offset and getting the relative variable offset from the variable
list, and then poking changes into a variable definition. You couldn't
change type or increase string length, but you could modify it in any other
way. Shortening a string required poking a change in string length into the
variable list data, leaving the remainder of the original string length as
inaccessible "dead area" data, until the next data heap recompilation.
Particularly useful for tweaking ASM call strings on-the-fly, changing
literal assignments and accessing variable data in other local heaps, but it
also avoided a time- and memory-consuming data heap recompilation, even when
used in lieu of a simple redefinition of a global variable. But then time
and memory were at more of premium in DOS days.

Regards,
Joe Earnest
 
E

Evertjan.

Joe Earnest wrote on 03 apr 2004 in
microsoft.public.inetserver.asp.general:
Omitting Let and Call never bothered me, since the parsing syntax
still seems obvious to scan (left-versus-right side of the equals
sign, or no equals sign).

The difference between
Let a = 3
and
If a = 3 Then

would have been much clearer to many a newbee

==================

the asp-vbs statement:

response.write "hello"

is written by many with a function syntax as

response.write("hello")

Only accidentally being parsed correctly,
because there is only 1 argument in this case

I think the Call omission must have
occurred prior to 1995 -- as best I can recall, you could omit it in
all minor versions of QuickBASIC 4, *if* you declared the procedure at
the outset. (ca. 1990-92 ??)

Could be, I was just guessing from memory
I've never used Forth. The result sounds curiously like an old DOS
compiled QuickBASIC trick, which was to access the data heap directly,
by getting the data heap offset and getting the relative variable
offset from the variable list, and then poking changes into a variable
definition.

Forth was, is, much more versatile, since you define your own string on
the fly and interpret/compile (no real difference in Forth) it in general
continuous memory space (for instance, in Forth there are many ways to
Rome) by:

[nextunitpointer][namelength] name [stringlength] stringcontent
 
J

Joe Earnest

Hi,

Evertjan. said:
The difference between
Let a = 3
and
If a = 3 Then

would have been much clearer to many a newbee

True. As a substitute in the case of your conditional "If" statement, as
part of my systematic casing, simplified HN and syntax, I routinely use
parentheses around conditionals (If, While, Until, ...), even if simple or
following default order. It scans better and helps to avoid logical errors
when using bitwise logical operators with conditions. The parentheses do
not seem to slow parsing. (I suspect that they may even speed it up to some
very slight degree, since the interpreter does not have to test for literal
grouping, then fall back on default modes of parsing.) They also flag for
me, in quick visual scanning, the fact that I've got a conditional
statement. For the same reason, I routinely all-cap only bitwise logical
operators, to remind me what I've got. The obscure untrapped errors
generated by improper interaction between zero/non-zero conditionals and
bitwise logical operators, as well as VBS's annoying problem of not
comparing true numerics and string numerics, seems to be a real problem for
newbees who've never masked, and remains one that needs to caught for
everyone on visual scanning. E.g., ...

if (n=3) then ...
if NOT (n=3) then ...
if ((n1=3) AND (NOT cbool(n2))) then ...
if (n=(sN +0)) then ...
==================

the asp-vbs statement:

response.write "hello"

is written by many with a function syntax as

response.write("hello")

Only accidentally being parsed correctly,
because there is only 1 argument in this case

That gets me into a digression ...

For me, a useful overview metaphor (but *not* one that bears up to strict
scutiny or literal use), is to think of BASIC as a living language, that is
absorbing other dialects, while retaining its own identity and shortening
its syntax over time. Many people find the ambiguous structure of BASIC
difficult, for the same general sort of reason that a "mongrel" and
ambiguous language like modern American English seems difficult.
Object-orientation, in the past, and mark-up language syntax (which has
strong C and Java ties), in the present, as well as general influence from
other languages, have pushed the syntax somewhat and added to the
syntactical ambiguity. I like it, as a general utility language, but then I
have a history with it. To me, the reality-check for understanding its
ambiguities lies in trying to directly visualize its operation as parsed
machine language, not in comparing it to an intermediate language.

Back more on point, BASIC's syntactical ambiguities and multiple ways to
accomplish tasks have always led to masking some misunderstood or "sloppy"
coding. Although its dialects vary in application, I think that it's best
intended as a utility language, more for temporary or local fixes, than for
long-term general distribution. Even in DOS QB days, anything seriously
programmatic usually involved cross-compiling QB and MASM.
I've never used Forth. The result sounds curiously like an old DOS
compiled QuickBASIC trick, which was to access the data heap directly,
by getting the data heap offset and getting the relative variable
offset from the variable list, and then poking changes into a variable
definition.

Forth was, is, much more versatile, since you define your own string on
the fly and interpret/compile (no real difference in Forth) it in general
continuous memory space (for instance, in Forth there are many ways to
Rome) by:

[nextunitpointer][namelength] name [stringlength] stringcontent

I'll have a look at it. Sounds like its structurally optimized for text
manipulation. And the continuuous memory space sounds intriguing, Thanks.

Regards,
Joe Earnest
 
B

Bonj

Let's say, for instance, I wanted a routine that would determine whether the
second letter of a given string was "a". Should I write:

Function IsSecondLetterA(InString)
IsSecondLetterA = (Mid$(InString, 2, 1) = "a")
End Function


??
That function doesn't work in VBScript, but it does in VB6. Confusing, isn't
it?
If I put
Mid$(InString, 2, 1) = "a"
then it changes the second letter to a whatever, but when I assign it with a
second equals as above, it doesn't. This wouldn't be the case in C++ though
would it. So I guess it's not "it's position relative to THE equals sign",
but "whether it has AN equals sign to the left of it".

Joe Earnest said:
Hi,

Evertjan. said:
Joe Earnest wrote on 03 apr 2004 in
microsoft.public.inetserver.asp.general:
To add a bit to Evertjan's reply, using the same terminology as the MS
documentation:

The Mid "function" (i.e., x= mid(...) ) works in VBS exactly as it
does in VB (or, for that matter, QB). The Mid "statement" (i.e.,
mid(...)= ... ), however, is not available in VBS.

The problem is Microsoft in its Basics systematically tries to obscure
the difference between a statement and a function.

Making the "Let" (1980?) statement and the "Call" (1995?) statement both
be default is part off this.

Newbees, those that started programming after those days that is, will
never get a deep understanding of the exact meanings, if they are not
historically inclined.

=============

The mid() statement is specially usefull if the stringvariable can be
internally manipulated, thereby improving speed [= processortime
consumption] and space [= memory consumption]. In interpreted [= script]
language kernels this is not as useful as in assembling language [pre]
processing.

A nice inbetween is the Forth language [kernel dependent, of cource]
where a string variable can only be manipulated "in place", if the result
gets a shorter, or keeps the same length.

The mid() function, on the other hand, is not crippled at all.

Good points. From past experience, I tend to think of what the compiler is
looking at when it's parsing, and tend to forget that many scripters don't
think that way. The Mid function and statement are obviously two entirely
separate underlying code routines, "masked" (if you will) by the use of the
same inherent name (or keyword in some versions of BASIC), but recognized by
placement relative to the equals sign.

Omitting Let and Call never bothered me, since the parsing syntax still
seems obvious to scan (left-versus-right side of the equals sign, or no
equals sign). I think the Call omission must have occurred prior to 1995 --
as best I can recall, you could omit it in all minor versions of QuickBASIC
4, *if* you declared the procedure at the outset. (ca. 1990-92 ??)

I've never used Forth. The result sounds curiously like an old DOS compiled
QuickBASIC trick, which was to access the data heap directly, by getting the
data heap offset and getting the relative variable offset from the variable
list, and then poking changes into a variable definition. You couldn't
change type or increase string length, but you could modify it in any other
way. Shortening a string required poking a change in string length into the
variable list data, leaving the remainder of the original string length as
inaccessible "dead area" data, until the next data heap recompilation.
Particularly useful for tweaking ASM call strings on-the-fly, changing
literal assignments and accessing variable data in other local heaps, but it
also avoided a time- and memory-consuming data heap recompilation, even when
used in lieu of a simple redefinition of a global variable. But then time
and memory were at more of premium in DOS days.

Regards,
Joe Earnest
 
E

Evertjan.

Bonj wrote on 04 apr 2004 in microsoft.public.inetserver.asp.general:
The mid() statement is specially usefull if the stringvariable can
be internally manipulated, thereby improving speed [= processortime
consumption] and space [= memory consumption]. In interpreted [=
script] language kernels this is not as useful as in assembling
language [pre] processing.
Let's say, for instance, I wanted a routine that would determine
whether the second letter of a given string was "a". Should I write:

Function IsSecondLetterA(InString)
IsSecondLetterA = (Mid$(InString, 2, 1) = "a")
End Function


??
That function doesn't work in VBScript, but it does in VB6. Confusing,
isn't it?
If I put
Mid$(InString, 2, 1) = "a"
then it changes the second letter to a whatever, but when I assign it
with a second equals as above, it doesn't. This wouldn't be the case
in C++ though would it. So I guess it's not "it's position relative to
THE equals sign", but "whether it has AN equals sign to the left of
it".

It should not be all that confusing.

[confusing is that you change to topposting in the middle of a thread,
corrected]

confusing to you is that you do not see the difference between a
statement and a function.

Let mid(..) = "123"
'' "let" statement is not available anymore so leave it out

Here the mid() statement is used, not available in vbscript.

If mid(..) = "123" Then

This is using the mid(..) function available in vbscript
in a boolean resulting comparison.

==================================

btw:

IsSecondLetterA = ( Mid(InString, 2, 1) = "a" )

[leave out the $ of mid$ in vbscript,
since you are most probably not referring to a byte string]

and easier

IsSecondLetterA = ( instr(InString,"a") = 2 )

are the same
 
B

Bob Barrows

Bonj said:
Let's say, for instance, I wanted a routine that would determine
whether the second letter of a given string was "a". Should I write:

Function IsSecondLetterA(InString)
IsSecondLetterA = (Mid$(InString, 2, 1) = "a")
End Function


??
That function doesn't work in VBScript, but it does in VB6.
Confusing, isn't it?

Yes this assertion is confusing, considering that this statement works fine
on my machine:

IsSecondLetterA = (Mid(InString, 2, 1) = "a")

Oh! I see the problem: you're attempting to use the "$" version of the
function. Given that all variables are variant in vbscript, the Mid$, Left$,
etc. functions are not supported. It's not explicitly mentioned on this
page:
http://msdn.microsoft.com/library/en-us/script56/html/vsgrpnonfeatures.asp
but it is implied in the Data Types row.


If I put
Mid$(InString, 2, 1) = "a"
then it changes the second letter to a whatever

You're talking about doing this in VB/VBA, right? The above statement does
not work in vbscript, because:
1. the Mid statement is not supported.
2. the "$" version of string functions is not supported

If you look up Mid in the VB/VBA documentation, you will see that it is
listed twice: once as the Mid function, and once as the Mid statement. If
you look it up in the vbscript documentation, you will only see it listed as
a function.

Just to reiterate, in this statement

x = Mid(InString, 2, 1)

Mid is a function (functions return values, statements and subs do not).

In this statement:

Mid(InString, 2, 1) = "a"

Mid is being used as a statement.

I think the other reason you are being confused by your example:

IsSecondLetterA = (Mid$(InString, 2, 1) = "a")

is because you have used the shorthand method of writing this routine. You
are actually using the Mid$ as a function, but it's hard to recognize this
because you've taken the shortcut of not assigning the value returned by
Mid$() to a variable. If you had written it out completely:

x = Mid$(InString, 2, 1)
If x = "a" then
IsSecondLetterA = True
else
IsSecondLetterA = True
end if

It would have been obvious that you were using Mid as a function. What you
need to realize is that in the background, when vb/vba/vbscript executes
this statement:

IsSecondLetterA = (Mid(InString, 2, 1) = "a")

the first thing it does is assign the value returned by the Mid function to
an implicit variable, which is used in the boolean expression, which returns
the appropriate boolean value which gets assigned to the IsSecondLetterA
variable. The implicit variable is then discarded.

Another example of this type of confusion is when people use the MsgBox
function:

if msgbox("Continue?",,"title") = vbYes then

vs

msgbox "Message",,"title"

But this situation is a little different: MsgBox is only a function and
cannot be called as a statement. Notice that when it is used to simply
display a message that no parentheses are used. If you attempt to use
parentheses in that statement you will get an error. With the Mid statement,
however, you have to use the parentheses. Try this in the VB debug window to
see:

x="abc":Mid x,2,1 = "d":?x

To me this is very confusing, since the Mid statement appears to be the only
statement that requires parentheses around its arguments. It is the only
violation of the rules I use to determine when to use parentheses:

1. If the method returns a value which is either evaluated by the calling
statement or assigned to a variable, parentheses are required.
2. Otherwise, do not use parentheses

If I wrote a subroutine which did what the Mid statement does:

Sub MyMid(ByRef pStringIn, ByVal pStartPos, _
ByVal pLength, ByVal pReplace)
pStringIn = Left(pStringIn, pStartPos -1) & _
pReplace & Mid(pStringIn, pStartPos + pLength)
End Sub

I would have to call it without parentheses:

x="abcdef":MyMid x,2,2,"hi":?x

Using parentheses would raise an error, which my rules would lead me to
expect.

Many people suggest using the Call statement to avoid this decision:

x="abcdef":Call MyMid(x,2,2,"hi"):?x

but to me, this still requires you to know when to use Call. You cannot use
Call when calling a function whose return value you wish to use, can you? I
prefer my simple rules, which have yet to let me down (except with the Mid
statment of course)

HTH,
Bob Barrows
 
J

Joe Earnest

Hi,

Bonj said:
Let's say, for instance, I wanted a routine that would determine whether the
second letter of a given string was "a". Should I write:

Function IsSecondLetterA(InString)
IsSecondLetterA = (Mid$(InString, 2, 1) = "a")
End Function


??
That function doesn't work in VBScript, but it does in VB6. Confusing, isn't
it?
If I put
Mid$(InString, 2, 1) = "a"
then it changes the second letter to a whatever, but when I assign it with a
second equals as above, it doesn't. This wouldn't be the case in C++ though
would it. So I guess it's not "it's position relative to THE equals sign",
but "whether it has AN equals sign to the left of it".

Both Evertjan's and Bob's thorough posts have pointed out the fundamental
"$" and "Mid" statement issue and other syntactical issues. No hard typing
or type-suffixes in VBS, for either variables or functions. And no
parentheses usage will "save" a "Mid" statement that doesn't exist as an
inherent procedure in VBS.

To clarify my prior post, the position of various "=" 's on a line, if any,
tells you the operative nature of the entities that are to the left or right
of its operative scope, or standalone (without an equals sign in the
operative scope). A function behaves as a "function" or "property" when you
get a return from it, but as a "sub", "method" or literal "property", when
you use it as a standalone statement. A function behaves as a "variable"
(and, in fact, you are using a transitory return variable created in the
variable list), when used with comparison, conditional or bitwise logical
operators.

I always put parentheses around a comparative "=" operator, particularly
when used in an assignment. Technically, you don't have to. If there are
multiple "=" 's on a line (not otherwise confined in scope, as in an
argument or a conditional phrase), the parser will interpret the first "="
as an assignment operator and the remainder as comparison operators in a
default order. But the parentheses help me scan the code visually and, when
checking the code, if I have made a mistake such as a boolean-comparison
mismatch or comparing a numeric string to numeric subtype, or in
multiple-comparison ordering. Others, however, particularly those who may
rely on a specific editor's capabilities, find the multiple parentheses to
be an annoying clutter.

Heavily grouping through parentheses seems to have negligible, if any,
effect on parsing speed.

So, in the end, it's like casing, spacing and Hungarian Notation -- use what
works for you (i.e., actually helps you -- not make-work), or is required in
or for your work environment. I developed my casing/spacing/HN/parentheses
standard over a long period of time (and Alex Angelopoulos forced me to take
a hard look at it, recently, that resulted in some revisions). I'm glad to
share it. But many accomplished scripters have other standards.

Joe Earnest
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top