This post discusses important stylistic improvements that *must* be made
for me to accept Vitalije's new code. In fact, I have already made these
improvements. They greatly clarify the code.
These improvements will have absolutely now effect on performance. Rather,
they will make the code more robust and easier to understand.
I am open to debate on this subject, but there is virtually no chance of
changing my mind.
At present, parts of Vitalije's new code can (will!) break if the order of
child nodes changes. This must not be allowed to happen! Not only is it
unacceptably bad Leonine style, it needlessly obscures the scope of vars.
*Edicts*
Edict 1. @others may only be used to add inner functions/classes. @others *must
not ever* be used to include bare code. Bare code included by @others is,
in effect, an implicit section reference. Such references are *banned*.
In the unlikely event that section references would be essential to
speeding up code, *explicit* section references must be used. Having said
that, it is highly unlikely that section references are necessary in
Vitalije's code.
Edict 2. The functions included via @others must work regardless of their
order.
As I'll illustrate below, in some cases new args to the functions may have
to be added. Adding such args is *infinitely* preferable to
order-dependent functions.
*Example1*
I have rewritten the function in miniTkLeo.py as follows:
def main(fname):
tstart = time.monotonic()
@others
ltm, ltmbytes = load_xml(fname)
app = create_app()
f1, f2, bodyW, canvW, logW = create_gui(app)
start_thread(app, f1, f2, ltmbytes)
return bunch(
ltm=ltm,
app=app,
tree=canvW,
body=bodyW,
log=logW,
q=queue.Queue(1),
topIndex=IntVar())
The extra args ensure that the helper functions may be defined in any
order. They also make clear what the data flow is. This is no small thing
while studying code.
*Example 2*
The all_lines function in leoDataModel.py is now:
def all_lines(gnx, ind):
mNI = NI[0]
h, b, ps, chn, sz = ltm.attrs[gnx]
lines = b.splitlines(True)
for i, line in enumerate(lines):
if line.startswith('@setindent '):
ind = int(line[11:].strip())
continue
if line.startswith(('@killcolor\n', '@nocolor\n','@language ')):
continue
if '@others' in line:
sline = line.lstrip()
ws = len(line) - len(sline)
if sline == '@others\n':
for ch in chn:
NI[0] += 1
for x in all_lines(ch, ind + ws):
yield x
continue
if ind:
line = (' '*ind) + line
yield line, mNI, i
There is no need at all for @others.
*Example 3*
The auto_py_from_string function leoDataModel.py is now:
Line = namedtuple('Line', 'ln st en ind cl isInd cpos txt')
def auto_py_from_string(rgnx, src):
# init_import
ind = 0
attrs = {}
attrs[rgnx] = [[], [], '', '']
@others
<< do import >>
<< fill lines >>
return nodes2treemodel(tuple(viter(rgnx, 0)))
Clearly, converting the two section references to function calls will have
zero effect on performance.
*Summary*
I can not guarantee the changes give above are equivalent to the original
code. That's precisely the point.
The following functions contains "numbered" children whose order implied.
The edicts mean that these nodes should define explicit sections:
promote
1. promote this part of outline
2. update clones of this node in outline
3. update sizes in outline
Similarly for promote_children, indent_node, and load_derived file.
The section refs in all these functions should be converted to helper
functions. The helper sections are called infrequently.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.