Welcome, Guest. Please Login
Tinderbox
  News:
IMPORTANT MESSAGE! This forum has now been replaced by a new forum at http://forum.eastgate.com and no further posting or member registration is allowed. The forum is still accessible via read-only access for reference purposes. If you wish to discuss content here, please use the new forum. N.B. - posting in the new forum requires a fresh registration in the new forum (sorry - member data can't be ported).
  HomeHelpSearchLogin  
 
Pages: 1 2 
Send Topic Print
Finding the first child of agent item aliases... (Read 4666 times)
Pat Maddox
Full Member
*
Offline



Posts: 66

Finding the first child of agent item aliases...
Apr 01st, 2016, 11:26am
 
This is very similar to this question... but unfortunately I can't seem to figure it out.

I have a container called "projects". It has children, some of which have children.

I have an agent called "actionable projects". Its query is:

Code:
inside("projects") & $ChildCount > 0 



This returns any of my projects that have a child.

Now I want to find a list of tasks – any note that is a child of a note found by "actionable projects". That's where I'm stuck.

I have tried a bunch of stuff and always get 0 results. So I'm not sure it's even worth sharing what I tried. I just don't know how to compose this query.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #1 - Apr 1st, 2016, 12:23pm
 
Anything 'inside' your 'actionable projects' is the child of an agent and thus an alias. Aliases don't have children but their originals do. However, you can look 'down' from an alias at the (original's) descendants attributes. Thus if you give your 'actionable projects' this rule:

$MyNumber = sum(children,$ChildCount)

…your agent will have a count of the tasks. The reason I mention this, is I think your need is essentially to do the opposite - look upwards from a child to an alias of the parent. But, I don't think Tinderbox supports that.

No matter, there's usually more that one way to solve a task, so let's back out of that dead-end and look at a simple alternate. The easiest approach is to make the 'actionable projects' agent set a flag that your task-finding agent can poll. So, make a Used Boolean attribute $IsActionable. now make the 'actionable projects' agent's action:

$IsActionable = true

Now make your new 'actionable task' agent and give it this query:

$IsActionable(parent)==true

(Code tested in v6.5.0b198)

~~~~~~~~
If you are likely to delete all of a project's tasks, then you've an edge case to deal with, but it's better to avoid such complication unless you definitely know you need it.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #2 - Apr 1st, 2016, 12:37pm
 
Hrm... I really don't like that attribute-based approach. I can't put my finger on why. But it seems like there ought to be an approach that works with queries. Like:

parent(inside("actionable projects"))

"my parent is inside the actionable projects list"

Per the tbref, inside will return true if "an alias of A is inside X" (or two other conditions).

