map and flatMap steps

407 views
Skip to first unread message

Michael Pollmeier

unread,
Sep 11, 2015, 12:17:26 AM9/11/15
to gremli...@googlegroups.com
In GraphTraversal you define map and flatMap as I would expect, but
there's also an overloaded version of `map` which doesn't make sense to
me because it takes a `Traversal`. I'm trying to understand what it's
for and if Gremlin-Scala should wrap it.

Background: typically in a monadic class they are defined as follows:
```
class SomeMonad<A> {
def map(fun: A => B): SomeMonad<B>
def flatMap(fun: A => SomeMonad<B>): SomeMonad<B>
}
```
I.e. the only difference is the return type of the provided function. If
you call `map` with a function that is a `A => SomeMonad<B>` then you
get a recursive structure in the return type `SomeMonad<SomeMonad<B>>`.
Which is what you often have, and want to avoid, hence `flatMap` which
maps and flattens the structure.

What's the difference between the `map` and `flatMap` steps which both
take a `Traversal`?

Marko Rodriguez

unread,
Sep 11, 2015, 10:56:50 AM9/11/15
to gremli...@googlegroups.com
Hello,

map: one-to-one
flatMap: one-to-many

If the internal traversal has more than one output and its wrapped in map() only the first output is returned. If its wrapped in flatMap(), all the outputs are returned.

HTH,
Marko

--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/55F255C8.6080009%40michaelpollmeier.com.
For more options, visit https://groups.google.com/d/optout.

Michael Pollmeier

unread,
Sep 13, 2015, 9:22:44 PM9/13/15
to Gremlin-users
Interesting.. that concept doesn't quite align with my understanding of map / flatMap.
To me, `flatMap` is simply `map` followed by `flatten`, so it doesn't have any notion of 'takes only the first output':

```
scala> List(1,2,3)
res0: List[Int] = List(1, 2, 3)

scala> res0.map(i => List(i, i+1))
res1: List[List[Int]] = List(List(1, 2), List(2, 3), List(3, 4))

scala> res1.flatten
res2: List[Int] = List(1, 2, 2, 3, 3, 4)

scala> res0.flatMap(i => List(i, i+1))
res3: List[Int] = List(1, 2, 2, 3, 3, 4)
```

You can think of a Tinkerpop traversal as a List. So in my world a flatten step would transform a nested traversal like `Traversal[Traversal[Something]]` into a `Traversal[Something]`. It's fine with me to leave as is, just wanted to raise my concerns from a functional programming perspective.

Joan

unread,
Sep 16, 2015, 2:07:55 PM9/16/15
to Gremlin-users
To me

To you, to me, to the Scala users, to the Haskell users and to the Java 8 users (except Gremlin users)... That makes a lot of people I guess.

Marko Rodriguez

unread,
Sep 16, 2015, 7:54:40 PM9/16/15
to gremli...@googlegroups.com
Hi,

As I currently reason, Gremlin doesn't work on lists. Its works on streams. Furthermore, it doesn't work for power set mappings. That is:

{ A } -> { B, C, D }

In this environment flatMap is what you would expect from "unfolding" a power set element.

a.flatMap(out()) -> b, c, d (stream of )

For map, we don't do:

a.map(out()) -> [b,c,d] (stream of lists)

..we do:

a.map(out()) -> b

However, I suppose we could do [b,c,d]… but then all Map steps would return Lists…. and thats just really not what Gremlin is about.

Finally, there really is never a reason you should do a.map(out()) as you probably want to do a.limit(out().limit(1)). map(traversal) its there just for "full consistency" as we have Map,FlatMap,Filter,SideEffect, and Branch "native steps."

Marko.
Reply all
Reply to author
Forward
0 new messages