# Implicit lambda names

**URL:** <https://discuss.kotlinlang.org/t/implicit-lambda-names/16977>\
**Category:** Language Design\
**Created:** [April 5, 2020, 2:59pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977 "2020-04-05T14:59:56Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 5, 2020, 2:59pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/1 "2020-04-05T14:59:56Z")

</div>

## Problem

- As it is partly mentioned in this [topic](https://discuss.kotlinlang.org/t/shorthand-lambda-argument-implicit-names-proposal/2286), using `it` as implicit parameter name leads to 2 problems (one is mentioned in that topic):
  - It can be confusing. So there is advice not to use it there.
  - Furthermore, it can be confusing even for small lambdas: `.forEach { it.run() }` seems less understandable, than `.forEach { student : Person -> student.run(); }` because we could expect `it` as some `Callable`, for example.
    - If you use `it` somewhere inside some more complicated code, the code becomes absolutely unreadable.
    - Using both `.apply` and `it` makes the code unreadable to: `someMap.putIfAbsent(it, element.line)?.apply { someHandler(element, it, this) } `.

  - The second problem is that using `it` in nested lambdas is even more confusing. So it would be great to be able to specify the context of `it`. _[There is a solution for the problem: name the parameter explicit, but there is a better solution]_

* * *

## Solution

This solution can solve both problems.

I propose to be able to use any name as an implicit parameter name. The actual name of the parameter can be got from its usage.

- How that crazy idea can be implemented?
- Compiler can try to resolve all used variables in the lambda. Then, if there is only one unresolved variable, it is the name of the implicit parameter. This would look somehow like `.forEach { student.run() }`.
- This solution provides both laconicism and readability of using of an implicit lambda parameter name.
- I suppose that suggested syntax is the most comfortable for both reading and writing.
- Perhaps, you can use the same name in nested lambdas and get the second again, but that case becomes very rare, and can be solved by highlighting in IDE (as it is already done now for `it`).
- Comparison of the mentioned approaches:  
Predeclaration:

```kotlin
open class Person(val id: Int, val name: String, val parent: String)
class Student(val schoolId: Int, id: Int, name: String, parent: String) : Person(id, name, parent)

```

  - Explicit syntax

```kotlin
ArrayList<Student>()
    .filter { student -> student.schoolId % 2 == 0 }
    .filterNot { person -> person.id == 0 }
    .map { familyMember -> familyMember.parent.toUpperCase() }

```

  - `it` based syntax

```kotlin
ArrayList<Student>()
    .filter { it.schoolId % 2 == 0 }
    .filterNot { it.id == 0 }
    .map { it.parent.toUpperCase() }

```

  - Suggested syntax

```kotlin
ArrayList<Student>()
    .filter { student.schoolId % 2 == 0 }
    .filterNot { person.id == 0 }
    .map { familyMember.parent.toUpperCase() }

```

- Limitations:
  - This approach is perfect for small lambdas when `it` is usually used because a reader can easily resolve its meaning from the context without repeating parameter name (`friend -> friend.call()`). Nevertheless, the given approach is better even in this case: `.map { key[it] }` is worse than `.map { key[authorizatedUser] }`.
  - It can also be used in some cases when `it` can not be used: when lambda (does not tell)/(tells ambiguously)/(tells wrong way) what `it` is: if we used `it` in the previous example, we would think, that `it` is something implementing `Callable`, not a person we phone.
  - But it is still a bad idea to use the feature when the code snippet is so big that it makes the reader to find a declaration of the variable
  - As a temporary result, the object of the proposal has a wider range of usages than `it`, because the reader understands what object it is because of its name, but it is still not as universal as external lambda syntax

- 
# PS
**Unfortunately, implicit naming leads to another big problem: it becomes sensitive to the naming of other variables in other scopes (both internal and external)**. It is possible to use labels to specify the context, but this is a lot less obvious than just using explicit parameters then, so the thing we have to do is
  - Making such variable name start with `$` or some other unused character to
    - Help reader to understand that it is an implicit parameter name
    - Make such implicit names insensitive to usual variables:  
The problem happened when I renamed `key` to `value` because I would try to use external `value` instead of the implicit parameter.

```kotlin
val key = 3
coll.map { value.second }

```

This way that is not the problem anymore:

```kotlin
val key = 3
coll.map { $value.second }

```

becomes

```kotlin
val value = 3
coll.map { $value.second }

```

  - But such names still influence other implicit parameter names, so we could
    - Just not to allow to use same nested implicit names
    - Make them invisible in nested lambdas
    - I choose the second approach because
      - Otherwise, I can not write the lambda without the context and be sure that it is valid because the name can be used somewhere else
      - When we use the `it`, there is the only reserved name, which is also not a very good one for explicit parameters, so I do not have the same problem
      - Furthermore, it is possible to specify which `it` is allowed then (in nested lambdas), but we can not specify the list of names because that can be changed.

    - There is also the third approach: to consider variables starting with `$` as pseudonyms for `it`, so using such variables in nested lambdas should be the same with using `it` in nested lambdas.

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [April 5, 2020, 10:53pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/2 "2020-04-05T22:53:58Z")

</div>

I agree with this answer, given to a similar proposal:

> [@Allow any name in single parameter lambda functions](https://discuss.kotlinlang.org/t/allow-any-name-in-single-parameter-lambda-functions/1724/3):
>
> I’m not sure how allowing to use an arbitrary, undeclared name would be familiar to people coming from any other language, because I haven’t seen this feature anywhere else. In Haskell, the lambda parameter name is explicitly declared, so I’m not sure why this would be familiar to Haskell users. Also, real code is never a single line. If I encountered such a line in an actual program, I’d have to spend a lot of time trying to understand where “name” comes from - is it a variable from an outer s…

Had to search for a while before I could find it 🙂

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 5, 2020, 11:05pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/3 "2020-04-05T23:05:13Z")

</div>

When I tried to find similar topics, I didn’t anything. So I created that. Actually, I had already found mentioned problem before you told me, but now I know that I am not along with the idea. Is what I mentioned at the end a solution of the problem? @tieskedh

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 6:50am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/4 "2020-04-06T06:50:34Z")

</div>

I like the idea but it has a flow with regard to maintenance: if someone later introduces a variable or property in the containing scope, which has the same name as such a lambda variable, the meaning of the variable changes. If the type of the new entity is incompatible it just won’t compile but sometimes it will, and will do something subtly incorrect. I’m my experience, this sort of thing already happens often enough in long-lived projects with enough staff turnover - or anyone making simple human errors!

To avoid that, how about requiring these variables to have some format of name which can only be used in lambdas, e.g., starting with `$` or some character not otherwise used in identifiers?

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [April 6, 2020, 8:31am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/5 "2020-04-06T08:31:16Z")

</div>

```
foos.sumBy{
    $foo.bars.sumBy{
        $bar.intValue
    }.sum()
}

```

or

```
foos.sumBy{
   //$fooBar.doSomething()
    bars.sumBy{
        $fooBar.intValue
    }.sum()
}

```

How wouldn’t it change in the last example?

What would be possible is using the labels:

```
foos.sumBy foos: {
   $foos:fooBar.doSomething()
    bars.sumBy bars: {
        $fooBar.intValue
    }.sum()
}

```

But in this case, I don’t think you gain anything.

For not-nested lambda’s, I do see some value.  
Therefor, I personally wouldn’t mind having implicit lambda names, if and only if a special kind of names are required, such that it’s immediatetly clear that it’s coming from the lambda.

I don’t think I personally would use it, but who knows 😉

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 8:54am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/6 "2020-04-06T08:54:04Z")

