VBScript Quirks for RhinoScript

May 15, 2026 · View on GitHub

Things that bite when writing .rvb / .vbs files and aren’t obvious to anyone whose mental model is C-family or Python.

Always Start With Option Explicit

Without it, mistyping a variable name silently creates a new Variant set to Empty. Every .rvb file should begin:

Option Explicit

No Block Scope

All Dim declarations inside a Sub/Function are hoisted to the top. A Dim inside an If block is visible after the If ends. Loop counters survive the loop.

Nothing vs Empty vs Null

SentinelTest withMeaning
EmptyIsEmpty(x)Dim’d but never assigned
NullIsNull(x)Explicit “no value” — what Rhino.GetObject returns on cancel
Nothingx Is NothingAn object reference that points to nothing — only for Set variables

Wrong sentinel → silently false.

Parentheses Change Semantics

Foo a, b              ' Call a Sub or Function (return value discarded)
Call Foo(a, b)        ' Call a Sub or Function (return value discarded)
x = Foo(a, b)         ' Call a Function and capture the return
Foo(a, b)             ' SYNTAX ERROR for multi-arg subs

Foo(x)                ' Calls Foo passing x BY VALUE, even if Foo declares ByRef
Foo x                 ' Honors Foo's ByRef declaration

If a Sub modifies its argument and your change isn’t taking effect — you wrapped the argument in parentheses.

ByRef Is the Default

Unlike most languages, VBScript passes arguments by reference by default. Functions can mutate their callers’ variables. Be explicit:

Sub Increment(ByRef n)
    n = n + 1
End Sub

Arrays Are 0-Based But Have UBound, Not Length

Dim arr(2)            ' Three elements: arr(0), arr(1), arr(2)
For i = 0 To UBound(arr)
    arr(i) = i * 10
Next

Dim arr(n) creates n+1 elements. ReDim Preserve arr(newSize) resizes (only the last dimension of a multi-dim array).

Set Is Required for Object Assignment

Set fso = CreateObject("Scripting.FileSystemObject")    ' correct
fso = CreateObject("Scripting.FileSystemObject")        ' RUNTIME ERROR

Any time the right-hand side is an object (COM object, RegExp, Dictionary), you must use Set.

Error Handling Is Manual

On Error Resume Next
Rhino.AddCircle Array(0,0,0), -1
If Err.Number <> 0 Then
    Rhino.Print "Failed: " & Err.Description
    Err.Clear
End If
On Error GoTo 0           ' Restore normal error behavior

On Error Resume Next suppresses all errors until On Error GoTo 0. Forgetting to restore is a common bug.

Points Are 3-Element Arrays

Rhino expects Array(x, y, z). A 2-element array (Array(x, y)) raises a type-mismatch error.

Dim pt
pt = Array(1.0, 2.0, 3.0)
Rhino.AddPoint pt

String Concatenation Uses &, Not +

+ on strings works only if both sides are strings. If one side is a number, + does numeric addition and throws a type-mismatch. Always use &:

Rhino.Print "Count: " & n

For Each Needs a Variant

Dim item
For Each item In someCollection
    ' ...
Next

The loop variable must be Variant. You cannot Dim item As Long (VBScript has no typed Dim).