VBScript!

I've been fighting with a little script I wrote to massage some text for me. It's a very simple task so I thought VBS would be adequate (read each line of text, if there's a special bit of text in the line capitalize everything to its right - no big deal). I know I can use C# and JavaScript if I use Windows' Powershell, but I didn't think VBS would have any trouble with it. And it didn't. But I learned something ridiculous about VBS in the process.

Here is a very simple VBScript program.

Function timesTwo(ByRef inParam)
    inParam = inParam * 2
    timesTwo = 1
End Function

i = 10

WScript.Echo "i = " & i
timesTwo(i)
WScript.Echo "i = " & i
z = timesTwo(i)
WScript.Echo "i = " & i

Here I have a simple function called 'timesTwo' that multiplies its input parameter by two and returns a value of 1. Since I declared the input of the function "ByRef", the input is passed "by reference", which basically means the function can change the value of the parameter. If I pass it a variable with a value of 5, the variable should have a value of ten when the function ends. Magic.

If the parameter was declared "ByVal" ("by value"), the function would receive a copy of the input parameter, which it could modify as much as it wanted, but changing the copy wouldn't change the value of the original parameter. But I didn't declare it that way...

The code below that function tests the function. It...

  1. initializes a variable called 'i' to a value of 10 (i = 10)
  2. prints the value of i (WScript.Echo "i = " & i )
  3. calls the function, ignoring its return value. (timesTwo(i))
  4. prints the value of i
  5. calls the function again, putting its return value in a variable 'z'. (z = timesTwo(i))
  6. prints the value of i

So, what do you think we should get?

i = 10
i = 20
i = 40

That seems reasonable. Start with i = 10, print i, call the function to double i, print i, call the function to double i again, print i.

But if that worked, this would be a truly boring blog post!

No, what we actually get is:

i = 10
i = 10
i = 20

Why? Well, I don't know exactly why. But, the effect is: if you ignore the return value of a function, the parameter you pass is actually passed by value (ByVal), not by reference.

Pass by value:

timesTwo(i)

Pass by reference:

z = timesTwo(i)

What. The. Fuck.

Why would that difference in behavior ever be useful, let alone expected ?

I should've used JavaScript.

6 thoughts on “VBScript!

  1. Rob Caldecott

    Slightly off topic but my JavaScript linter is configured to stop function parameters ever being modified: I always treat them as constants. Far too easy to get yourself in a proper mess.

    But VBS… shudder. I always managed to stay away from it. Remember the iloveyou.vbs virus from around 2000? Ha! Every fucker in our office opened that bastard.

    1. cleek Post author

      ByRef is how you get around having to create classes to hold multiple return values! let the stack be your struct!

  2. Rob Caldecott

    You love this stuff really and choose VBS because you knew it would offer up some WTF moments. Geek masochism!

    1. cleek Post author

      if i really wanted to hurt myself, i could’ve tried to write this thing in Bash or … in a regex !

  3. Rob Caldecott

    Have you discovered the joys of Node yet? I bet there is already a package on npm that does exactly what you want.

    I’m an npm addict.

Comments are closed.