WAVE/Z vs /ZZ

I've been playing around with the new WAVE/ZZ flag in IP9.

Example code:

Function/WAVE GetNullWave()
    return $""
End

Function MakeWave()
    Make/O data
End

Function Dostuff()
    MakeWave()

    WAVE/Z data = I_DONT_EXIST
    print 1, WaveExists(data)
    WaveClear data
   
    WAVE/ZZ data = I_DONT_EXIST
    print 2, WaveExists(data)
    WAveClear data 

    WAVE/Z data
    print 3, WaveExists(data)
    WaveClear data
   
    WAVE/ZZ data
    print 4, WaveExists(data)
    WAveClear data 

    WAVE/Z data = GetNullWave()
    print 5, WaveExists(data)
    WaveClear data
   
    WAVE/ZZ data = GetNullWave()
    print 6, WaveExists(data)
    WAveClear data
End

This gives:

•dostuff()
  1  0
  2  0
  3  1
  4  0
  5  0
  6  0


So I would say that /ZZ is always better than /Z as picking up global waves is suprising. Is that correct?

So I would say that /ZZ is always better than /Z as picking up global waves is suprising. Is that correct?

The documentation for WAVE makes it very clear that if you provide LocalName without =pathToWave Igor will "[make] the connection between the local name and the actual wave". If you consider the documented behavior to be surprising then using /ZZ might be useful but it will require more verbose WAVE statements than necessary in some situations (you might even consider that to be an advantage).

Here is an example in which you would not want to use /ZZ:

Function foo()
    Make/O/FREE ddd=enoise(5)
    WaveStats/Q/W ddd
    WAVE/ZZ M_WaveStats
    print M_WaveStats[0]
End

If you insist on using /ZZ, you can easily rewrite that like this:

Function foo()
    Make/O/FREE ddd=enoise(5)
    WaveStats/Q/W ddd
    WAVE/ZZ results = M_WaveStats
    print results[0]
End

the later is slightly more verbose and might be considered more difficult to read.

The intent when adding the /ZZ flag was to make it possible to avoid the potentially expensive cost of runtime lookup by name in code that is very performance sensitive.

Good, point. So I have to use /Z when I want to pickup global waves as in:

Function foo()
    Make/O/FREE ddd=enoise(5)
    WaveStats/Q/W ddd
    WAVE/Z M_WaveStats
   
    if(!WaveExists(M_WaveStats))
        print "WaveStats error"
        return NaN
    endif
   
    print M_WaveStats[0]
End

Not really a suprise re-reading the documentation.

Thanks!

The intent when adding the /ZZ flag was to make it possible to avoid the potentially expensive cost of runtime lookup by name in code that is very performance sensitive.

In Igor 8 and later, the cost to look up a wave in the current data folder is not that large, especially given the inherent overhead of running user code. But there is some cost. 

So I have to use /Z when I want to pickup global waves as in:

Well, in your example, you can be reasonably confident that WaveStats/W will create the wave, so the /Z isn't strictly necessary as the lookup is very unlikely to fail. And in fact, it would be sufficiently surprising that you might want the error that lets you know about it. If you use /Z, though, it is expected that you will follow up with a call to WaveExists() since the /Z flag indicates that there is a reasonable chance that the lookup will fail.