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
Wow. Confirm that for IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2019.1.0S
But why? "@" introduces an additional stack, right? And what is above in stack should be visible. Or not?
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.
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.
Working example:
Class dc.test [ Abstract ]
{
/// d ##class(dc.test).Test1()
ClassMethod Test1() [ ProcedureBlock = 0 ]
{
new active,reactive,info,i
kill info
set active = 1
set reactive = 2
for i="active","reactive" {
set info(i)= @i
}
zw info
}
/// d ##class(dc.test).Test2()
ClassMethod Test2() [ PublicList = (active, reactive) ]
{
new active, reactive
kill info
set active = 1
set reactive = 2
for i="active","reactive" {
set info(i)= @i
}
zw info
}
}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