Richard Gaskin ambassador at
Mon Dec 8 12:49:06 EST 2008

dunbarx wrote:

 > This is the sort of thing I wrote, too. HC code would be similar
 > ; I'll take your word for the speed.
 > I was wondering if there was something snazzy in Rev (that was not
 > in HC) that did not require running through the whole body of text,
 > in other words, directly, like the new "replaceText" function that
 > is a one-line substitute for "fullReplace". Very Rinaldi-like.

While the algorithms you would use in Rev and HC may appear similar in 
some respects, don't underestimate the power of "repeat for each".  This 
form of repeat was not available in HC, and is at least one or two 
orders of magnitude faster than "repeat with i = 1 to the number of 

The reason for the incredible speed difference between the two is that 
"repeat for each" makes the assumption (indeed requires) that the text 
being parsed will not change during the repeat, while "repeat with..." 
cannot know this in advance.

So when running "repeat with i = 1 to the number of lines", each time 
through the loop it needs to count the lines from 1 to i, and then you 
can say "get line i" and that will once again count from 1 to i to 
obtain the line.  Lots of redundant overhead, but necessary in a form in 
which the text being parsed might be changing in each iteration.

In contrast, "repeat for each" counts and parses chunks as it goes, 
doing two operations at once (going to the line and parsing it out into 
the iteration variable) and never counting its way through the text 
within a given iteration, since it knows where it left off last time.

To make things even faster, a few years ago Scott Raney optimized the 
"put <text> after <othertext>" operation, with a dramatic speed boost. 
In most xTalks, modifying a chunk means a fair amount of overhead with 
multiple copies of the destination text to accommodate the change.  With 
"put...after..." the underlying pointer manipulation has been 
significantly optimized specifically for that append operation, so it's 
much faster in Rev than any other xTalk I've seen (and I've worked with 
most of them, including HC, SC, Plus, OMO, Gain Momentum, and ToolBook).

These two constructs, "repeat for each..." and "put...after...", combine 
well for most common parsing tasks, making extraordinarily efficient 
work of slicing through even large blocks of data and combining your 
found results into a new variable.

And then there are arrays, variables with slots for each element which 
can be referenced by the element name.

In HC, multi-part data could be stored in a given variable only by 
carefully minding your chunks, e.g.:

   put tData into line 4000 of tMyVar

This means that you not only need to make sure that tData never contains 
any character you're using to delimit your chunks, but also that 
accessing it will require the overhead of counting chunks to access thte 
one you want:

   get line 4000 of tMyVar

Arrays use an internal hashing scheme so that element names are 
associated with the location of the element's data in a much more 
efficient way.  To store data you just use:

   put tData into tMyVar[4000]

And to get it:

   get tMyVar[4000]

But the real advantage of arrays is that you're not limited to indexing 
them by number; you can use names instead.

For example, if you wanted to store info about a person in a chunk, you 
might use:

   put tName into line 1 of tMyVar
   put tPhone into line 2 of tMyVar
   put tAddress into line 3 of tMyVar

Works well enough - as long as you remember which line has which data. 
So this requires adding comments in your code to remind you later on how 
the data is structured.

With arrays this is much simpler:

   put tName into tMyVar["name"]
   put tPhone into tMyVar["phone"]
   put tAddress into tMyVar["address"]

If you need to display all of the elements of an array, you can combine 
them with the "combine" command:

   combine tMyVar with return and tab
   put tMyVar into fld 1

You can also convert a list into an array with the split command:

   put fld 1 into tMyVar
   split tMyVar with return and tab

In summary, there's a bit of a learning curve with picking up the most 
efficient ways to do things in Rev.  But it's time well spent, because 
in most cases you'll be free to munge data however you want right in the 
language, liberated from dependencies on externals written in C.

And given the overhead of the XCMD interface, you might even find that 
some of these operations actually run faster in Transcript than in the 
externals you used to use.

  Richard Gaskin
  Fourth World
  Revolution training and consulting:
  Webzine for Rev developers:

More information about the Use-livecode mailing list