</div>

In the second case the existing warning about shadowing variable names would let developers know that there was a possible mistake (just as with standard variable names and scopes), so I think it still works.

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 11:04am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/7 "2020-04-06T11:04:43Z")

</div>

That is what already written in the last sentence. _If I understand you right way._

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 11:13am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/8 "2020-04-06T11:13:08Z")

</div>

As you have already noticed there is a problem with nested lambdas that can be solved by labels. But using labels in such case is definetely worse than just explicit naming. So I suppose forbidding using such variables in nested lambdas to be the right solution.

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 11:50am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/9 "2020-04-06T11:50:22Z")

</div>

> [@zhelenskiy](#):
>
> That is what already written in the last sentence. _If I understand you right way._

Oops, yes, you’re right - I missed that somehow. Sorry!

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 11:53am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/10 "2020-04-06T11:53:16Z")

</div>

> [@zhelenskiy](#):
>
> there is a problem with nested lambdas that can be solved by labels

I think this idea is even _more_ useful in nested lambdas, so I wouldn’t want to see it forbidden there. You could also solve it by treating the first of such a variable in a lambda as an implicit declaration, in which case the compiler can give you the usual “shadowing declaration” warning. I agree that adding labels would make things harder to understand.

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 12:11pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/11 "2020-04-06T12:11:32Z")

