Where in the VB6/VBA project references do Array(), LBound(), and UBound() come from..? - vba

Where in the VB6/VBA project references do Array(), LBound(), and UBound() come from..? When I'm typing in code, they don't appear in the Autocomplete list (ctrl+space), they don't get autocompleted, and they must be typed out completely before the text editor recognizes them. And only when a left-parenthesis is typed will ToolTipText pop up with the command syntax. Also, they do not appear anywhere in Object Explorer.
There's probably a basic concept in play here that I'm not aware of. And it makes me wonder, what other commands/statements/keywords are hidden in the same way..? Is there a list somewhere..? I googled for info but didn't find anything, probably because I don't know what I'm looking for and using the wrong search terms.
I ask these questions because I have the habit of prefixing many VB6 built-in functions like this: VBA.Left(), VBA.Len, VBA.Instr(), and so on. But I can't figure out what reference prefeix to use with Array(), LBound(), and UBound(), or perhaps they're so basic to VB6 that they don't have one.
I do this prefixing because years ago I was working on a large project, and there were functions I was trying to use with the same name in different reference libraries. I was a newbie and it took me a while to figure out, and it was causing tremendous problems since the functions were just NOT working the way I thought they were supposed to. It was then that I developed the prefixing habit after I figured it out. It's just easier that way, and always ensures the expected functions are being used.

