1

I have an IDL function that takes in up to 4 data variables: data1, data2, data3 and data4. I want to be able to access the level=-1 scope of these variables in a loop using a string construct for the data variable name, so I can document the name of the original data that was passed to the function in an efficient manner.

Here's a simplified version of the function, showing only pertinent parts.

Function funcData, dat1, dat2, dat3, dat4,
  n=1 
  txt = "Data " 
  ;Check that data variable n was passed.                                      
  WHILE N_ELEMENTS(scope_varfetch("dat"+strtrim(n+1,1), level=0, /enter)) $
      NE 0 DO BEGIN
    dat = scope_varfetch("dat"+strtrim(n,1), level=0, /enter)    ; get data
    txt=txt + scope_varname("dat"+ strtrim(n,1), level=-1) +", " ; data names  
    n+=1                                                         ; update n 
  ENDWHILE
END

The problem is that scope_varfetch handles the concatenated string construct "dat"+strtrim(n,1) and returns the appropriate data set, but scope_varname does not, returning a blank.

Does anyone know why this is happening? Is there another way I can do this (short of brute force, case format)?

I have tried to search for an answer on-line, but have not been able to find anything about using string constructs in the IDL scope functions.

veda905
  • 782
  • 2
  • 12
  • 32
  • I suggest you try an alternate approach to solve your problem. Using `SCOPE_VARFETCH` and `SCOPE_VARNAME` is seldom the easiest way to do things. Maybe try passing a hash into your routine with the name and value of your variables? – mgalloy May 03 '17 at 00:59
  • Thanks for the suggestion, @mgalloy. But I am not sure that passing a hash would be any simpler than passing an array with the variable names, especially since my hash keys would just be `1,2,3,4`. In any case, creating and passing either a hash or an array seems overly complicated and inelegant for the simple problem here. If I am missing something, I would welcome more input. – I Antonenko May 04 '17 at 17:02
  • Have you tried formatting your string using `string()` with the `format` keyword? `strtrim()` with the `1` flag only removes leading spaces. I know you did the same for `scope_varfetch()` but sometimes IDL is funny like that. – sappjw May 04 '17 at 23:21
  • Thanks for the suggestion @sappjw, but I am not sure how `string()` with `format` would help here. When I check the string length of my string-trimmed number with `strlen(strtrim(i,1))`, I get 1, so there is no extra padding at the end of the string. Also, I can't seem to get something like `print, string(i,format="%s")` to even work. I have tried multiple combinations of braces, parenthesis, quotes, etc., using both Fortran and C style format codes, but I don't get useful results. Any suggestions on what you had in mind would be greatly appreciated. – I Antonenko May 09 '17 at 16:39
  • @IAntonenko I was thing something like `string(i, format='(i-0)')`, but you've already checked the padding. – sappjw May 10 '17 at 11:28
  • @sappjw, thanks for the formatting tip. Even if it doesn't solve my problem, it's new information and that is always appreciated. – I Antonenko May 11 '17 at 15:47

2 Answers2

1

A Facebook contact provided this solution:

result=execute('sv=scope_varname(dat'+ strtrim(n,1)+', level=-1)')   
txt=txt + sv + ", "  

Works perfectly.

  • This doesn't work in a VM so it is less than ideal...but it works – sappjw May 04 '17 at 23:23
  • Unfortunately, it also doesn't work when the scoped variable is a structure field, so I'm still looking for a universal solution. – I Antonenko May 09 '17 at 16:42
  • That last requirement may be tough to do. [My answer](http://stackoverflow.com/a/43891451/610375) does not address this, so you may have to do some additional testing. – sappjw May 10 '17 at 11:42
  • Actually, `scope_varname` doesn't seem to work at all when the scoped variable is a structure field, regardless of whether the variable name is a string construct or just a plain string (though `scope_varfetch` does). So, I may need to do something else in such cases. – I Antonenko May 11 '17 at 15:57
1

scope_varname expects a variable as its parameter, so you need an extra call to scope_varfetch when using it:

txt=txt + scope_varname((scope_varfetch("dat"+ strtrim(n,1))), level=-1) +", " ; data names
sappjw
  • 373
  • 1
  • 14
  • Thanks @sappjw. This works with the same caveats as the other solution. Can I ask why extra parentheses around the `scope_varfetch` call would avoid creating an extra copy of the data? I tried `tmp=scope_varfetch(data)` and `tmp=(scope_varfetch(data))` and in both cases the entire data set was assigned to `tmp`, so I'm not clear on how the parentheses would work. – I Antonenko May 11 '17 at 16:07