What does "SET" do

gg

Registered User.
Local time
Today, 12:01
Joined
Aug 1, 2000
Messages
23
I get a lot of my code from web sites wherein others have already done what I want to do. I use the solution, but am uncomfortable when I don't understand the code.

Often, the word "Set" is used, like Set db = CurrentDb or Set rst = something or set xyz=nothing. I read that "Set" has some relation to "References", but I don't understand what References" means here.

Can someone point me to a site or book that would make things clearer? I use 2003 and A2007.
 
Back in the 80's an old friend of mine named Gerry Weinburg wrote a great book titled "The Psychology of Computer Programming". It was more of a psychology book than a technical book and made some interesting points about what makes a "good" computer language. Sadly, VB/VBA doesn't fit the definition of "good" since it is way too flexible and there are too many ways to do certain things.

So to answer your question, you use Set when you are "setting" a property of an Object. So, db is defined as a DAO.Database OBJECT and rst is defined as a DAO.Recordset OBJECT. But just use = when setting the value of a variable, control, or field. I'm not sure what real difference it would have made if VB/VBA always required Set or never required it. I suspect it goes back to the fact that VB/VBA is a loosely typed language. That means that it doesn't require variable definition. So, if you didn't define your variables, it would be important to differentiate between those variables that were the names of objects and those that weren't.

My first computer language was COBOL and although folks throw sticks at it for being so verbose, it does fit the definition of a "good" language since it is strongly typed (all variables require definition) and there is only one way to do any particular thing. At least that was the case before they introduced Functions into the language. That may no longer be the case.
 
Thanks much. I suspected that it might be superfluous in some of the things that I copied. I have sometimes rewritten some copied code to change things a little and to gain understanding. Never used "Set". Thanks again
 
So to answer your question, you use Set when you are "setting" a property of an Object.

Not quite right but I am sure Pat has just had a glitch of expression. Properties mostly are not Set becauase mostly they are ordinary variables.

Set is used for object variables. It assigns the variable with a pointer to another object. Ordinary variables are just assigned with a value.

It is little known but there are actually two assignment commands in VBA. "Set" for objects and "Let" for ordinary variables. However the use of Let is deprecated because it is understood.

Try this in your code:
Code:
Let x = 1
 
There is one curious anomaly from Set always being used for assigning objects and I have long wondered why.

An ADO Command or Recordset has a Connection property. An ADO Connection is an object yet we can assign that property in VBA without using Set.

A far as I know this is the only case in VBA where an object is assigned without Set. We Set the Recordset Property of a form or listbox so it isn't just about the object being a property.
 
gg.

I don’t know the technical reason for Set to be required for Objects. If we omit the word Set then the compiler raises an error at runtime. So the compiler is aware of the need for the word Set at runtime but does not fix the problem at compile time.

Examples:
No error:-
Dim X As Variant
X = CurrentDb()

No error:-
Dim X As Variant
Set X = CurrentDb()

No error:-
Dim X As Variant
Let X = CurrentDb()

No error:-
Dim X As Object
Set X = CurrentDb()

Error:-
Dim X As Object
X = CurrentDb()

For Variants the word Let is optional but for Objects the word Set is required.
I have not seen a reason for that behaviour.

So if you have never used "Set" then it may be that you have not used Option Explicit and not declared the variables as Objects. If that is what has happened then the default would be Variant and you might just have gotten away with it.

Also, I disagree with the concept of ‘good’ because it seems to have the opposite of ‘bad’. The idea of ‘strongly typed’ as being ‘good’ may be out of context for the purpose of VBA.

What might be seen as ‘good’ from the point of view of a professional programmer may not be seen as ‘good’ from the point of view of the user. If the user is not a professional programmer then ‘loosely typed’ might be seen as ‘good’.

VBA can jump through hoops to try and get something to work for the user. On occasion it might jump through too many hoops and cause trouble. But at least it tries to get things running for the user and I think it does an excellent job of that.

If we view VBA as a computer language for people, not just programmers, I think we can see the context in which it was written. We may also see why VBA has Option Explicit turned off by default.

I think we can also see that it takes a lot more work, on the part of the compiler writters, to make VBA ‘loosely typed’. We can say that a certain amount of work needs to be done. The question is then; who does the work, the compiler writters or the user?

Let’s (pun intended) take a simple case:-
Let A = B
or
A = B

