But I'm wondering if there are broader issues here, and if a general
rather than cleo specific solution might be useful.
unknownAttributes (uAs) can be bound to vnodes and / or tnodes, it's up
to the application (script, plug-in, whatever) to decide which location
to use / search. So if vnodes A and B are 'clones' of tnode C, there
are three different places to store/retrieve uAs.
Clones are often used to make indexes or short lists of nodes that are
spread around in other places, a common example being an "active tasks"
node containing clones of nodes on which work is currently being done.
What I struggle with is that some attributes should be universal for
the (t)node in any context, and others only make sense in some contexts.
For example you might color code the backgrounds of cloned nodes in an
active task list to indicate urgency. But when you're looking at the
node in it's "primary" location you don't want to be distracted with
"why is that one node pink?" type noise.
Thinking about it I suspect there's no general solution, these are
application specific issues.
A complicated solution might be for cleo or whatever to try and
interpret the context in which the node's displayed, and selectively
use / ignore attributes based on that.
A simpler solution might involve, when changing uAs on a vnode,
iterating the other clones and updating common attributes without
affecting attributes which aren't shared.
NOTE TO SELF: updates could be on in common keys or restricted to
in common key/value pairs.
Maybe I'll write code for the last approach, and maybe that could move
into the core as it's general rather than cleo specific.
Cheers -Terry
What I struggle with is that some attributes should be universal for
the (t)node in any context, and others only make sense in some contexts.
Do changes on vnodes attributes propagate to all clones or not?
> To repeat: vnodes represent nodes *on the screen*.
This seems like something of an oversimplification to me. The topology
of vnodes defines the context in which your referencing a tnode.
Consider:
Urgent fixes
update_main
delete_all(1)
init_stage2
...
...
class Fred
__init__
delete_all(2)
andSoOn
So the delete_all nodes are clones. One's a reference to the
delete_all code as something needing urgently fixing, the other's a
reference to the delete_all code as a member of the Fred class. The
different contexts are more than just where they are on the screen.
So you might want delete_all(1) color coded to display urgency, but not
see that color at delete_all(2), which is fine, uAs on vnodes work that
way. But there are probably attributes you want present on all
references to delete_all, fine, put them on the tnode, and maybe some
attributes you want on just a subset of references to delete_all, which
means iterating the list of clones and updating appropriately. Seems
to me the current implementation gives plenty of flexibility.
Shoot, oversimplification is 3 letters to long to be a great Scrabble
word :-)
I've attached a diagram of structure I made some time ago, it's not
new, I think it was correct. The pink things are vnodes, the others
tnodes, BTW. I find myself wondering what would happen if vnodes had
their own list of 'children' rather than taking them from their tnode.
The simple answer, of course, is that everything would break :-)
Cheers -Terry
This seems like something of an oversimplification to me. The topology
> To repeat: vnodes represent nodes *on the screen*.
of vnodes defines the context in which your referencing a tnode.
Therefore, simplifying the node concept in Leo would have me up in arms.
> Without tnodes, cloned "just plain nodes" must contain *copies* of all
> data structures that used to be in tnodes. Updating those structures
> is possible, using the equivalent of v.t._vnodeList, but it would be a
> significant rewrite of the internals.
>
Before asking the following question, I must note that there is so much
code making good use of the vnode/tnode distinction that I think it
would be a bad idea to change Leo's internals.
The question is: why would "just plain nodes" need to have copies of
data structures? The only distinction I can think of in "just plain
leo" between one vnode and another is whether it is expanded or not, and
that has never been an essential feature for me (that is, if I
expanded/collapsed one vnode and all its clones instantly
expanded/collapsed as well, I'd be neither annoyed nor pleased).
Consider the following data structure for a node of a DAG:
node_data # header, body
ordered_list_of_children # references to other nodes
That data structure is also sufficient for a general graph, and contains
no optimizations or constraints appropriate to a DAG. Aside from being
a conceptual underpinning, such a simplification might help with design
of alternative access to the Leo data, e.g., as represented in a
database or via AJAX.
Or perhaps I'm missing something obvious; if so, please do enlighten me.
- Stephen
why would "just plain nodes" need to have copies of data structures?
Edward, I am very glad you are sharing your thoughts in this depth.
At the same time I still feel stymied as I just sent in the slides,
where it is basically stated that Leo's data structure basically
reflects
ODM, that Leo is being developed for 10 years and has matured,
is stable, unlikely to undergo big changes etc.
A rose by any other name. If you look at the ODM you will see
that there is a distinction between --Ref and --Def elements, and
that some attributes are peculiar to the reference and some to
the definition. You may refer to it as bad style but I was elated
to see this structure mirrored by Leo.
The question is, how do I hide the auxiliary nodes from the
user.
I would really like to preserve the tree view which is
for instance seen in the screenshot of this offer: http://www.xml4pharma.com/SDTM-ETL/
The other suggestion was outlined by you and Terry in the
parallel thread: to somehow annotate the position during a
traversal of the tree. You call that easy, but then you are a
programmer.
> > The other suggestion was outlined by you and Terry in the
> > parallel thread: to somehow annotate the position during a
> > traversal of the tree. You call that easy, but then you are a
> > programmer.
>
> I strongly suggest not going in this direction. It's really, really
> ugly, and it will not be easy to do correctly.
Actually I wasn't suggesting "annotating the position", but rather just
iterating through p.stack (which in unified node world will make more
sense) to determine context.
But now that you mention "annotating the position" it seems that there
might be uses for callbacks invoked by a position as it moves through
the tree. I'm not sure it would achieve anything you couldn't do by
iterating p.stack, but it might save time.
A
B
C
D
E
If a position gets to D and it has called a registered callback at each
step (with itself as an argument, no doubt) it could already contain
information collected from A, B, and C on the way, instead of
collecting information from A, then A and B, then A and B and C, then
A-D, as would be the case with iterating p.stack.
There'd need to be some invocation of the callback as the position
moved back up, so that B,C,D info. could be dumped when you get to E.
Of course this is all assuming too much about how iterators work with
positions without checking the code, but I think it's interesting in
the context of, er, context.
> I just don't see how I can be wrong about this. In my eyes, you are
> misusing clones so that they appear differently in different contexts.
Cleo does a similar thing, although changing it probably wouldn't have
any noticeable impact on cleo. I think using vnodes to distinguish
context has been an obvious, even if unintended, choice, up to now.
Positions have evolved to more important and sophisticated entities
over time.
Cheers -Terry
> <link from="gnx1" cx="4" a="EMOTV" unknAtrr1="foo" />
The issue of whether links carry no attributes at all, or only a
(perhaps implicit) "direction" attribute, or any number of attributes,
is interesting.
If I'm understanding, the current unified nodes proposal is that links
carry no attributes (apart from the trivial implicit direction, either
child list or parent list). So links have nothing interesting to tell
us except where they point. An they can just be a python list of
references to nodes.
Once you let them carry additional attributes they have to be objects in
their own right, like vnodes. The alternative is to use "intermediate"
regular nodes to carry link related information when required.
For links carrying arbitrary attributes, where upper case are nodes and
lower case are links, you could represent something as:
A-+-a-B
|
+-b-C
|
+-c-D
where a, b, and c can tell you things about how A relates to B, C, and
D.
Vs. links that carry no attributes, again upper case are nodes and lower
case links:
A-+-x-M-x-B
|
+-x-N-x-C
|
+-x-O-x-D
I use 'x' for all the links because while they're all separate links,
there all just python list entries. M, N, and O are additional nodes
used to carry link information.
I think the latter's the unified node plan for cases where you need to
store information about links.
Not trying to illuminate anyone, just working through my understanding
to see if it's on the right page.
Cheers -Terry
Of course, if you must, you can base your product on the old world. It's always a valid option.
I hope there are more "important" (by any metric) users of Leo than
myself.
> 1. Perhaps most importantly, in the unified-node world, are Leo
> outlines a proper representation of a DAG? If so, what is the graph-theoretical correspondence between the graph and Leo nodes?
My take on it is as follows:
The current implementation represents a vertex- and edge-labelled
DAG. Unified nodes lose the possibility to label edges.
I suspect most of the requests [for joined nodes] stem from misplaced analogies about object inheritance or parameterised macros.
the user as clones. But then I have the clone mark on every node,
OK; I can flesh out all non-intermediate nodes and present them to
where I would like the clone mark to be significant to the user.
The thing is that the --Ref attributes (in CDISC ODM) are few and not
too often made use of. In an earlier version I had combined --Ref and
--Def attributes in tnode uA's (until I rejoicingly noticed that
tnodes and vnodes can be annotated separately). There is a possibility that all --Ref attributes can go into unknownAttributes of the mother node, but that may mean that these uA's have to be updated whenever a
child node is deleted or moved. But then I always wanted to know
about plugins and hooks anyway.
> Clone marks
>
> Now is the time to mention another piece of the puzzle. In order to
> set the clone mark, (unified) nodes must contain another ivar.
> Provocatively, let us call this ivar n.vUa. (It will probably be
> called something like n.cloneInfo). vUa will contain zero or more
> dictionaries. We add a dict to vUa when creating or cloning a node,
> and delete a dict when deleting a node. A node n is cloned iff
> len(n.vUa) > 1.
I would have thought, if unified nodes have both a children list and a
parent list, which I think they do according to a previous email, a
node n is cloned iff len(n.parents) > 1?
I can see how n.vUa might be constructed on read, but I don't see how
that works on write, would it not just appear that that dict belongs to
the node, i.e. is that nodes uA dict?
On second thoughts, perhaps I get it, the keys in n.vUa identify which
parent brought us to this node, they're sort of a parent specific uA?
Is that easier than doing something based on p.stack[-1]... assuming
that's a reference to the parent that brought us to this node? You can
only pick a entry from n.vUa if you know the context (position) and so
which parent is relevant?
Cheers -Terry
I would have thought, if unified nodes have both a children list and a
parent list, which I think they do according to a previous email, a
node n is cloned iff len(n.parents) > 1?
I can see how n.vUa might be constructed on read, but I don't see how
that works on write, would it not just appear that that dict belongs to the node, i.e. is that nodes uA dict?
On second thoughts, perhaps I get it, the keys in n.vUa identify which
parent brought us to this node, they're sort of a parent specific uA?
> > I would have thought, if unified nodes have both a children list
> > and a parent list, which I think they do according to a previous
> > email, a node n is cloned iff len(n.parents) > 1?
>
> That was my first thought too. But two clones can share the same
> parent.
Yes... but they must also each have at least one additional parent in
order to be clones? So len(n.parents) > 1 holds?
I've been becoming increasingly unsure about the definition of "clone"
in the unified node world. At least, I see no problem mapping
current Leo's "clones" to the unified node world, but the discussion
using the term clone, I'm not sure we're on the same page.
Data:
A-+
|
+-B
|
+-C-+
| |
| +-F
|
+-D-+
|
+-E
|
+-(to C)
Alternative view, same data (this is a DAG, just assume
arrowheads as needed):
A-+
|
+-B
|
+--------------+
| |
| |
| |
+-D-+ +-C-+
| | |
+-E | +-F
| |
+----------+
Leo tree widget presentation:
A-+
|
+-B
|
+-C*-+
| |
| +-F
|
+-D-+
|
+-E
|
+-C*-+
|
+-F
Narrative:
Node C is "cloned". There is only one C node. "*" is the Leo clone
indicator. Node C occurs in the children lists of both A and D. Node
C has two entries in its parents list, i.e. A and D. There is only
one node F, and it has only node C on its parent list. In the
vnode/tnode world you'd say the Fs are joined (I think?), but they're
the same node, so this is redundant.
Cheers -Terry
I've been becoming increasingly unsure about the definition of "clone"
in the unified node world.
> That was my first thought too. But two clones can share the same parent.Ouch. That's where the DAG analogue breaks, or even the analogue with
graphs in general. Didn't think of that.
In order to maintain the analogy, would it be possible to disallow
"identical twins", so to say? Obviously this would mean getting rid of
the Clone Node function and having "Paste node as clone" as the normal
way of producing clones. Or are there use cases for having multiple
clones as siblings?
On a related note, how would unified-node versions of Leo handle
legacy files? Will there be an import function? If you'd be willing to
make a change taht radical, the import function would then merge
idenical twins to a single node (and give a warning about it).
I am boldly proposing this for three reasons: Out of some kindergarten
spite ("you destroy my card house, so I'm destroying someone else's"),
because I am right now seeing no use for identical twins, and because
I think it is a very good idea to keep the analogy to some very well
described and explored mathematical structure.
> > That was my first thought too. But two clones can share the same
> > parent.
>
> Ouch. That's where the DAG analogue breaks, or even the analogue with
> graphs in general. Didn't think of that.
>
> In order to maintain the analogy, would it be possible to disallow
> "identical twins", so to say? Obviously this would mean getting rid of
> the Clone Node function and having "Paste node as clone" as the normal
> way of producing clones.
Ah, now I understand the "two clones can share the same parent" bit, I
didn't get it until now. But is there anything, in the most general of
generalized graphs, that says you can't have two links between nodes?
It seems unified node world could just have B appear in A's children
list twice. Obviously there a limited reasons for doing this,
basically to support the usually transient state created by the Clone
Node function, and maybe to make an entry visible at two places in a
long list. But I don't see how it's a problem - it's working now,
basically.
I think it's a shame unified node world isn't happening, because I
don't think the v/tnode system has any advantages and I think the
v/tnode system is much less intuitive.
Of course, if we get a sane p.stack and vnodes get parents and children
iterators that yield other vnodes we're basically there, is that how
things are going to fall out?
Cheers -Terry
Ah, now I understand the "two clones can share the same parent" bit, I
didn't get it until now. But is there anything, in the most general of
generalized graphs, that says you can't have two links between nodes?
It seems unified node world could just have B appear in A's children
list twice. Obviously there a limited reasons for doing this,
basically to support the usually transient state created by the Clone
Node function, and maybe to make an entry visible at two places in a
long list. But I don't see how it's a problem - it's working now,
basically.
I think it's a shame unified node world isn't happening, because I
don't think the v/tnode system has any advantages and I think the
v/tnode system is much less intuitive.
Of course, if we get a sane p.stack and vnodes get parents and children
iterators that yield other vnodes we're basically there, is that how
things are going to fall out?
When two clones have the same parent (e.g., immediately after the
clone node operation) wouldn't they list the same parent twice in the
parent list?
This sounds to me as if you'll eventually drop tnode uA's. I amassuming an alert position again.
>
> This has the feel of some kind of permission problem. The following
> just succeeded, but it looks like it created a new branch named
> ~sschaefer/trunk, which is apparently separate from ~leo-editor-team/
> trunk. Is there something I need to do to join the "leo-editor-team"?
https://launchpad.net/~leo-editor-team
Should be a join team button there I think.
Cheers -Terry
That did it, thanks! The changes are now in the trunk.
I have only the mildest of aesthetic objections. My timings from
before and after introducing the lambda arguments differed only in the "noise" range. On the other hand, when I tried using psyco, it
crashed very badly, and psyco has recently had problems with lambdas, so if getting rid of the lambdas allowed psyco to work, that would be an overwhelming reason to remove the lambdas.
> What I struggle with is that some attributes should be universal for
> the (t)node in any context, and others only make sense in some contexts.
> For example you might color code the backgrounds of cloned nodes in an
> active task list to indicate urgency. But when you're looking at the
> node in it's "primary" location you don't want to be distracted with
> "why is that one node pink?" type noise.
(*bump*)
I am replying to this old thread because it's important.
As it appears, most of the advantages of vnode uAs (and vnodes in
general) seem to be misunderstandigs (i.e. assumption that vnode is
somehow like position, i.e. tree position specific).
--
Ville M. Vainio
http://tinyurl.com/vainio
(*bump*)
On Tue, Feb 26, 2008 at 2:14 AM, Terry Brown<terry_...@yahoo.com> wrote:
> What I struggle with is that some attributes should be universal for
> the (t)node in any context, and others only make sense in some contexts.
> For example you might color code the backgrounds of cloned nodes in an
> active task list to indicate urgency. But when you're looking at the
> node in it's "primary" location you don't want to be distracted with
> "why is that one node pink?" type noise.
On Tue, Feb 26, 2008 at 9:16 PM, Edward K. Ream<edre...@gmail.com> wrote:
>> This seems like something of an oversimplification to me. The topology
>> of vnodes defines the context in which your referencing a tnode.
>
> Yes, you are correct. I misspoke. Vnodes *used to* correspond to nodes on
> the screen, but that is ancient history.
Ah, so this explains existence of vnodes - they were analogous to
positions before , but this analogy was removed at some point
(effectively making vnodes redundant).