0

How does nested scope in IML modules work?

I am trying to create a module for optimization. It contains other modules. The inner modules need access to the local scope outer module, because of how the optimization functions in IML work.

Here is what I would LIKE to work.

start mvo_cvar(m,s,ub,lb,st);

    start C_VAR(x) global(s, st);
        r = st - x*s*x`;
        return (r);
    finish C_VAR;

    start F_RETURN(x) global(m);
        r = m`*x`;
        return (r);
    finish F_RETURN;

    nvar = nrow(s);
    ones = J(1,nvar,1);
    ubound = ones*ub;
    lbound = ones*lb;
    con = (lbound || {. .}) //
          (ubound|| {. .}) //
          (ones || {0 1}); 

    optn = j(1,11,0);
    optn[1] = 1;
    optn[2] = 0;
    optn[10] = 1;
    optn[11] = 1;
    x = J(1,nvar,0);
    x[1]=1;

    call nlpqn(rc,results,"F_RETURN",x,optn,con) nlc="C_VAR";

    return (results);
finish mvo_cvar;

However, the F_RETURN and C_VAR modules cannot find the s, st, or m matrices. I get

ERROR: (execution) Matrix has not been set to a value.

 operation : ` at line 6948 column 14
 operands  : m

m      0 row       0 col     (type ?, size 0)


 statement : ASSIGN at line 6948 column 9
 traceback : module F_RETURN at line 6948 column 9
             module MVO_CVAR at line 6940 column 1

for example.

Is there a way to reference the local scope of the outer module?

DomPazz
  • 12,415
  • 17
  • 23

1 Answers1

2

There is no such thing as a local module or a nested module. All modules are known globally. See the doc at http://support.sas.com/documentation/cdl/en/imlug/66112/HTML/default/viewer.htm#imlug_programstatements_sect023.htm

The variables m, s, and st are local to the mvo_cvar module. To make them accessible to the other modules, they all need to have the same global name. I like to prefix my global variables with "g_". So the code might look like this:

start mvo_cvar(m,s,ub,lb,st) global(g_m, g_s, g_st);
   g_m = m; g_s=s; g_st = st;  /* assign shared global vars */

   nvar = nrow(s);
   ones = J(1,nvar,1);
...
   call nlpqn(rc,results,"F_RETURN",x,optn,con) nlc="C_VAR";

   return (results);
finish mvo_cvar;

start C_VAR(x) global(g_s, g_st);
     r = g_st - x*g_s*x`;
     return (r);
finish C_VAR;

start F_RETURN(x) global(g_m);
    r = g_m`*x`;
    return (r);
finish F_RETURN;
Rick
  • 1,210
  • 6
  • 11
  • thanks. Not exactly the answer I was hoping for. I will have to do this with macros as the names of those global variables change and are not known prior to run time. – DomPazz Mar 01 '14 at 21:18
  • Surely you know the names of the variables when you are going to use them. JUst define a module called SetGlobal() that assigns the global variables from whatever local variables you want to use. – Rick Mar 10 '14 at 15:26