In the first instance the word Let notifies the compiler parser to regard that line as a Let assignment. In essence then the word Let reduces the work of the parser because it reduces the number of possibilities of what that line of code might mean. If the number of possibilities is reduced then the amount of compiler code is reduced and the compile time will decrease. These were once important factors and may still be important factors with full source code Interpreters, if they still exist.

In the second instance the parser does not have the luxury of the word Let. It then has to start and jump through hoops trying to figure out what’s going on with that line of code. It take more compiler code and time to jump through hoops.

‘Let A = B’ then becomes good for the compiler but bad for the user. On the other hand ‘A = B’ becomes good for the user and bad for the compiler.

What has happened here is that the work load has been shifted from the user to the compiler. And there are many instances in VBA where type casting also does the same thing… shift the work load.

It would have taken a lot of work, by the compiler writers, to shift the work load from the user to the compiler. It would not have happened just by chance, it would have been deliberate.

Certainly there are times when it might go astray but I think VBA does a magnificent job for the usage it was intended; to serve the end user not just the professional programmer.

Chris.
 
Pat Hartman; My first computer language was COBOL and although folks throw sticks at it for being so verbose said:
Many years ago when I was in college there was a CPA in my class that also had a COBOL class. I though to myself why doesn't he go out and make big buck with his CPA, this computer stuff is not going anywhere. How wrong I was. He probable the guy how program MS Money, or Quicken.
BTY Pat that was up your way PC
 
I always thought VB is strongely typed. Its got the AS statement, where as loosely typed languages like JavaScript don't (not that I'm aware of). If you don't specify the data type in VB, doesn't it just assume it is a variant? Hmmm...on the other hand, a variant object can still not be defined with a data type. I suppose that does make it a loosely typed. Thanks Pat.
 
I might look at this another way than my esteemed colleagues did.

Let's do a simple one.

Code:
Dim rsX as DAO.Recordset

So the question is, what is rsX? It is an address variable that has been strongly typed to limit its targets to DAO recordsets.

When you use the SET command, you advise Access that the thing in question is going to be an object structure. What you don't see is what really happens. Let's look at it mechanistically.

SET rsX = CurrentDB.OpenRecordset (yada, yada, yada...)

The OpenRecordset method of CurrentDB builds a data structure used to control a DAO Recordset. If you went to the Object Browser and called up DAO library and Recordset object, you could see most of what that structure looks like, even including structure offsets and the data types of the elements of the structure. In this context, rsX is an address pointer that points to the memory-resident data structure built by OpenRecordset.

Think about it. You always use SET object-variable = class.method - and it is the method that gives you the object structure, but the object-variable merely is the pointer to what you created. In essence, the method creates the block of memory for your object, initializes it, and returns the address to the object-variable via SET. SET warns Access that you think the variable is an object variable rather than a primitive variable (LONG, DOUBLE, etc.)

This is where two basic concepts come into play. First, when you open a structure, you close it. Like.... rsX.Close

But then, after you close it, you need to tell Access that you are done with the data structure - so.... SET rsX = Nothing

If you do these in the wrong order, or if you don't bother to close in the first place, you find that you run out of either or both memory and resources very quickly as your detritus accumulates.

That SET xxx = Nothing command triggers the object "destructor" that releases the data structure created in memory to actually control the object you were using. If you closed it first, you are OK. If you didn't, you left the object "dangling."

So, now to more directly answer your question:

Any non-primitive data type that supports use of "SET" such as DAO.Recordset or Access.ComboBox or whatever ya got is actually a pointer to a memory data structure.

The pointer is in the form of something called a descriptor, which includes the real address of the real controlling memory-resident data structure along with information needed to present the data type of the object and any associated elements.

The object's data structure contains the public and private slots that are the public and private properties of the object so represented. Other elements associated with the object include code references to methods associated with the object.

With regards to "references" - the word relates to referencing or dereferencing pointer variables.

Hope that helps you to see what really happens back there in the weeds.
 
Doc.

Please try to prove any of that with an uploaded posted coded solution which can be substantiated by others.

Chris.
 
ISET warns Access that you think the variable is an object variable rather than a primitive variable (LONG, DOUBLE, etc.)

I am curious though why VBA needs the Set when the right hand side of the equation is obviously an object.

It will second guess plenty of other things left unspecified. (For example it annoyingly converts out of scope dd/mm/yy dates to mm/dd/yy or yy/mm/dd automaticlly if they will fit.)

Why do they make us type Set when the system could obviously work it out for itself?
 
Also does anyone have any idea on the anomaly I outlines in Post 5?
 
ChrisO, that "coded solution" might be difficult. I'll have to try to find where I read about that. If I posted some sort of link, would you take that? (Assuming I can find it again, of course.)
 
