Strange behavior when using $get

Primary tabs

Looks like the $get is actually trying to use the property getter instead of evaluating the GetAt as a method first.
Should this be considered a bug?


Based on the documentation, it seems like this may be expected since $GET is expecting a variable, not a value returned from a method call. The main purpose is to protect against undefined references which a method call should never return since an empty string is different than undefined. Since the documentation mentions it accepts multidimensional object properties, it seems like it is assuming this is what the passed in reference is.

Documentation on expected values here.

To add a little more to this, I would say it is basically the same as using SET vs WRITE:

SAMPLES>set person=##class(Sample.Person).%OpenId(1)
SAMPLES>w person.CurrentAge($h-1000)
SAMPLES>set person.CurrentAge($h-1000)=1
SET person.CurrentAge($H-1000)=1
<PROPERTY DOES NOT EXIST> *CurrentAge,Sample.Person

Interesting question and one I hadn't considered.

If it helps, you need to think about  the type of data you are referencing as they work on different data structures:

  • $GET works on variables, arrays and global references but does not refer to object data. 
  • GetAt is a specific object function.

I cannot see any need to combine both in the same instruction, both return null if the item does not exist.

Hope this helps.

I cannot see any need to combine both in the same instruction, both return null if the item does not exist.

I wanted to avoid writing more than one line or having to get the value twice, e.g.

set value = array.GetAt("key")
if value = "" set value = "default"

I actually did it that way. But I could do it this way too:

set value = $select(array.GetAt("key") '= "" array.GetAt("key"), 1: "default")

But now I would be calling it twice which seemed like code smell for me.

I think you're overthinking this, either method is fine. If you are passing a key value and not searching each time then this is nothing to worry about. Sometimes doing something in 2 steps can be easier to read than a compound instruction.

You can do this very simply ($get(array.Data("key"),"default")), for example:

set array=##class(%ArrayOfDataTypes).%New()

write $get(array.Data("oops"),"what?!"),!

do array.SetAt("blabla","oops")
write $get(array.Data("oops"),"what?!"),!

I can't believe I forgot about that Data property.

I just won't mark your reply as the answer because I didn't specified that I wanted to know how to do that. My bad... but thanks anyway.