Hi Yura, welcome to the dev list and thanks for offering this thought for
discussion.

> wouldn't it be nice to make Gremlin (or rather GLVs) a bit more type safe?

You mention GLVs and I'd say that the choice to be more type safe would
rest on the level of type safety features the language allows. If a
language has type safety measures, it's nice when you can utilize them.
I'll assume that you're talking about Java mostly though given your
examples and say that we had a number of discussions around this in the
early days of TinkerPop 3.x (which I don't remember the details of) and
ultimately we went with what we have. My gut reaction to a complex
inherited interface system is a bit on the repulsive side given some
experience with TinkerPop 2.x and the weave of interfaces we had there
which Marko and I vowed not to repeat. :)

With your example with by() I'm not sure it fully solves the problem you
pose though because steps that support by() don't always support all
overloads of by(). And then you have other modulators, like with() which
you might mix with by() for some steps but not others. Before you know it
there will be a mad mix of different Traversal interfaces species (i.e. see
the Traverser hierarchy which almost no one understands but at least is
manageable and fits its purpose) with lots of deprecation from version to
version. Maybe I'm envisioning it wrong, but it seems like sacrificing that
portion of type safety for a clean interface hierarchy is a good choice.



On Tue, Aug 14, 2018 at 3:46 PM [email protected] <[email protected]>
wrote:

> Hello guys,
>
> I have small question to discuss (sorry if it was already brought up,
> couldn't find it on the lists) - wouldn't it be nice to make Gremlin (or
> rather GLVs) a bit more type safe?
> Lets consider Gremlin java for example. After each step we return
> GraphTraversal which contains all available Gremlin steps. So we can write
> something like 'g.V().out().by("name")' which will produce CCE. What if we
> would return not GraphTraversal (with all steps) but rather interface with
> subset of steps which are relevant after last one.
> For example after Modulating steps return Traversal with common steps and
> By steps:
>
> default <E2> ByModulatingGraphTraversal<S, Map<String, E2>> project(final
> String projectKey, final String... otherProjectKeys) {
>         ...
>         return (ByModulatingGraphTraversal) this.asAdmin().addStep(new
> ProjectStep(...));
> }
>
> where:
>
> interface BaseWithByTraversal extends BaseGraphTraversal,
> ByModulatingGraphTraversal {}
>
> interface BaseGraphTraversal<S, E> extends Traversal<S, E> {
>     // common steps
> }
>
> interface ByModulatingGraphTraversal<S, E> {
>     // by stesps
>     default BaseWithByTraversal<S, E> by() { ... }
>
>     default BaseWithByTraversal<S, E> by(final Traversal<?, ?> traversal)
> { ... }
>     ...
> }
>
> or even:
> default <E2, G extends BaseGraphTraversal<S, E2> &
> ByModulatingTraversal<S, E2>> G project...
>
> It can be useful in several cases:
> 1) by modulating steps -> By steps
> 2) order -> By (with order direction)
> 3) configuring steps -> with + common steps
> 4) addE -> to/from + common
> 5) io -> read / write
> 6) path -> from/to + common
> 7) ...
>
> I realize that this is breaking (destroying?) change with relatively low
> benefit. So maybe at least it is something to consider for TinkerPop4?
>
> Thanks and regards,
> -Yura
>
> P.S. sorry for poorly formatted long message
> P.S.S. we have VerificationStrategies but its run time vs compile time
> P.S.S.S. this question was inspired by jOOQ (https://github.com/jOOQ/jOOQ)
> which allows to write type safe SQL in Java
>
>

Reply via email to