wave assignment and multiple return statements

I wonder if there is some way to assign the elements of two waves simultaneously with one function, something like the following (silly) MWE:

function [variable out1, variable out2] sub(variable in)
    out1 = in/2
    out2 = in*2
    return [out1, out2]
end

function main()
    make/O/N=(2,2) W_in=p*q+1, W_out1, W_out1
    [W_out1[][], W_out2[][]] = sub(W_in[p][q])
end

Main() doesn't compile. The alternative is to do an explicit loop in Main(), or to split sub() into to two separate functions. Neither seems attractive. The actual use-case here is to split a string expression to return two values.

 

 

In case the two returns is not possible, with what you want, would it work to put the return the two strings in a 1x2 text wave function?

W_out1[][] = splittextwave(w_in[p])[q]

function [Wave out1, Wave out2] sub(Wave in)
    out1 = in/2
    out2 = in*2
    return [out1, out2]
end

function main()
    make/O/N=(2,2) W_in=p*q+1, W_out1, W_out2
    [W_out1, W_out2] = sub(W_in)
end

I haven't thought about any performance consequences of this, but if you change to inputting and returning waves instead of variables, it will compile and I think do what you want. 

JJ, I had considered something like that, to return a one point, two layer wave, but I didn't get this to work.

Ben, the wave approach will not work in my case, which is given below. I want to extract data and error values from string expressions in which the error is reported in terms of last significant digit. The strings are copied & pasted into a 2D text wave. The main function works, I just hoped I could get rid of the nested loops, mainly for aesthetic reasons.

function GetDataAndError(wave/T txt2d)
    variable nRows=DimSize(txt2d,0)
    variable nCols=DimSize(txt2d,1)
   
    Make/D/O/N=(nRows, nCols), W_values, W_errors
    CopyDimlabels txt2D, W_values, W_errors
   
    variable i, k, value, error
    for(i=0; i<nRows; i++)
        for(k=0; k<nCols; k++)
           
            [value, error] = SplitExpression(txt2d[i][k])
            W_values[i][k] = value
            W_errors[i][k] = error
           
        endfor
    endfor
end

function [variable value, variable error] SplitExpression(string str)
       
    // split the input string, such as e.g. "3.25(4)", into two numeric parts
    // ignore any other non-numeric characters that may be in the string, as in e.g. "3.25 (4)#"
    string sValue, sError
    splitstring/E=".*?([0-9.]+).*?\(\s*(\d+)\s*\).*" str, sValue, sError
   
    // does value has a decimal point, if yes how many digits behind it?   
    variable PosDecimalPoint = strsearch(sValue, ".", 0)
    variable nDigits = PosDecimalPoint == -1 ? NaN : (strlen(sValue) - PosDecimalPoint -1)
    value = str2Num(sValue)
   
    if (PosDecimalPoint == -1)
        // if value has no decimal point, error is absolut
        error = str2num(sError)
    else
        // if yes, scale error according to digits after decimal of data value
        error = str2num(sError)/10^(nDigits)
    endif
   
    return [value, error]
end


// sample data:
Make/O/T txt = {{"23652 (23)"," 0.125(3)"}, {"125.5(9)","2.3(11)a)"}}

 

ok, I think I do it like this, but thanks for the comments!

function GetDataAndError(wave/T txt2d)
    variable nRows=DimSize(txt2d,0)
    variable nCols=DimSize(txt2d,1)
   
    Make/D/O/N=(nRows, nCols), W_values, W_errors
    CopyDimlabels txt2D, W_values, W_errors
   
    W_values = SplitExpression(txt2D[p][q], 0)
    W_errors = SplitExpression(txt2D[p][q], 1)
end

function SplitExpression(string str, int mode)
    // split the input string, such as e.g. "3.25(4)", into two numeric parts
    // ignore any other non-numeric characters that may be in the string, as in e.g. "3.25 (4)#"
    variable Value, Error
    string sValue, sError
    splitstring/E=".*?([0-9.]+).*?\(\s*(\d+)\s*\).*" str, sValue, sError
   
    // does value has a decimal point, if yes how many digits behind it?   
    variable PosDecimalPoint = strsearch(sValue, ".", 0)
    variable nDigits = PosDecimalPoint == -1 ? NaN : (strlen(sValue) - PosDecimalPoint -1)
    value = str2Num(sValue)
   
    if (PosDecimalPoint == -1)
        // if value has no decimal point, error is absolut
        error = str2num(sError)
    else
        // if yes, scale error according to digits after decimal of data value
        error = str2num(sError)/10^(nDigits)
    endif
   
    variable out=nan
    out = (mode ? error : value)
   
    return out
end