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.
>>>>>>>>>> ---
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>>>
>>
>>