Skip to content

Commit 39fdd6c

Browse files
authored
remove traversal compat (#374)
* improve compat * more compat improvements
1 parent eca283c commit 39fdd6c

File tree

4 files changed

+73
-40
lines changed

4 files changed

+73
-40
lines changed

traversal/src/main/scala/overflowdb/traversal/Implicits.scala

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,31 @@ trait Implicits {
77
type Traversal[+A] = Iterator[A]
88
implicit def jIteratortoTraversal[A](jiterator: java.util.Iterator[A]): Iterator[A] = jiterator.asScala
99

10-
implicit def toTraversalSugarExt[A](iter: Iterator[A]): TraversalSugarExt[A] = new TraversalSugarExt(iter)
11-
implicit def toTraversalLogicExt[A](iter: Iterator[A]): TraversalLogicExt[A] = new TraversalLogicExt(iter)
12-
implicit def toTraversalFilterExt[A](iter: Iterator[A]): TraversalFilterExt[A] = new TraversalFilterExt(iter)
13-
14-
implicit def toTraversalTrackingExt[A](iter: Iterator[A]): TraversalTrackingExt[A] = new TraversalTrackingExt(iter)
15-
implicit def toRepeatTraversalExt[A](iter: Iterator[A]): TraversalRepeatExt[A] = new TraversalRepeatExt(iter)
16-
17-
implicit def iterableToTraversal[A](iterable: IterableOnce[A]): Iterator[A] = iterable.iterator
18-
implicit def toNodeTraversal[A <: Node](traversal: Iterator[A]): NodeTraversal[A] =
19-
new NodeTraversal[A](traversal)
20-
21-
implicit def toEdgeTraversal[A <: Edge](traversal: Iterator[A]): EdgeTraversal[A] =
22-
new EdgeTraversal[A](traversal)
23-
24-
implicit def toElementTraversal[A <: Element](traversal: Iterator[A]): ElementTraversal[A] =
25-
new ElementTraversal[A](traversal)
10+
implicit def toTraversalSugarExt[A](iter: IterableOnce[A]): TraversalSugarExt[A] = new TraversalSugarExt(
11+
iter.iterator
12+
)
13+
implicit def toTraversalLogicExt[A](iter: IterableOnce[A]): TraversalLogicExt[A] = new TraversalLogicExt(
14+
iter.iterator
15+
)
16+
implicit def toTraversalFilterExt[A](iter: IterableOnce[A]): TraversalFilterExt[A] = new TraversalFilterExt(
17+
iter.iterator
18+
)
19+
20+
implicit def toTraversalTrackingExt[A](iter: IterableOnce[A]): TraversalTrackingExt[A] = new TraversalTrackingExt(
21+
iter.iterator
22+
)
23+
implicit def toRepeatTraversalExt[A](iter: IterableOnce[A]): TraversalRepeatExt[A] = new TraversalRepeatExt(
24+
iter.iterator
25+
)
26+
27+
implicit def toNodeTraversal[A <: Node](traversal: IterableOnce[A]): NodeTraversal[A] =
28+
new NodeTraversal[A](traversal.iterator)
29+
30+
implicit def toEdgeTraversal[A <: Edge](traversal: IterableOnce[A]): EdgeTraversal[A] =
31+
new EdgeTraversal[A](traversal.iterator)
32+
33+
implicit def toElementTraversal[A <: Element](traversal: IterableOnce[A]): ElementTraversal[A] =
34+
new ElementTraversal[A](traversal.iterator)
2635

2736
implicit def toNodeOps[N <: Node](node: N): NodeOps[N] = new NodeOps(node)
2837

traversal/src/main/scala/overflowdb/traversal/Traversal.scala

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,64 @@ import scala.collection.immutable.ArraySeq
1616
import scala.jdk.CollectionConverters._
1717
import scala.reflect.ClassTag
1818

19-
class TraversalSugarExt[A](val iterator: Iterator[A]) extends AnyVal {
19+
class TraversalSugarExt[A](val iter: Iterator[A]) extends AnyVal {
2020
type Traversal[A] = Iterator[A]
2121

2222
/** Execute the traversal and convert the result to a list - shorthand for `toList` */
2323
@Doc(info = "Execute the traversal and convert the result to a list - shorthand for `toList`")
24-
def l: List[A] = iterator.toList
24+
def l: List[A] = iter.toList
25+
26+
/** group elements and count how often they appear */
27+
@Doc(info = "group elements and count how often they appear")
28+
def groupCount[B >: A]: Map[B, Int] =
29+
groupCount(identity[A])
30+
31+
/** group elements by a given transformation function and count how often the results appear */
32+
@Doc(info = "group elements by a given transformation function and count how often the results appear")
33+
def groupCount[B](by: A => B): Map[B, Int] = {
34+
val counts = mutable.Map.empty[B, Int].withDefaultValue(0)
35+
iter.foreach { a =>
36+
val b = by(a)
37+
val newValue = counts(b) + 1
38+
counts.update(b, newValue)
39+
}
40+
counts.to(Map)
41+
}
42+
43+
def groupBy[K](f: A => K): Map[K, List[A]] = l.groupBy(f)
44+
def groupMap[K, B](key: A => K)(f: A => B): Map[K, List[B]] = l.groupMap(key)(f)
45+
def groupMapReduce[K, B](key: A => K)(f: A => B)(reduce: (B, B) => B): Map[K, B] = l.groupMapReduce(key)(f)(reduce)
46+
47+
/** Execute the traversal and return a mutable.Set (better performance than `immutableSet` and has stable iterator
48+
* order)
49+
*/
50+
def toSetMutable[B >: A]: mutable.LinkedHashSet[B] = mutable.LinkedHashSet.from(iter)
2551

26-
/** Execute the traversal and return a mutable.Set (better performance than `immutableSet`) */
27-
def toSetMutable[B >: A]: mutable.Set[B] = mutable.Set.from(iterator)
52+
/** Execute the traversal and convert the result to an immutable Set. */
2853

29-
/** Execute the traversal and convert the result to an immutable Set */
30-
def toSetImmutable[B >: A]: Set[B] = iterator.toSet
54+
def toSetImmutable[B >: A]: Set[B] = iter.toSet
3155

3256
/** Execute the traversal without returning anything */
3357
@Doc(info = "Execute the traversal without returning anything")
3458
def iterate(): Unit =
35-
while (iterator.hasNext) iterator.next()
59+
while (iter.hasNext) iter.next()
3660

3761
def countTrav: Traversal[Int] =
38-
Iterator.single(iterator.size)
62+
Iterator.single(iter.size)
3963

40-
def head: A = iterator.next()
64+
def head: A = iter.next()
4165

42-
def headOption: Option[A] = iterator.nextOption()
66+
def headOption: Option[A] = iter.nextOption()
4367

4468
def last: A = {
45-
iterator.hasNext
46-
var res = iterator.next()
47-
while (iterator.hasNext) res = iterator.next()
69+
iter.hasNext
70+
var res = iter.next()
71+
while (iter.hasNext) res = iter.next()
4872
res
4973
}
5074

5175
def lastOption: Option[A] =
52-
if (iterator.hasNext) Some(last) else None
76+
if (iter.hasNext) Some(last) else None
5377

5478
/** casts all elements to given type note: this can lead to casting errors
5579
*
@@ -58,33 +82,33 @@ class TraversalSugarExt[A](val iterator: Iterator[A]) extends AnyVal {
5882
*/
5983
@Doc(info = "casts all elements to given type")
6084
def cast[B]: Traversal[B] =
61-
iterator.asInstanceOf[Traversal[B]]
85+
iter.asInstanceOf[Traversal[B]]
6286

6387
/** collects all elements of the given class (beware of type-erasure) */
6488
@Doc(info = "collects all elements of the provided class (beware of type-erasure)")
6589
def collectAll[B](implicit ev: ClassTag[B]): Traversal[B] =
66-
iterator.filter(ev.runtimeClass.isInstance).asInstanceOf[Traversal[B]]
90+
iter.filter(ev.runtimeClass.isInstance).asInstanceOf[Traversal[B]]
6791

6892
/** Deduplicate elements of this traversal - a.k.a. distinct, unique, ... */
6993
@Doc(info = "deduplicate elements of this traversal - a.k.a. distinct, unique, ...")
7094
def dedup: Traversal[A] =
71-
iterator.distinct
95+
iter.distinct
7296

7397
/** deduplicate elements of this traversal by a given function */
7498
@Doc(info = "deduplicate elements of this traversal by a given function")
7599
def dedupBy(fun: A => Any): Traversal[A] =
76-
iterator.distinctBy(fun)
100+
iter.distinctBy(fun)
77101

78102
/** sort elements by their natural order */
79103
@Doc(info = "sort elements by their natural order")
80104
def sorted[B >: A](implicit ord: Ordering[B]): Seq[B] = {
81-
(iterator.to(ArraySeq.untagged): ArraySeq[B]).sorted
105+
(iter.to(ArraySeq.untagged): ArraySeq[B]).sorted
82106
}
83107

84108
/** sort elements by the value of the given transformation function */
85109
@Doc(info = "sort elements by the value of the given transformation function")
86110
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Seq[A] =
87-
iterator.to(ArraySeq.untagged).sortBy(f)
111+
iter.to(ArraySeq.untagged).sortBy(f)
88112

89113
/** Print help/documentation based on the current elementType `A`. Relies on all step extensions being annotated with
90114
* \@Traversal / @Doc Note that this works independently of tab completion and implicit conversions in scope - it

traversal/src/main/scala/overflowdb/traversal/TraversalSource.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ class TraversalSource(graph: Graph) {
1717
graph.nodes(ids: _*).asScala.asInstanceOf[Traversal[NodeType]]
1818

1919
def label(label: String): Traversal[Node] =
20-
graph.nodes(label).asScala
20+
this.labelTyped[Node](label)
2121

2222
def hasLabel(label: String): Traversal[Node] =
23-
this.label(label)
23+
this.labelTyped[Node](label)
2424

2525
def labelTyped[A <: Node](label: String): Traversal[A] =
26-
this.label(label).asInstanceOf[Traversal[A]]
26+
InitialTraversal.from[A](graph, label)
2727

2828
/** Start traversal with all nodes that have given property value */
2929
def has(property: Property[_]): Traversal[Node] = {

traversal/src/main/scala/overflowdb/traversal/package.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ package object traversal extends Implicits {
1010
* method calls and a `match` without @switch 2) no additional `map` step that iterates and creates yet another
1111
* iterator
1212
*/
13-
def toScalaAs[B]: IterableOnce[B] =
13+
def toScalaAs[B]: Iterator[B] =
1414
new JIteratorCastingWrapper[B](jIterator)
1515
}
1616

0 commit comments

Comments
 (0)