Article
· Dec 28, 2025 1m read

#DIM vs SET - Objectscript

SET assigns value to the variable at RUNTIME.

#DIM declare the variable and it's Data Type at COMPILE TIME.


SET #DIM
Makes the variables Dynamic. Improves Readability.
No Data Type Declaration. Enables IDE auto-completion.
Runtime Useful for Object references.

#DIM name As %String
Set name = "Micheal Scott"
#DIM age As %Numeric
Set age = 36
#DIM employer As App.Employer               ; compile time
Set employer = ##class(App.Employer).%New() ; runtime 

 

SET or #DIM? Your design, your rules.

Discussion (13)4
Log in or sign up to continue

I tend to break up my usage between SET when an object is being created within the class, and using #DIM when working with responses from another ClassMethod. For example:

Set SearchParams = ##Class(DM.EmployeeSearch).%New()
Set SearchParams.EmployeeID = 042114040518
#DIM Employee As DM.Employee
Set tSC = ##class(DM.Employee).EmployeeSearch(SearchParams,.Employee)
If '$ISERROR(tSC){
    $$$TRACE(Employee.Name) //Should return "Jim Halpert"
}

This is really helpful to know. I think I have seen it not work like this in the past and picked it up as a habit, but can't say for sure.

To test this for myself, I have written out above pseudocode into real classes and found that the code completion doesn't kick in when attempting in the $$$TRACE, but does when attempting outside of the macro params:

   
I'll try get this logged via github later today assuming this isn't intended behaviour for the Language Server.

EDIT:

Logged here and I realise that my habit of using #Dim for Intellisense 100% comes from my historic use of Studio.

I'm still not a big fan of #dim. It was useful for code completion in Studio. But it hasn't been necessary for code completion in VS Code for a while. Check this post from last year for more details. Perhaps code clarity is the only remaining reason to use it, to help developers who are used to declaring variables in other languages (like Python type hints).

My main reason for discouraging its use is that it makes it seem like it's necessary to declare variables in ObjectScript, which it isn't. There is no variable declaration in ObjectScript, as you can read at the top of the documentation that @Vachan C Rannore cited. He is not the first developer to write something like this: "#DIM declares the variable and it's Data Type at COMPILE TIME." #dim causes confusion for developers.

As @Evgeny Shvarov says, the compiler skips #dim. But as the examples prove (thanks @Vitaliy Serdtsev), the compiler doesn't skip #dim that includes variable assignment, which it helpfully changes into Set statements. More confusion...

The first example looks a little weird because it uses #dim but doesn't include "as datatype".

#dim a,b,##class(Sample.Person).%New()

Why use #dim syntax that supposedly declares something, and then avoid declaring anything? Confusing. The compiler just changes it into this standard Set syntax. Just use the Set syntax in the first place.

set (a,b,c) ##class(Sample.Person).%New()

For the second example, I admit that it's slightly useful to get 3 different objects with a single statement. I never knew about this. The compiler turns this #dim statement into 3 separate Set statements, so it does save some typing.

set a ##class(Sample.Person).%New(), b ##class(Sample.Person).%New(), c ##class(Sample.Person).%New()

Some developers will like this "insider trick." But I think using an obscure non-command instead of just calling %New() 3 times for this one special case is not worth it. Just use Set statements.

By the way, what do you think this statement does? Note the %OpenId(20) at the end instead of %New(). 

#dim a,b,As Sample.Person ##class(Sample.Person).%OpenId(20)

Confusing. The addition of "As Sample.Person" has no effect when used with %OpenId(). How about this statement?

#dim a,b,As Sample.Company ##class(Sample.Person).%New()

Do you get 3 companies or 3 persons? Does it try to "cast" persons as companies? Do you get an error at compile time or run time? Would it work if Sample.Company extends Sample.Person? More confusion... The addition of "As Sample.Company" has the same effect as "As Sample.Person" or "As Bla.bla" would. No casting, no error, inheritance doesn't matter. You just get 3 new persons.

By the way, what do you think this statement does? Note the %OpenId(20) at the end instead of %New(). 

#dim a,b,As Sample.Person ##class(Sample.Person).%OpenId(20)

Confusing. How about this statement?

#dim a,b,As Sample.Company ##class(Sample.Person).%New()

Do you get 3 companies or 3 persons? Does it try to "cast" persons as companies? Do you get an error at compile time or run time? Would it work if Sample.Company extends Sample.Person? More confusion...

There is no confusion.

Here's another example where the class may not even exist and yet the code compiles without errors and according to the documentation.

test.MAC

#dim a,b,As %Boolean ##class(bla.bla).%OpenId(20)
#dim a,b,As bla.bla.bla123 ##class(bla.bla).%OpenId(20)

--> test.INT

Set (a,b,c)=##class(bla.bla).%OpenId(20)
Set a=##class(bla.bla).%OpenId(20),b=##class(bla.bla).%OpenId(20),c=##class(bla.bla).%OpenId(20)

The only thing is that in this case Studio Assist will not work.

A good thing to know is, that there isn't actually a thing as 'during compile time' in ObjectScript.
Compiling a class is a three step process:
- transform the class definition (including any superclasses) to a (set of) .MAC files
- the Macro 'compiler' resolves the $$$macros and #xxx statements and create a (set of) .INT routines
- which in turn are pre-compiled into byte code .OBJ routines

#dim a,b,= ##class(Data.Product).%New()
#dim x,y,as Data.Product = ##class(Data.Product).%New()
in a .MAC routine becomes:

Set (a,b,c)=##class(Data.Product).%New()
Set x=##class(Data.Product).%New(),y=##class(Data.Product).%New(),x=##class(Data.Product).%New()
in a .INT routine