What is the sense of a subroutine (Sub
)? Why not use a Function
without a return value?
Edit
What I mean is, why does the keyword Sub
exist? I can use Function
without declaring a return value and have the same, no?
What is the sense of a subroutine (Sub
)? Why not use a Function
without a return value?
Edit
What I mean is, why does the keyword Sub
exist? I can use Function
without declaring a return value and have the same, no?
I can think of a couple reasons off the top of my head.
It prevents the caller from trying to assign the non-existent return value to something:
In Excel, it allows it to be used as a macro (assuming that it doesn't have arguments).
It's unclear to somebody else who is reading the code what the intention is.
It (should, assuming otherwise decent coding practices) signals that it should not have side effects. A
Sub
is expected to have side-effects.Specifically regarding the edit.
This is not a correct statement. If you declare a function like this...
...it still has a return value - it is just implicit. The code above is exactly equivalent to:
VBA doesn't force you to explicitly declare the type of the return value (similar to how it doesn't require an explicit type for a
Dim
statement). That does not mean that it doesn't have one - it does.It is possible (not advisable, nor a good practice) to use boolean functions instead of
Sub
s everywhere and make sure that they even returnTrue
once they reach the end.Like this:
This is easy to test with one line:
Debug.Print Main
Then you can use it like this:
If Not SomeFunction Then IncrementLogString ("SomeFunction")
And at the end, you may check the log with all the functions, that were false.To be honest, I have only done this once, about 5 years ago, because the other dev insisted on it and I did not have a choice. Concerning the fact, that it was probably the biggest VBA application I have seen and it ran smoothly (I was not the main developer there, thus taking no credit there), I guess there is no problem in it. After some time I got used to it and it was fun. But in general, people would frown upon it.
Because it clarifies the intent.
A
Function
clearly says "I'll have something for you when I return". The expectation is that aFunction
returns something, because that's what functions are meant to do.A
Sub
clearly says "I'm doing something that you should expect to just eventually succeed". The expectation is that aSub
executes an action, alters some state, causes some side effects.A
Function
that would be namedDoSomething
, is just as confusing as aSub
that would be namedGetFoo
: the intent is obscured, the very nature of the procedure conflicts with how it's advertised. I expectDoSomething
to either succeed at doing something, or throw some error. Similarly, I expectGetFoo
to, well, get me aFoo
.Because a non-returning function makes no sense.
In several programming languages, a
Function
(or semantically similar construct) that doesn't return a value in all code paths, can't even be compiled. Using a Function-without-a-return-value for everything in VBA sounds very much like abusing the language, just because VBA won't complain about it. As common wisdom tells us, it's not because we can, that we should.Why return
void
, when you can return abool
everywhere, and not assign it?A VBA
Sub
procedure is like a C#void
method: it's explicit about its non-returning nature, and that's a good thing.Because static code analysis tools will complain.
The VBA compiler will notoriously not care if you write code where it's never clear whether your non-returning of an implicit return value is intentional or not.
When you do mean to return a value - and forget, because bugs happen all the time - how can you be sure that this one is legitimately non-returning, and that other one isn't? Without combing through the code and fully understanding everything it does and why, you can't tell. If you're lucky, you're looking at small, specialized functions that obviously do one thing, and do it well. Otherwise, you need to waste your time understanding what's going on, just to be sure of something that should already be obvious.
Static code analysis tools like Rubberduck (I maintain that project) will flag these functions, since they are potential bugs hiding in your code base, waiting to bite you:
The real question to be asking is not why
Sub
exists, but whyFunction
exists! Why?VBA is built on top of VB6 which is built entirely on top of COM. unfortunately I can't find the source for this but, all COM methods must return a
HRESULT
. This means that all VBA/VB6 methods are, once compiled, sub-routines!But if all methods are sub routines, how come my method returns a value? Well, let's look at an example
ISynchronizeHandle::GetHandle
:As you can see, the parameter for the return value is actually supplied by reference in the DLL C++ header definition. By convention this return type is always the last parameter. So for
IStdMarshalInfo::GetClassForHandler
the definition is:where the class returned is returned as the
CLSID
of the class (last parameter).The C++ header for
Application.Evaluate()
would look something like this:This would be similar to us implementing a sub-routine as follows:
And thus whenever we call the function we'd need to prepare a return type first and then call the sub.
This kind of sucks... So Microsoft figured "Hey, let's give the VB engine a way to return data. We'll just wrap the existing sub behaviour under the hood, but our VM will handle the real result and return that to the user's function". So instead of extending the existing sub-behaviour, they likely just wrapped the behaviour and created a new declare
Function
.Ultimately
Function
was only implemented as an afterthought toSub
. This is whySub
exists at the onset.Bear in mind that you can make a custom
VOID
class for example and then write:and then call your function like:
But it isn't advised.