# Finding the first item in a sequence by type requires an extra cast to that type

**URL:** <https://discuss.kotlinlang.org/t/finding-the-first-item-in-a-sequence-by-type-requires-an-extra-cast-to-that-type/4058>\
**Category:** Uncategorized\
**Created:** [August 6, 2017, 8:45am UTC](https://discuss.kotlinlang.org/t/finding-the-first-item-in-a-sequence-by-type-requires-an-extra-cast-to-that-type/4058 "2017-08-06T08:45:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rhdunn](https://avatars.discourse-cdn.com/v4/letter/r/c67d28/32.png) [@rhdunn](https://discuss.kotlinlang.org/u/rhdunn)\
**Post date:** [August 6, 2017, 8:45am UTC](https://discuss.kotlinlang.org/t/finding-the-first-item-in-a-sequence-by-type-requires-an-extra-cast-to-that-type/4058/1 "2017-08-06T08:45:56Z")

</div>

Given a function that returns a sequence of a superclass/interface, such as [1]:

```
fun PsiElement.descendants(): Sequence<PsiElement> {
    return PsiElementWalker(firstChild, PsiElement::getFirstChild).asSequence()
}

```

using first/firstOrNull to find an element of a given class:

```
val module: PsiElement? = children().firstOrNull { e -> e is XQueryModule }
val versionDecl: XQueryVersionDecl? = module?.descendants()?.firstOrNull { e -> e is XQueryVersionDecl } as? XQueryVersionDecl

```

requires an additional cast (as seen in the versionDecl example). That is, expressions of the following forms require an extra cast:

```
val item: T = items.first { e -> e is T } as T
val item: T? = items.firstOrNull { e -> e is T } as? T

```

That is, the `as` is redundant due to the `is` check. It would be useful if Kotlin could infer the type and avoid the duplicated cast. This would be generally applicable to any predicate that checks for a type. This would then support the following:

```
val item: T = items.first { e -> e is T }
val item: T? = items.firstOrNull { e -> e is T }

```

In Java, I can do this by using things like:

```
public interface Sequence<A> {
    <B extends A> B first(Predicate<A> matcher);

    default <B extends A> B first(Class<B> c) {
        return findFirst(c::isInstance);
    }
}

```

and use:

```
T item = items.first(T.class)

```

[1] [https://github.com/rhdunn/xquery-intellij-plugin/blob/master/src/main/java/uk/co/reecedunn/intellij/plugin/core/extensions/PsiElement.kt](https://github.com/rhdunn/xquery-intellij-plugin/blob/master/src/main/java/uk/co/reecedunn/intellij/plugin/core/extensions/PsiElement.kt)

---

<div class="post-metadata">

**Author:** ![jstuyts](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/jstuyts/32/2141_2.png) [@jstuyts](https://discuss.kotlinlang.org/u/jstuyts)\
**Post date:** [August 6, 2017, 9:01am UTC](https://discuss.kotlinlang.org/t/finding-the-first-item-in-a-sequence-by-type-requires-an-extra-cast-to-that-type/4058/2 "2017-08-06T09:01:36Z")

</div>

You are trying to do 2 things with 1 operation: filtering and mapping. Unless you write a custom operator for that, I think it cannot be done with 1 operator.

Kotlin can correctly infer types if you do it like this:

```
val item: T = items.map { e -> e as? T }.filterNotNull().first()
val item: T? = items.map { e -> e as? T }.filterNotNull().firstOrNull()

```

---

<div class="post-metadata">

**Author:** ![pdvrieze](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/pdvrieze/32/1882_2.png) [@pdvrieze](https://discuss.kotlinlang.org/u/pdvrieze)\
**Post date:** [August 6, 2017, 12:52pm UTC](https://discuss.kotlinlang.org/t/finding-the-first-item-in-a-sequence-by-type-requires-an-extra-cast-to-that-type/4058/3 "2017-08-06T12:52:05Z")

</div>

Actually there is a function [filterIsInstance](http://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-is-instance.html) that is the “right” approach - and does both, more efficiently. You can use it as:

```
val items.filterIsInstance<T>().firstOrNull()

```

Of course this means T needs to be concrete, if you have a kclass object you can use that as well as parmeter (rather than using a type parameter).