The reason that they don't appear as IntelliSense options (and also why they don't appear in the Object Browser) is that they aren't declared in the VBE7.dll typelib for some reason that's beyond me. The Array function is implemented in the .dll as rtcArray. The utility of knowing that is dubious, in that its sole argument is a ParamArray, which means that if you called it directly from VBE7.dll you would need to create an array to have it feed you back the same array... This partially explains why it isn't on the typelib - a COM call would need to do the same thing, and the marshaling would basically be doing the same thing as what you'd expect the function to return.
LBound and UBound don't even appear as functions in the export table, so my guess is that they are handled more like "keywords" than first class functions internally. This makes some sense, in that it's fairly trivial to check the bounds of a SAFEARRAY if you have a pointer to the automation struct (you just index into the rgsabound array at the end of it and read the cElements and lLbound from it. Again a guess, but I'd assume that this allows for flexibility in letting LBound and UBound function with both fixed length and variable length arrays. In the fixed case, the array is basically managed as a block of memory with an indexer (more like a VT_CARRAY than a VT_SAFEARRAY). I'd imagine that handling this internally was easier or more convenient than providing first-class functions.

You won't find Debug in the Object Browser either, nor its methods Assert and Print.
You won't find Statements that are used like methods, like Open, Close, Get and Put, which is why you don't get any Intellisense when you use those statements, and the syntax must be memorized.
You will find Load and Unload as members of VBA.Global, but it's not clear what they belong to otherwise, and their arguments are late-bound Objects. The VBA documentation states that Load and Unload are Statements, even though the Object Browser shows them as Methods.

Keep in mind that you can move the order of references and it will make a difference. Try moving VBA to the top or near the top of your list of references. I believe that if something else also defines a BASIC keyword, it steals it, in a sense. I once had Right disappear and because I was not aware of the order of references, had to change all references of Right to VBA.Right. It's possibly the same with the ubound, lbound, or array.

Related

Where is "require" defined?

I have been looking in Rakudo source for the implementation of require, first out of curiosity and second because I wanted to know if it was returning something.
I looked up sub require and it returned this hit, which actually seems to be the source for require, but it's called sub REQUIRE_IMPORT. It returns Nil and is declared as such, which pretty much answers my original question. But now my question is: Where's the mapping from that sub to require? Is it really the implementation for that function? Are there some other functions that are declared that way?
require is not a sub, but rather a statement control (so, in the same category of things like use, if, for, etc.) It is parsed by the Perl 6 grammar and there are a few different cases that are accepted. It is compiled in the Perl 6 actions, which has quite a bit to handle.
Much of the work is delegated to the various CompUnit objects, which are also involved with use/need. It also has to take care of stubbing symbols that the require will bring in, since the set of symbols in a given lexical scope is fixed at compile time, and the REQUIRE_IMPORT utility sub is involved with the runtime symbol import too.
The answer to your question as to what it will evaluate to comes at the end of the method:
$past.push($<module_name>
?? self.make_indirect_lookup($longname.components())
!! $<file>.ast);
Which means:
If it was a require Some::Module then evaluate to a lookup of Some::Module
If it was a require $file style case, evaluate to the filename

VBA Declaring a library vs dynamically loading it

I'm creating an application in VBA that uses a reference from vbscript.dll
I'm trying to figure out the best way to load the library, and am having difficulty distinguishing between using a declare function (http://msdn.microsoft.com/en-us/library/aa716201(v=vs.60).aspx) or just dynamically adding it to the list of references (How to add a reference programmatically, part 2 of the top answer)
If anyone can clarify the difference in result between the two, and maybe some advantages of one, I would be very happy.
My Notes:
I like the looks of a simple declare function, for one thing it's short and looks nice. For another, I like avoiding hard coded paths unless I know the files won't be found in different places.
On the other hand, I really like the error handling in method 2.
Declare is (typically) used for calling stdcall-supported functions exported from Windows DLLs. The VB run-time takes care of calling LoadLibrary, GetProcAddress, etc. to locate and load the functions you've declared. Most of the Windows API is used this way from VB/VBA.
References are used for COM objects -- that is, libraries that define a type library and a COM interface.
It's rare for a library to support both. If what you have is a COM library (if it appears in the 'References' dialog), add a reference to it and instantiate it that way.

Is there a way in elisp to make variable access trigger a function call?

I am programming in elisp, and I would like to associate a symbol with a function such that an attempt to access the variable instead calls the function. In particular, I want to trigger a special error message when lisp code attempts to access a certain variable. Is there a way to do this?
Example: suppose I want the variable current-time to evaluate to whatever (current-time-string) evaluates to at the time the variable is accessed. Is this possible?
Note that I do not control the code that attempts to access the variable, so that code could be compiled, so walking the tree and manually replacing variable accesses with function calls is not really an option.
You are looking for the Common Lisp define-symbol-macro.
Emacs Lisp lacks this feature, you cannot accomplish what you are trying to do.
However, not all is lost if you just want an error on accessing a variable.
Just makunbound it and access will error out (unless, of course, someone else nds it first).
I don't think you can do that.
As Sam says, define-symbol-macro would be the closest thing in Lisp (tho you make it sound like the accesses might be compiled beforehand, in which case even define-symbol-macro would be powerless). The closest thing in Elisp would be cl-symbol-macrolet, but that is even more limiting than define-symbol-macro since it has to be placed lexically around the accesses.

Odd behaviour of casing of a control name in vb6 code

I have a label control on a form named lblTotal
During my last commit to the repository I was surprised to see this form's name on the modified list.
When I looked through the code I saw that all occurrances of this control's name were now lbltotal, (ie Small t).
The control's name itself was lblTotal in the properties window.
Further when I used ctrl-F with case matching to find lbltotal it would only find one as instantly all other occurrances would revert to lblTotal.
So it seems that at some moment after the IDE records some event in the code window it gets around to making the casing conform to the control's name.
What I don't understand is how this happened in the first place without a change to the control's name?
Can someone explain how?
PS After I wrote the above I saw this. Interestingly I also had a string variable that's name had its casing changed during the same commit and I assumed I must have changed it myself but now, having read the above I think it's because the same variable name was present in a different scope.
However there is no other occurrance of lbltotal anywhere else in the project.
PPS lblTotal is actually lblTotal(0) and many more copies are loaded during runtime, so a lot of the code references are lbltotal(x1).Caption etc. I don't know if this makes any difference.
Finally has anyone ever seen vb6 change the casing of string literals by itself? (Please God no!!)
Actually this last point is what causes me the most unease about this experience as in TOO many places in the codebase string literals are used in conditional clauses.
On top of the behaviour mentioned, VB6 will also re-case variable names that happen to occur in any of the COM interfaces your program references, which means that if you reference a new library, or change their order, you're in for even more fun.
At one time I even wrote a small program that "right-cased" VB6 source code from a dictionary of names ; the main drawback to that is you have to run it before each source commit.
But I think the answer from wqw here -> https://stackoverflow.com/a/1078018/108753 is probably the best solution to the problem I've seen, because he has quantified and exploited the behaviour of the IDE to solve the problem.
At least it's not VB3 - VB3 re-cases every variable in any files you have loaded into memory to what you last typed. Which makes you a lot more precise about typing case in variable names....

Function overloading vs. default parameters in VB.NET?

In VB.NET, which is better to use: function overloading or default parameters?
if the parameters are optional (i.e. the overloads are a subset of the parameters that the full procedure signature accepts) then default or optional parameters would make more sense.
If the overload is allowing a different type for the parameter or is a semantically different parameter that will be interpreted differently by the routine then overloads would make more sense.
Is the code going to be used by other languages? If so, that swings the balance towards overloads while still bearing Hamish's answer in mind. In particular, C# doesn't support optional parameters - yet...
Admittedly this wouldn't actually prevent someone using your code from C#, it just might be a pain for them.
If there are a lot of parameters and they logically represent something, you might want to consider encapsulating them together, in the same way that Process works with ProcessStartInfo. That's particularly nice from C# due to object initializers.
If this is for construction, you might also consider the builder pattern as a variant of this. For instance, in Protocol Buffers I can do something like:
Person jon = new Person.Builder { Name="Jon", Age=32,
Spouse="Holly", Kids=3 }.Build();
which ends up being very readable while still creating a person in one go (in one expression, and without having to mutate the person itself - indeed the message type is immutable; it's only the builder which isn't).
FYI
If you want to add a parameter to a function or method that is called from other assemblies, then:
You can overload by making an additional function with the extra parameter.
Or you can add an optional parameter, BUT: You have to recompile all of the assemblies that call this function, even if they don't need to use the new optional parameter! This is not usually what people expect (expecially those used to how VB6 works). Basically, you can't slip in a new optional parameter to a function and expect it to be totally backwards compatible. Also, as I understand it, if you change what the default value is, you need to rebuild all calling assemblies for the change to work.