That works for me. On Mon, Jun 15, 2015 at 8:55 AM, Marko Rodriguez <[email protected]> wrote:
> Ah. The plot thickens. > > I prefer to keep limit() and tail(). > > What if we do: > > Pop.first (was Pop.tail) > Pop.last (was Pop.head) > > Is then everything else consistent? > > Marko. > > http://markorodriguez.com > > On Jun 15, 2015, at 9:15 AM, Matt Frantz <[email protected]> > wrote: > > > In addition to unfold().tail(), there is tail(local), which is consistent > > with unfold().tail() in that it grabs the "end" of the List (or Map). > > > > By "consistent throughout", I guess you mean "select's use of head/tail > > terminology should be consistent with established terminology in graph > > theory." You also say that List.iterator() emits values left-to-right > > (tail to head). However, the terminology that I am accustomed to is > > described on the wiki for a Linked list: "The 'head' of a list is its > first > > node. The 'tail' of a list may refer either to the rest of the list after > > the head, or to the last node in the list." > > > > This terminology resonates in a cursory search ("stream head tail") to > > describe streams, i.e. "head" means the first thing that comes out of a > > stream, while "tail" means "everything except the head." With an integer > > argument, "head(n)" resembles Gremlin's "limit(n)", if you think of a > > Gremlin traversal as a stream that produces traversers. > > > > The use of "head" and "tail" as Unix utilities is currently consistent > with > > the tail step's usage, in that they refer, respectively, to the first and > > last objects in the stream. > > > > I feel that the two uses of "tail" should be consistent with each other > > within Gremlin, but I can see that they are currently drawn from > different > > disciplines of computer science. My preference would be to replace > > "limit/tail" with "first/last" to avoid such ambiguity. Then, we can > swap > > Pop head/tail as it was in the beginning. > > > > The idea of making "limit" and "tail" more obviously symmetric belies the > > origin of "limit" as a terminology ported from RDBMS (I presume). I am > not > > opposed to synonyms/aliases, although the Gremlin language may be rich > > enough without them. > > > > I'd be happy to help with whatever solution is agreeable to the > community. > > I'll have some TP3 budget in a couple of days. > > > > My two cents. > > > > On Mon, Jun 15, 2015 at 6:55 AM, Marko Rodriguez <[email protected]> > > wrote: > > > >> Hi, > >> > >> So the way the select() puts things into a List (i.e. Path.get()), > >> currently, is good: > >> > >> gremlin> g.V().as('a').out('created').as('a').select('a') > >> ==>[v[1], v[3]] > >> ==>[v[4], v[5]] > >> ==>[v[4], v[3]] > >> ==>[v[6], v[3]] > >> > >> In the first result, the "tail/start/initial" is v[1] and the > >> "head/end/terminal" is v[3]. That lines up with the tail/head > terminology > >> in graph theory. However, what is off is that Pop.head/tail is wrong: > >> > >> gremlin> g.V().as('a').out('created').as('a').select(head,'a') > >> ==>v[1] > >> ==>v[4] > >> ==>v[4] > >> ==>v[6] > >> > >> Pop.head should return v[3] (for the first result). This is a simple fix > >> of just reversing the meaning of Pop.head/tail (2 line fix). > >> > >> However, the reason you flipped Pop.head/tail to begin with is because > you > >> wanted it to align with unfold().tail(). So lets look at unfold(). > >> > >> gremlin> > g.V().as('a').out('created').as('a').select('a').limit(1).unfold() > >> ==>v[1] > >> ==>v[3] > >> gremlin> > >> > g.V().as('a').out('created').as('a').select('a').limit(1).unfold().tail(1) > >> ==>v[3] > >> > >> This should emit v[1]. Bumskies! However, this is about how the > "unfolded" > >> Iterable is iterated. > >> > >> gremlin> [1,2,3,4].iterator() > >> ==>1 > >> ==>2 > >> ==>3 > >> ==>4 > >> > >> Unfortunately, when you do List.iterator(), it emits values > left-to-right > >> (tail to head). Not right-to-left (head to tail). So, we can make > unfold() > >> behave differently by: > >> > >> gremlin> [1,2,3,4].reverse().iterator() > >> ==>4 > >> ==>3 > >> ==>2 > >> ==>1 > >> > >> …but that is no bueno from a memory conservation standpoint. I would > argue > >> that unfold() has nothing to do with path-semantics, but instead, list > >> semantics. Therefore, we can argue (in debate) that "unfold().tail()" is > >> not an anomaly of tail(), but one of unfold(). > >> > >> Thus, to be consistent throughout, all we need to do is flip Pop.head to > >> Pop.tail and vice versa (i.e. as it was originally). > >> > >> Thoughts?, > >> Marko. > >> > >> http://markorodriguez.com > >> > >> On Jun 12, 2015, at 12:56 PM, Matt Frantz <[email protected]> > >> wrote: > >> > >>> We could do any of the following: > >>> > >>> - Rename the "tail" step (e.g. "last") so that we can flip Pop back to > >>> the way graph theorists presumably expect it to work. > >>> - Reverse the way "select" puts things in a List, and flip Pop back. > >>> - Rename Pop head/tail to oldest/newest (or first/last) > >>> > >>> > >>> On Fri, Jun 12, 2015 at 5:14 AM, Marko Rodriguez <[email protected] > > > >>> wrote: > >>> > >>>> Hm… I see what you are saying. The problem is that in graph theory, > >>>> head/tail terms are reversed in Path. > >>>> > >>>> Marko. > >>>> > >>>> http://markorodriguez.com > >>>> > >>>> On Jun 11, 2015, at 3:39 PM, Matt Frantz <[email protected]> > >>>> wrote: > >>>> > >>>>> Another symmetry I was aiming for: > >>>>> > >>>>> ...select(tail, 'a') > >>>>> ...select('a').by(unfold.tail(1)) > >>>>> > >>>>> On Thu, Jun 11, 2015 at 2:16 PM, Matt Frantz < > >> [email protected] > >>>>> > >>>>> wrote: > >>>>> > >>>>>> I was trying to reconcile the way that the range/limit/tail steps > >>>> operate > >>>>>> with how Pop is interpreted. For local scope, the range ordinals > are > >>>>>> congruent with the list index ordinals. Thus, "limit(1)" means > >>>>>> "range(0,1)" which means List.get(0). Since "tail(1)" is the > >>>> complement of > >>>>>> "limit(1)", it means "the highest numbered element" or > >>>>>> List.get(List.size()-1). > >>>>>> > >>>>>> I understand your description of a stream, but I was trying to > >> reconcile > >>>>>> the terms with Gremlin and not with streams. > >>>>>> > >>>>>> If you compare a stream with a Unix command line, and how the "head" > >> and > >>>>>> "tail" utilities act, then "head" means "the first lines you see" > and > >>>>>> "tail" means "the last lines you see". > >>>>>> > >>>>>> For global scope, it seems that "limit(1)" means "the first > traverser" > >>>> and > >>>>>> "tail(1)" means "the last traverser". For any Traversal, t, > >> t.limit(1) > >>>>>> produces the same thing as t.toList().get(0). > >>>>>> > >>>>>> Good news on select(pop)! > >>>>>> > >>>>>> On Thu, Jun 11, 2015 at 11:43 AM, Marko Rodriguez < > >> [email protected] > >>>>> > >>>>>> wrote: > >>>>>> > >>>>>>> Hey, > >>>>>>> > >>>>>>> Yes -- "first = tail" and "last = head". > >>>>>>> > >>>>>>> A path grows with its "head growing" .. its tail is static. > >>>>>>> > >>>>>>> a-->b-->c-->d-->e > >>>>>>> > >>>>>>> the tail is always "a"…the head is "a", then "b", then "c", then > >> "d"…. > >>>>>>> > >>>>>>> In a list or stream, the tail is the first element. > >>>>>>> - get(0) for list > >>>>>>> - stream().toList().get(0) > >>>>>>> In a list or stream, the head is always the most current element. > >>>>>>> - get(list.size() - 1) for list > >>>>>>> - stream().next() > >>>>>>> > >>>>>>> …..? > >>>>>>> > >>>>>>> I will hide your interface inside ImmutablePath just for my sanity > >> :). > >>>>>>> > >>>>>>> BTW: select(pop) is on its way. > >>>>>>> > >>>>>>> Marko. > >>>>>>> > >>>>>>> http://markorodriguez.com > >>>>>>> > >>>>>>> On Jun 11, 2015, at 12:30 PM, Matt Frantz < > >> [email protected]> > >>>>>>> wrote: > >>>>>>> > >>>>>>>> limit(1) means "first" and tail(1) means "last" (in both global > and > >>>>>>> local > >>>>>>>> manifestations). > >>>>>>>> > >>>>>>>> In the Path.get results, you get a list whose first element is the > >>>>>>>> first/oldest object matching the step label, so that felt like > >> "head" > >>>> to > >>>>>>>> me, while the last element is the most recent and thus "tail". > >>>>>>>> > >>>>>>>> get => [a,b,c,d] > >>>>>>>> getSingle(head) => a > >>>>>>>> getSingle(tail) => d > >>>>>>>> > >>>>>>>> In other words the following should be equal: > >>>>>>>> > >>>>>>>> ...map{it->it.path().get('foo')}.tail(local, 1) > >>>>>>>> ...map{it->it.path().getSingle(tail, 'foo')} > >>>>>>>> > >>>>>>>> I used ImmutablePathImpl because I needed HeadPath to have the > >>>>>>>> getSingleTail/getSingleHead methods, too. Thus, a common > interface > >>>>>>> between > >>>>>>>> ImmutablePath and HeadPath was required. The interface has > package > >>>>>>> scope, > >>>>>>>> so it is not part of the public API. > >>>>>>>> > >>>>>>>> On Thu, Jun 11, 2015 at 11:12 AM, Marko Rodriguez < > >>>> [email protected] > >>>>>>>> > >>>>>>>> wrote: > >>>>>>>> > >>>>>>>>> Hi Matt, > >>>>>>>>> > >>>>>>>>> limit(1) means the most recent value. > >>>>>>>>> tail(1) means the oldest value. ? > >>>>>>>>> > >>>>>>>>> path: [a,b,c,d] > >>>>>>>>> a = tail > >>>>>>>>> d = head > >>>>>>>>> > >>>>>>>>> No? > >>>>>>>>> > >>>>>>>>> Also, why did you do ImmutablePathImpl? Seems that can just be > >>>> private > >>>>>>>>> methods inside of ImmutablePath? > >>>>>>>>> > >>>>>>>>> Thanks, > >>>>>>>>> Marko. > >>>>>>>>> > >>>>>>>>> http://markorodriguez.com > >>>>>>>>> > >>>>>>>>> On Jun 11, 2015, at 11:56 AM, mhfrantz <[email protected]> > wrote: > >>>>>>>>> > >>>>>>>>>> GitHub user mhfrantz opened a pull request: > >>>>>>>>>> > >>>>>>>>>> https://github.com/apache/incubator-tinkerpop/pull/76 > >>>>>>>>>> > >>>>>>>>>> TINKERPOP3-700 Path getSingle/getList improvements > >>>>>>>>>> > >>>>>>>>>> As requested in the comments of TINKERPOP3-700. I also reversed > >>>> the > >>>>>>>>> sense of `Pop` to align with `tail(local)`. Thus `Pop.tail` now > >>>> means > >>>>>>> the > >>>>>>>>> most recent value. > >>>>>>>>>> > >>>>>>>>>> You can merge this pull request into a Git repository by > running: > >>>>>>>>>> > >>>>>>>>>> $ git pull https://github.com/RedSeal-co/incubator-tinkerpop > >>>>>>>>> TINKERPOP3-700-Path-getSingle > >>>>>>>>>> > >>>>>>>>>> Alternatively you can review and apply these changes as the > patch > >>>> at: > >>>>>>>>>> > >>>>>>>>>> https://github.com/apache/incubator-tinkerpop/pull/76.patch > >>>>>>>>>> > >>>>>>>>>> To close this pull request, make a commit to your master/trunk > >>>> branch > >>>>>>>>>> with (at least) the following in the commit message: > >>>>>>>>>> > >>>>>>>>>> This closes #76 > >>>>>>>>>> > >>>>>>>>>> ---- > >>>>>>>>>> commit e1e1a40b068ffe6da3d321256d6200dee0504074 > >>>>>>>>>> Author: mhfrantz <[email protected]> > >>>>>>>>>> Date: 2015-06-11T16:47:41Z > >>>>>>>>>> > >>>>>>>>>> Add javadoc for Path getList/getSingle > >>>>>>>>>> > >>>>>>>>>> commit 4939cf0a22c4fc44a4f86ed3e023fa30e4e872cc > >>>>>>>>>> Author: mhfrantz <[email protected]> > >>>>>>>>>> Date: 2015-06-11T17:10:27Z > >>>>>>>>>> > >>>>>>>>>> Reverse sense of Path.getSingle Pop to align with tail(local) > step > >>>>>>>>>> > >>>>>>>>>> commit 027d6319f9ff06ca26d785e83bf17b21364c3dca > >>>>>>>>>> Author: mhfrantz <[email protected]> > >>>>>>>>>> Date: 2015-06-11T17:51:23Z > >>>>>>>>>> > >>>>>>>>>> Optimize MutablePath.getSingle > >>>>>>>>>> > >>>>>>>>>> commit 5e9ad8d7dff6c63b9746147a1d255cbf7258cea3 > >>>>>>>>>> Author: mhfrantz <[email protected]> > >>>>>>>>>> Date: 2015-06-11T17:52:43Z > >>>>>>>>>> > >>>>>>>>>> Optimize ImmutablePath getSingle and getList > >>>>>>>>>> > >>>>>>>>>> ---- > >>>>>>>>>> > >>>>>>>>>> > >>>>>>>>>> --- > >>>>>>>>>> If your project is set up for it, you can reply to this email > and > >>>> have > >>>>>>>>> your > >>>>>>>>>> reply appear on GitHub as well. If your project does not have > this > >>>>>>>>> feature > >>>>>>>>>> enabled and wishes so, or if the feature is enabled but not > >> working, > >>>>>>>>> please > >>>>>>>>>> contact infrastructure at [email protected] or file a > >> JIRA > >>>>>>>>> ticket > >>>>>>>>>> with INFRA. > >>>>>>>>>> --- > >>>>>>>>> > >>>>>>>>> > >>>>>>> > >>>>>>> > >>>>>> > >>>> > >>>> > >> > >> > >
