Call keyword – deprecated or not

Consistency is King

Whether you’re calling a Sub or a Function makes no difference whatsoever. What matters is consistency, and that’s what Call-lovers claim using the keyword brings. Consistency with whether or not parentheses are required around the argument list.

So instead of this simple-as-it-gets implicit call statement:

MsgBox "I'm a function but you're discarding my return value, so no parentheses."

We get things like this:

MsgBox ("I'm a function but you're discarding my return value, and this call looks weird.")

And I’ve yet to see the Call actually being used with any kind of actual consistency:

Call MsgBox("I'm a function but you're discarding my return value, so I have a Call keyword.")
Call MyProcedure(42)
Call ActiveSheet.Range("A1:A10").Clear
Call Beep
Call CallByName(obj, "SomeMethod", VbCalType.VbMethod)

Used consistently, Call quickly becomes obnoxious, clearly redundant, and slows down reading, because the eyes can’t help but stop on the keyword, and then the brain goes “oh hey watch out, we’re calling something here”. I suppose at one point you just stop seeing it, and just feel like something’s off if it’s missing.

The overwhelming majority of every single executable statement is going to be a call to something, somewhere, at some abstraction level – using Call consistently makes the language even more heavily bulky than it already is.

Unless Call isn’t really about consistency, more about being able to easily see my own user procedure calls… which at this point is just grasping at straws to legitimize an archaic construct that serves no purpose whatsoever: there is no legitimate use for the Call keyword.

This is the only “legit” use case:

Public Sub Test()
DoSomething: DoSomethingElse
'vs.
'Call DoSomething: Call DoSomethingElse
End Sub

Private Sub DoSomething() '<~ dead code. can you see why?
End Sub

Private Sub DoSomethingElse()
End Sub

The Call keyword disambiguates a LineLabel: from a ParameterlessProcedureCall followed by an : instruction separator. Only problem is, : instruction separators are great for golfing and cramming as much executable code as possible on a single line of code …they are terrible for readability. Besides everybody agrees that a NEWLINE should follow a ; in any semicolon-terminated language, even though it makes perfect sense for the compiler to ignore the line jump.

We write code for people to read and maintain, not just for compilers to build and run.


Deprecated? Says who?

Says me and my ducky.

I’m 100% certain I’ve read in the Official docs at one point in my life, that the keyword was obsolete. Heck, it’s even specified as being redundant. Languages evolve, VBA is no exception – even with mind-blowingly incredible levels backward-compatibility and after two decades without any kind of significant changes, the language – or rather, its practices are still fluid, even if its maintainers have retired vowed to just let it be.

Call isn’t the only deprecated token in VBA, but for questionable subjective reasons not unsimilar to what people use to justify clinging to the formidable mistake that Systems Hungarian notation was in this century, its roots run deep.

Where are the defenders of the Rem comment marker? Why is While...Wend still a thing when Do While...Loop supersedes it? Is anyone raising errors with the Error statement rather than through Err.Raise? Outputting error messages with Error$ rather than through Err.Description? Declaring variable types with the ever-so-legible $&%^!# type hints? Who writes On Local Error? Why use Global for things that are really Public?

And if explicit Call isn’t obsolete and “makes the code more readable”, then why aren’t the same people using explicit Let statements for value assignments for the exact same explicitness/clarity reasons?

I think it’s well past time to rewrite what the best practices are, and leave Call in the past, along with Let, Hungarian Notation, and walls-of-declarations at the top of procedures. Every single programming community did this already – only the VBA community is still holding on to the “best practices” from 30 years ago, for brand new code, not just legacy stuff written in another era. I suspect it’s very much possible that VBA’s “dread score” has a lot to do with that, even without taking the bare-bones IDE into account.

I’d love to be able to pull a reference from fellow Microsoft MVP old-timers Rob Bovey and Stephen Bullen, and say “here, see, page 172 it says the call keyword is obsolete” (this answer seems to mention a “two inch thick book on VBA basically says don’t use it unless you want to use the Find feature of the VBE to easily find calls in large projects”), so this might be it, but in any case at the time these gurus essentially defined what the best practices were, “refactoring” was a foreign word, “unit testing” was an extreme programming crazy idea – the entire programming landscape has enormously evolved in the past 20 years, but VBA stood still. Time to end this, and move on forward.

Speaking of moving forward

“It makes it easier to migrate to VB.NET”

Allegedly, using Call statements make it “easier” to port the code to .NET, because VB.NET will want the parentheses everywhere. Respectfully, that’s bullocks. First because what you’ll want to port your VBA code to isn’t VB.NET but much more likely TypeScript, if any kind of porting is ever actually going to happen. If you’re manually copying VBA code and “translating it” to get it to compile in the target language, you’ll quickly find that not having to deal with parentheses is a very marginal perk, since literally everything else needs to be rewritten, …including dropping the Call tokens.

Writing small, specialized procedures that do very few things if ever more than a single one, leveraging abstraction levels and classes/objects, reducing coupling between modules, improving cohesion within modules, having your code’s behavior covered and documented with thorough unit tests, that will help you port your VBA code faster, and ensure the ported code works identically. Call and parentheses are just an excuse to keep a bad habit going.

Leave a Comment