Written by

Senior Cloud Architect at InterSystems
MOD
Question Eduard Lebedyuk · Feb 28, 2019

Indirection example does not work

Here's a simple indirection snippet. It fails with <UNDEFINED> error and I'm not sure why.

ClassMethod ind()
{
  kill info

  set active = 1
  set reactive = 2

  for i="active","reactive" {
    set info(i)= @i
  }

  zw info

  break
}

 

I'm getting this exception: <UNDEFINED>zind+5^test.Client.1 *active

Comments

Evgeny Shvarov · Feb 28, 2019

Wow. Confirm that for IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2019.1.0S 

0
Evgeny Shvarov  Feb 28, 2019 to Alexander Koblov

But why? "@" introduces an additional stack, right? And what is above in stack should be visible. Or not?

0
Alexander Koblov · Feb 28, 2019

Quoting doc: "Name indirection, argument indirection, and XECUTE commands that appear within a procedure are not executed within the scope of the procedure."

https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_usercode_indirxecjob

Consider method:

Class Test.test [ Abstract ]
{

ClassMethod ind()
{
	kill info

	set active = 1
	set i="active"
	set @i = "global scope"
	break
}

}

Output:

USER>do ##class(Test.test).ind()
 
 break }
 ^
<BREAK>zind+5^Test.test.1
USER 2d1>w
 
active="global scope"
<Private variables>
active=1
i="active"

Notice private variables and public variables.

0
Alexander Koblov  Mar 1, 2019 to Evgeny Shvarov

No, indirection does not introduce additional stack, as far as I know. It works with variables that are visible in public (global) scope, not in private scope of procedure.

0
Vitaliy Serdtsev · Feb 28, 2019

Working example:

<FONT COLOR="#000080">Class dc.test </FONT><FONT COLOR="#000000">[ </FONT><FONT COLOR="#000080">Abstract </FONT><FONT COLOR="#000000">]
{

</FONT><FONT COLOR="#000080">/// d ##class(dc.test).Test1() ClassMethod </FONT><FONT COLOR="#000000">Test1() [ </FONT><FONT COLOR="#000080">ProcedureBlock </FONT><FONT COLOR="#000000">= 0 ] {   </FONT><FONT COLOR="#0000ff">new </FONT><FONT COLOR="#800000">active</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">reactive</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">info</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">i      </FONT><FONT COLOR="#0000ff">kill </FONT><FONT COLOR="#800000">info

  </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">active </FONT><FONT COLOR="#000000">= 1   </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">reactive </FONT><FONT COLOR="#000000">= 2

  </FONT><FONT COLOR="#0000ff">for </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"active"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"reactive" </FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">info</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">)= @</FONT><FONT COLOR="#800000">i   </FONT><FONT COLOR="#800080">}

  </FONT><FONT COLOR="#0000ff">zw </FONT><FONT COLOR="#800000">info </FONT><FONT COLOR="#000000">}

</FONT><FONT COLOR="#000080">/// d ##class(dc.test).Test2() ClassMethod </FONT><FONT COLOR="#000000">Test2() [ </FONT><FONT COLOR="#000080">PublicList </FONT><FONT COLOR="#000000">= (active, reactive) ] {   </FONT><FONT COLOR="#0000ff">new </FONT><FONT COLOR="#800000">active</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#800000">reactive   </FONT><FONT COLOR="#0000ff">kill </FONT><FONT COLOR="#800000">info

  </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">active </FONT><FONT COLOR="#000000">= 1   </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">reactive </FONT><FONT COLOR="#000000">= 2

  </FONT><FONT COLOR="#0000ff">for </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"active"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"reactive" </FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#800000">info</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">)= @</FONT><FONT COLOR="#800000">i   </FONT><FONT COLOR="#800080">}

  </FONT><FONT COLOR="#0000ff">zw </FONT><FONT COLOR="#800000">info </FONT><FONT COLOR="#000000">}

}</FONT>

0
Julius Kavay · Mar 1, 2019

The correct way is:

ClassMethod ind() [ PublicList = (active,reactive) ]
{
  new active,reactive

  kill info
 // the above command (kill info) is a kind of NOP (no-operation)
 // at the time of entry into a methode there are no variables,
 // except those in the public list (if defined)

  set active = 1
  set reactive = 2

  for i="active","reactive" {
    set info(i)= @i
  }

  zw info

  break
}

If you want to use name-indirection in a procedure block, then

- variables, used by indirection, must be made public (via PublicList)
- and, depending on the situation, should be saved with the NEW command
0