> A few comments:
> MXLOOPS does not apply if the loop is indexed, so one could use an indexed loop with break instead and eliminate the PRESERVE/RESTORE.
Of course but I believe it poor programming practice to alter the value of a loop index variable within the loop so I used the nonindexed version and added SET MXLOOPS as an afterthought and the PRESERVE/RESTORE as a second afterthought ;-) .
+ IF (#i GT 1) #i=#i-1.
+ ELSE.
+ COMPUTE #i=#i+1.
>
> CHAR.LENGTH returns the length of the string in characters (not bytes as with the old LENGTH function) after trimming trailing blanks, so RTRIM is unnecessary.
>
> Most important, the range test
> NOT RANGE(#S,'A','Z','a','z')
> excludes any accented characters and characters such as Japanese, Hebrew, >Russian, etc.....
I suppose one might do a little more work and figure out the RANGE of characters desired and work it out as follows (simply add additional ranges).
*-----Even more elegant solution ;-)-----.
PRESERVE.
SET MXLOOPS=100 /*Whatever the length of the STRING if > 40 */.
STRING name_new(a10).
COMPUTE name_new = name_in.
COMPUTE #i=1.
LOOP.
+ COMPUTE #found= NOT(RANGE(NUMBER(SUBSTR(name_new,#i,1),PIB1) ,97,132,65,90)).
+ IF #found SUBSTR(name_new,#i)=SUBSTR(name_new,#i+1).
+ COMPUTE #i=SUM(#i,-1*(#found AND #i GT 1),NOT(#found)).
END LOOP IF #i GT LENGTH(RTRIM(name_new)).
RESTORE.
LIST.
<SNIP Python evangelism>