String Optimization: More detail

In the prior post (String Optimization. How does it work?) I described an optimization of how the Assignment statement calls the expression evaluator for string concatenation statements.  There are certain limitations with this optimization. For example, if you use a Public variable and call a routine that can modify the variable, you might get unexpected results.

MyPublicVar = MyPublicVar + MyRoutine(MyPublicVar)

Another example is passing the variable by reference:

MyVar = MyVar + MyRoutine(@MyVar)

This kind code is very hard to read and does not seem deterministic. Also, in C++, you can write identical constructs, which have undefined meaning.

A legitimate case is recursion. Over the last 8 years, we’ve had very few reports of customers running into this problem.

Try running the code below, and you’ll get 2 different results.

Why?

The optimization modifies the compiled code to evaluate the addend:

x = x + <something recursive>

is modified to be

x = “” + <something recursive>

and then the result is evaluated.

The recursive call will see only the modified code, which doesn’t do the append of the addend.

There are several easy workarounds:

y=<something recursive>

x = x + y

or

x = “” + x + <something recursive>

This has been fixed for the next release.

ndepth=3

cResult=recur(ndepth,.t.)

?"Opt=.t. Len="+TRANSFORM(LEN(cResult)),"Result=",cResult

?"Now doing valid res"

cResult=recur(ndepth,.f.)

?"Opt=.f. Len="+TRANSFORM(LEN(cResult)),"Result=",cResult

PROCEDURE recur(nLev,fOpt) as String

LOCAL cstr,i

IF nlev=1

RETURN "1"

ENDIF

cstr=REPLICATE("_",110)

IF fOpt

cstr=   cstr+TRANSFORM(nLev)+"  "+recur(nLev-1,fOpt)

ELSE

cstr=""+cstr+TRANSFORM(nLev)+"  "+recur(nLev-1,fOpt)

ENDIF

?nlev,"L="+TRANSFORM(LEN(cstr)),cstr

RETURN cstr

Tags