</div>

How do you want to guess that it is a shadowing variable, but not just usage of the previous one?

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 12:49pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/12 "2020-04-06T12:49:58Z")

</div>

Hmm, good question.

How about … any lambda which uses such variables must mention exactly one new such variable which doesn’t exist in a containing scope, and that mentioned variable is the implicitly declared variable for the lambda.

If you change the containing scope to add such a variable with a name which matches one the lambda, the lambda no longer mentions a new variable, so you get a compiler error.

If you change the containing scope to remove a variable which is mentioned in the lambda (and is therefore not the implicit one), the lambda now has two new such variables, so you get a compiler error.

Does that work?

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 12:54pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/13 "2020-04-06T12:54:58Z")

</div>

Actually, no. that leads to other problems: the method taking the lambda can be polymorphic, so it can take both `(T) -> X` and `() -> X`, so You would implicitly change the method you call. That is very bad.

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 6, 2020, 1:03pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/14 "2020-04-06T13:03:13Z")

</div>

Well, I’m saying that we define the behaviour to be that the lambda just won’t compile if it mentions any of these `$` variables and doesn’t mention exactly one new one. If you really did mean to have a lambda which does that, which I _guess_ would be unusual (but I may well be wrong) then you have to start the lambda with some `( $_dummy -> ...`.

I’m not sure that would be pleasant and comprehensible to use but I think it would at least have well-defined behaviour which doesn’t change in unreported ways when you change the outer scope.

We might also want to specify that a lambda which contains any such variables is defined not to have an implicit `it`. But I don’t think that’s needed and it would make it more ugly to use such variables inside DSL blocks etc.

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 1:09pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/15 "2020-04-06T13:09:16Z")

</div>

How do you see interal `() -> X` lambdas then? They do not introduce any new variable.  
(I added one more approach to the text)

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 6, 2020, 1:10pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/16 "2020-04-06T13:10:04Z")

</div>

The text has been changed a bit. (Its end)

---

<div class="post-metadata">

**Author:** ![HughG](https://avatars.discourse-cdn.com/v4/letter/h/35a633/32.png) [@HughG](https://discuss.kotlinlang.org/u/HughG)\
**Post date:** [April 7, 2020, 5:51am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/17 "2020-04-07T05:51:14Z")

</div>

Hadn’t thought of that, either. Maybe some syntax which makes it clear that there are no parameters to the lambda, e.g., `{ -> bodyOf($theLambda) }`, where `$theLambda` is an implicit variable from an enclosing lambda, and the rule about having to have exactly one new such variable is changed to “zero new such variables” because of the lone arrow.

That’s kinda ugly but it might do 😉

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 7, 2020, 6:12am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/18 "2020-04-07T06:12:03Z")

</div>

> [@tieskedh](#):
>
> foos.sumBy{ $foo.bars.sumBy{ $bar.intValue }.sum() }

That would be somethinh like

```kotlin
foos.sumBy {
    -> $foo.bars.sumBy{ -> $bar.intValue }.sum()
}

```

Are you that it is what you want? Is such syntax obvious? If so, this should be taken under consideration then.

I think it is better jusr=t to specify such lambda with `$`. Smth like:

```kotlin
foos.sumBy ${
    $foo.bars.sumBy ${ $bar.intValue }.sum()
}

```

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [April 7, 2020, 8:14am UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/19 "2020-04-07T08:14:23Z")

</div>

Oh, no.  
I liked [the reaction after my post](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/6) 😉

---

<div class="post-metadata">

**Author:** ![zhelenskiy](https://avatars.discourse-cdn.com/v4/letter/z/3da27b/32.png) [@zhelenskiy](https://discuss.kotlinlang.org/u/zhelenskiy)\
**Post date:** [April 7, 2020, 3:17pm UTC](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977/20 "2020-04-07T15:17:41Z")

</div>

What do u mean by saying it? I don’t understand it.

[Next page](https://discuss.kotlinlang.org/t/implicit-lambda-names/16977.md?page=2)
