How about a third choice that always returns a List? Pop.all? This would provide the Java Generic type safety that fills our hearts with light.
On Mon, Jun 15, 2015 at 9:49 AM, Matt Frantz <[email protected]> wrote: > 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. >> >>>>>>>>>> --- >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>> >> >>>>>>> >> >>>>>> >> >>>> >> >>>> >> >> >> >> >> >> >