i guess it just comes down to syntax

as already pointed out , with a variable the syntax is

let somevar = whatever, but the let is optional

with an object the syntax is

set someobj = whatever

and the the set is not optional. no doubt if the compiler is clever enough to recognise that set is missing, it could add the set itself. maybe the compiler designers thought it was less ambiguous to insist on the keyword set being present.

by the same token, you cannot instantiate multiple variables

dim a,b,c as long does not instantiate a, b and c as longs

you cannot assign a variable in a single statement

dim a as long = 4

and there is no shorthand for increment such as

x+=1 or inc(x) or even x = succ(x)

you have to say x = x+1, even though no doubt the compiler would do the same thing with each of these variations.

just syntax peculiar to vb and vba
 
I think another (good) reason for requiring SET is that it forces disambiguation. Consider the following (lots of looseness in the meta language here ;-):

Code:
Class MyStuff
Public Name as string
End Class

YourOtherStuff=MyStuff
MyOtherStuff=YourOtherStuff
(Declarations deliberately omitted to make it more like 'real-user' code


Does this mean that:
a) I want MyOtherStuff to be an instantiation of the Class MyStuff?
b) I want My OtherStuff to be the value of the Name property from YourOtherStuff?

What do I want YourOtherStuff to be?

Requiring the use of SET allows/requires the programmer to make their intention a little more obvious to both the compiler and those hapless souls who have to maintain the code some months later.

Tony
 
Doc.

Yes, post a link if you like but there is already something on this site which might help:-

http://www.access-programmers.co.uk/forums/showthread.php?t=225415

There is even a demo for people to test. And on my SkyDrive site there are plenty more demos which use pointers to other Objects, all the OpenArgs demos.

----------

But you were also talking about the need to close recordsets and set them to Nothing. While under some circumstances that might be necessary it generally isn’t.

We can all post links to people who say it is necessary and some of us can post links to people who say it isn’t necessary. So what I was wondering about is if you could prove that it is necessary via a posted demonstration database.

----------

But about the use of the word Set. Your post restates that it is required. Well, it is required sometimes but not all. So the question was; why does the compiler require it sometimes but not all?

Chris.
 
Tony.

As far as I can see, with Option Explicit turned off, all variables would be Variants and there is nothing to set any of them to Class MyStuff. Hence, I don’t think that it would be possible to get at the variable Name in Class MyStuff.

Chris.
 
I agree that it wouldn't be possible - I was trying to show that rather than the 'obvious' intention of the programmer, there are other possibilities. (Hypothetically) requiring SET forces the programmer to make that clear. My original code (from which I deleted as much as possible) did indeed have the declaration of the Class instance (YourOtherStuff). However, I agree with you, and am intrigued by what would constitute the 'proof' you'd like to see.

Tony

PS You're up early!
 
Well, specifically the proof of this from post #9:-

>>This is where two basic concepts come into play. First, when you open a structure, you close it. Like.... rsX.Close

But then, after you close it, you need to tell Access that you are done with the data structure - so.... SET rsX = Nothing

If you do these in the wrong order, or if you don't bother to close in the first place, you find that you run out of either or both memory and resources very quickly as your detritus accumulates.

That SET xxx = Nothing command triggers the object "destructor" that releases the data structure created in memory to actually control the object you were using. If you closed it first, you are OK. If you didn't, you left the object "dangling."<<



It’s been going on for years but people keep saying it without giving proof. They will show links to other people who say the same thing but they too offer no proof.

What concerns me is that people are just repeating what they read but don’t actually do the work to try and prove it. I think it has the trickle down effect that all that is required is to read something and it is automatically correct.

----------

>>PS You're up early!<<
Yep, but the Sun is up now so I should be okay until my kindy nap after lunch. :D

Chris.
 
ChrisO

First, I cannot find that link again. It has been a while. So I'm going to back down on that one and say that what I described is conceptually analogous to what really happens.

However, my comments about it being necessary to close objects and to set the object pointers to nothing - I stand by that because of threads from this very forum in which the symptoms were running out of resources (for not closing what you opened) and running out of virtual memory (for not setting closed objects to nothing) - for which the posted and accepted solution was to close what you open and put away things (the memory) that you took out (via NEW or CREATEOBJECT etc). I will not stand down from that assertion of necessity unless you can point to something that says you NO LONGER need to do that because of relatively recent changes to Access behavior.
 

Users who are viewing this thread

Back
Top Bottom