So my query (which doesn't work of course) to me would mean: "my parent, or an alias of my parent, is inside the actionable projects list".

I have to figure there's a clean query-based approach for this, rather than setting up attributes...
Back to top
 
 
  IP Logged
Mark Bernstein
YaBB Administrator
*
Offline

designer of
Tinderbox

Posts: 2871
Eastgate Systems, Inc.
Re: Finding the first child of agent item aliases...
Reply #3 - Apr 1st, 2016, 12:51pm
 
How about something like this?

   $Path(grandparent)=="/projects"

That'll find all the grandchildren of the top-level container "projects".  If you have other kinds of grandchildren and you only want the tasks, try:

        $Path(grandparent)=="/projects" & $Prototype="Task"


Back to top
 
 
WWW   IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #4 - Apr 1st, 2016, 12:55pm
 
Yes, something like that can work.

I just want to clarify: is there no query that can express the idea "give me the children of an alias's original note"?

That's pretty surprising to me, given Tinderbox's power. But if that's truly the case, then I'll completely drop this line of thinking.
Back to top
 
 
  IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #5 - Apr 1st, 2016, 1:06pm
 
Here's what I came up with:

Code:
collect(children("actionable projects"), $ID(original)).contains($ID(parent)) 



This feels long-winded to me, and that it would be pretty slow once my project gets bigger (if I'm reading it right, it will rebuild the list of actionable project paths for every single note that it compares... but maybe TB is doing some optimization, who knows?)

I'm wondering if there's a simpler way to express it?

In the mean time, I guess I'll live with it and see how the document performs over time...

edit: changed $Path to $ID to handle case of notes with duplicate names / paths.
Back to top
 
« Last Edit: Apr 1st, 2016, 1:28pm by Pat Maddox »  
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #6 - Apr 1st, 2016, 1:50pm
 
Quote:
edit: "my parent, or an alias of my parent, is inside the 'actionable projects' list"

I get the desired logic, but I tried to explain, I don't think a child/descendant can interrogate upwards for its parent/ancestor's aliases - i.e. the bit in italics. It's not the the question is inherently wrong, but just this sort of query hasn't been asked for/implemented before (people have used other routes to the answer like above); it was only late in v5 (IIRC) that we could look at an original's children via an alias.

If there is a pattern for this sort of problem, it is the attribute method I described above. This problem has the smell of trying to write a complex code one-liner that might as easily be done in several steps.

Is the problem disppointment at non being able to implement ones conjectured ideal apporach (which I totally get - been there myself) or is there a practical implementation problem here that we're missing?
Back to top
 
« Last Edit: Apr 1st, 2016, 1:50pm by Mark Anderson »  

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #7 - Apr 1st, 2016, 3:56pm
 
Quote:
I don't think a child/descendant can interrogate upwards for its parent/ancestor's aliases


I'm not trying to interrogate upward for a parent's aliases! I have an alias (via an agent), and I want to get the children of the original note that the alias points towards.

Quote:
it was only late in v5 (IIRC) that we could look at an original's children via an alias.


That sounds like what I'm trying to do...

Quote:
If there is a pattern for this sort of problem, it is the attribute method I described above. This problem has the smell of trying to write a complex code one-liner that might as easily be done in several steps.


Hrm. I disagree. I think the attribute approach violates the principle of incremental formalism. For me, as of right now, an actionable project is any project that has a task associated with it. An actionable project is NOT any project with a special attribute set to on, with an agent that looks for appropriate projects and then sets the attribute.

I already have the list of projects via my query! Why on earth would I need to set an attribute to determine that list? Why is there such a huge leap between asking "does my parent have this attribute set" and "Is my parent inside another note" (remember, inside purports to check whether aliases live somewhere, in addition to originals...)

Quote:
Is the problem disppointment at non being able to implement ones conjectured ideal apporach (which I totally get - been there myself) or is there a practical implementation problem here that we're missing?


It's a problem of learning the Tinderbox query / programming model. "There's more than one way to do it" is a mantra around here. I'm cool with that! I think the attribute approach you posed is hacky. I need one agent to set things as actionable. I need another agent to set them as not actionable. I already have a mechanism for determining whether a project is actionable... and that is covered by inclusion in my query agent.

You and Mark B came up with solutions to a similar problem that I wouldn't have come up with. So, I'm trying to get an understanding of the query model so that I can come up with solutions myself.

And here's where my understanding of the Tinderbox query model breaks down:

1. I CAN get a note's parent
2. I CAN determine whether a note (or one of its aliases) is inside some other note
3. I CAN get a list of children for a note
4. I can't use them together???

Tinderbox seems to come with all the parts to make the query I need. But I can't figure it out. It seems more likely to me that it's a failure in my understanding of how to put things together, not that Tinderbox doesn't support it.

If Tinderbox doesn't support it, so be it. But my first inclination in such a situation is that I still lack understanding.

Perhaps the tbref documentation is out of date?

I'm basing my "desired" approach on a single line of tbref doc:

Quote:
In a more general context inside("X") is true for note A if... an alias of A is inside X


Based on that, I would expect either of these two to work:

Code:
any(ancestors, inside("actionable projects")); // any of my ancestors (or their aliases) are inside "actionable projects"
eval(parent(original), inside("actionable projects")); // my parent (or an alias) is inside "actionable projects" 



The big question: is it possible or not?

My final bit of frustration stems from not knowing whether what I want to do is possible or not. Both Marks have weighed in on ways to go about this. And maybe the implicit answer is, "No, you can't do that." But rather than come up with workarounds - when my limited understanding at this point is that Tinderbox can support my query but I just don't know how to express it - I'd rather get a definitive answer on whether TB can do this, and if not, THEN look at workarounds.

I've already found a query-based way of solving the problem. It's not complex, but it does seem backwards to me. And I'm assuming that TB can express it more elegantly and I just don't know how.

If TB truly can't express the query I want with its current functionality, fine... but that's never going to be my first assumption.

Is it really that complicated?

I have a list of notes (aliases in an agent). I want to find the children of the original notes. I have access to parent, inside, children, original, and a hundred other nifty functions... they really don't go together in the way I want? Seems unlikely.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #8 - Apr 1st, 2016, 5:18pm
 
I may be wrong, but I do think the short answer is 'no - via the desired route. I think this example of yours:

any(ancestors, inside("actionable projects"))

sheds some light on the 'missing' information. This polls any ancestor of a note.  For a task note - in TBX model discussed - the ancestors are a project, the 'projects' container, and so on back to root. Thus an alias of the parent project is not ancestor so your any() test fails to give your desired result.

I thus don't believe there is a query method that allows you to do boolean tests on aliases of ancestors of a note. At this point i think such behaviour is a feature request. As a fellow user, with no under-the-hood access, I've no idea of the cost or engineering complexity of adding that in. aTbRef is written from the same, user, context.

Please understand, I'm not taking a zero-sum I win/you lose perspective. Rather, I'm adhering to the pragmatism of Tinderbox use that if you can't do it one way (at this time) then there is likely another approach. My pragmatism leads me towards taking the possible path - no sense of smugness.

A few other tangential observations triggered by your last post:
  • Action code isn't a deliberately planned ground-up programming environment/IDE. Actually, it grew in gradual fashion out of Tinderbox's original ^export^ (which still survives for that purpose), adding features in response to users needs**. Thus don't think of omitted expected programming features so much as possible yet-to-be-implemented ones. IOW, if something's 'missing' it probably isn't there and thus the workaround approach.
  • Action code is added to regularly - there are 2 new operators and a series of scoping tweaks in v6.5.0, just released. If you think a new feature is needed, do email support (giving some sort of use case does help): simple stuff is often added straightway, other things can be more complex than presumed/too expensive to implement.
  • Agents always try to resolve to a single match per note, be it an alias or an original. However, an original is always chosen as the single match if in scope.
  • find() - which is an action code object wrapper for a query, doesn't de-dupe as above. Indeed, you often need to use an $IsAlias filtering query terms to reduce the matches). But, whilst you can put a find in an agent query, the agent will de-dupe so in the context of your problem it doesn't really help.
  • The constant references to 'more than one way' are mainly to help encourage those who are tempted to give up completely the moment their proposed course of attach doesn't work. For users with little/no coding experience getting an outcome often matters more than how the outcome is achieved (as likely they'll never touch the code again). For those with programming experience and an expectation of how things 'should' work, that can be frustrating.
** I can attest to that quite genuinely. Some of my more eccentric projects have resulted in new action code (often in the next beta, if simple). Eastgate isn't a big shop, but does listen to its customers - though such discussion are best had direct via email rather than here in the forum.

I hope that helps, even if I can't conjure up the exact feature you're after. If I've not explained anything clearly enough, do keep asking. I've learned as much about the app from such questions as I have from my own work.  Smiley
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #9 - Apr 1st, 2016, 5:28pm
 
Having checked my aTbRef notes, whilst it is true that:

Quote:
In a more general context inside("X") is true for note A if ... an alias of A is inside X

...it is not true that a descendant of A is descended from X if only an alias of A is inside X and A actually resides elsewhere.

I agree this aspect of the degree to which you can work with children/descendants via an alias is hazy. In part this is because the latter is a fairly recent addition to Tinderbox and thus lightly used by a few people (and in my case for completely different scenarios).

The best summary I can give is you can look at (the existence of) a descendant note via an alias. You cannot, from a descendant, query aliases of that note's ancestor. I'll try and think of a better summary and fold that into aTbRef, as I think this thread has thrown up some interesting - if unresolvable - questions.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #10 - Apr 1st, 2016, 5:34pm
 
Quote:
I may be wrong, but I do think the short answer is 'no - via the desired route. I think this example of yours:

any(ancestors, inside("actionable projects"))

sheds some light on the 'missing' information. This polls any ancestor of a note.  For a task note - in TBX model discussed - the ancestors are a project, the 'projects' container, and so on back to root. Thus an alias of the parent project is not ancestor so your any() test fails to give your desired result.


But there's a piece missing from your explanation. I interpret the tbref for inside() to mean it would be evaluated as:

* poll the ancestors of a note to see if...
* they are inside() a specific note (my agent) - either the original note OR an alias!

Quoted from tbref:

Quote:
In a more general context inside("X") is true for note A if any of the following are true:

* A is inside X
* an alias of A is inside X
* A is an alias, and its original is inside X


So while I agree with you that the ancestor itself is not contained in the agent, and the alias is not itself an ancestor... an alias of the ancestor is in fact inside the agent list.

Leading me to believe one or more of the following to be true:

1. the documentation is wrong
2. my interpreation of the documentation is wrong
3. my usage of what I learned from the documentation is wrong

Quote:
Please understand, I'm not taking a zero-sum I win/you lose perspective. Rather, I'm adhering to the pragmatism of Tinderbox use that if you can't do it one way (at this time) then there is likely another approach. My pragmatism leads me towards taking the possible path - no sense of smugness... The constant references to 'more than one way' are mainly to help encourage those who are tempted to give up completely the moment their proposed course of attach doesn't work. For users with little/no coding experience getting an outcome often matters more than how the outcome is achieved (as likely they'll never touch the code again). For those with programming experience and an expectation of how things 'should' work, that can be frustrating.


Indeed. The flip side is, I don't always go for the first solution that seems to work, if I can think of other ways to do it. Case in point, I found a query-based approach that is closer to what I originally wanted.

More importantly, spending some time upfront helps me learn the program and its features more effectively, so I can be more efficient when using them down the line.

It's an interesting conversation, and I appreciate your perspective on things. I also don't know what's going on under the hood... and so it would be helpful to me if Mark B could state definitively: such an approach isn't supported and would need to be a feature request, or it is supported and this is how you do it.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #11 - Apr 1st, 2016, 5:52pm
 
Quote:
poll the ancestors of a note to see if.

No, inside(X) polls each note [sic] and tests if its parent is X (or some such path-type test - not sure exactly what).

It can be confusing. At first, I assumed I was asking "get X to tell me what children it has", i.e. polling X. In fact, inside("X"), with no other query terms, added, polls every note regadless of where it is in the overall outline for whether it is a child of X.

I'm not sure what in aTbRef gave you the notion that ancestors were polled as that clearly needs reviewing (though this notion has never come up before). I write aTbRef to help fellow users so re-writing for better clarity is an ongoing process and I always welcome input.  Smiley
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #12 - Apr 1st, 2016, 5:56pm
 
Murphy's Law - I happen to know MB's on the road at present with impermanent net access otherwise he'd probably added some clarification by now (give it a few days; at time like these email trumps forums like this for quick access). I do know from past alias related issues that the whole alias area gets complex real fast under the hood. As a non-coder that's a bit over my head!
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Pat Maddox
Full Member
*
Offline



Posts: 66

Re: Finding the first child of agent item aliases...
Reply #13 - Apr 1st, 2016, 6:02pm
 
I think you overlooked half of the code snippet I shared:

Code:
any(ancestors, inside("actionable projects")) 



As I understand this, it will poll the ancestors to see if they're "inside" the actionable projects.

Quote:
I'm not sure what in aTbRef gave you the notion that ancestors were polled


It didn't. tbref gave me the notion that inside() will return true if an alias of the current note is inside the passed in note/path.

When I combine that with any(), I get: "are any of my ancestors (or their aliases) inside actionable projects?"

Make sense?
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Finding the first child of agent item aliases...
Reply #14 - Apr 1st, 2016, 6:31pm
 
[Sorry for multiple replies!]

Perhaps a visual context explains better:



X, Y and Z are projects. Only Y and Z are actionable as X lacks children. So far so good. Note that in the 'actionable projects' agent the aliases of Y and Z have no children.

Now, as I understand it, you want an agent [sic] that would, in this file, hold aliases to Y1, Y2 and Z1. That outcome is achieved by only those 3 notes, of all notes, matching the agent query. The query must resolve at note level, and you can use offset attribute references (i.e. a value of a given attribute but for a different note). But, sadly you can't, for instance, ask a note to resolve aliases of its parent. So the fact that Y and Z have aliases inside another agent is one thing we can't test from the context of Y1, etc.

The nuance here is that I say, "but inside("actionable projects") is true for Y" Well it is for Y, but not Y1. When you test for the container of Y1's parent it is always 'projects'. There isn't a construct to say "if my parent or any of its aliases are in inside(something)" and that's what you need.

I hope this also makes sense of why I made the earlier alternative suggested solution. If we can test task notes and they have some way to know their parent is actionable (other than via a currently impossible query!) then it's not hard to get the desired outcome. However, the (a!) suggested method does involve using stored attribute in the project-level notes. It doesn't have to involve adding a user attribute, I just did that for clarity. You could park a value in one of the Sandbox group of system attributes - e.g. $MyBoolean or $MyString - it all boils down to the same.

FWIW, Tinderbox really doesn't mind adding attributes - it's part of it' incremental formalisation approach (add stuff as you need it) and doesn't have noticeable overhead. In the context of agents, if owrried about load, order the query terms so as to poll as few notes as possible and - as you've already spotted - avoid blanket use of contains and gnarly regex. I should stress the latter does work: I do it a lot in my research, but I'm careful to watch load and don't expect those project to by as quick to resolve as a trivial one like illustrated above.

~~~~~~~~~~~~~
The edge cases always seem obvious after tha fact. Oddly, in 10+ years of use this one is new (to me at least). Of, course that doesn't imply it lacks purpose.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Pages: 1 2 
Send Topic Print