13

I'm confused by Kotlin lambda syntax.

At first, I have

.subscribe(
          { println(it) }
          , { println(it.message) }
          , { println("completed") }
      )

which works fine.

Then I moved the onNext to another class called GroupRecyclerViewAdapter which implements Action1<ArrayList<Group>>.

.subscribe(
          view.adapter as GroupRecyclerViewAdapter
          , { println(it.message) }
          , { println("completed") }
      )

However, I got the error:

error

Error:(42, 17) Type mismatch: inferred type is () -> ??? but rx.functions.Action1<kotlin.Throwable!>! was expected
Error:(42, 27) Unresolved reference: it
Error:(43, 17) Type mismatch: inferred type is () -> kotlin.Unit but rx.functions.Action0! was expected

I can fix the error by changing to:

.subscribe(
          view.adapter as GroupRecyclerViewAdapter
          , Action1<kotlin.Throwable> { println(it.message) }
          , Action0 { println("completed") }
      )

Is there a way to write the lambda without specifying a type? (Action1<kotlin.Throwable>, Action0)

Note: subscribe is RxJava method

Edit 1

class GroupRecyclerViewAdapter(private val groups: MutableList<Group>,
                           private val listener: OnListFragmentInteractionListener?) :
RecyclerView.Adapter<GroupRecyclerViewAdapter.ViewHolder>(), Action1<ArrayList<Group>> {
pt2121
  • 11,720
  • 8
  • 52
  • 69

2 Answers2

12

view.adapter as GroupRecyclerViewAdapter part should be lambda func, not Action, since onError and onComplete also lambdas

so, to fix this try:

.subscribe(
          { (view.adapter as GroupRecyclerViewAdapter).call(it) }
          , { println(it.message) }
          , { println("completed") }
      )

with your names (replace Unit with your type)

class GroupRecyclerViewAdapter : Action1<Unit> {
    override fun call(t: Unit?) {
        print ("onNext")
    }
}

with lambdas

val ga = GroupRecyclerViewAdapter()
...subscribe(
    { result -> ga.call(result) },
    { error -> print ("error $error") },
    { print ("completed") })

with actions

...subscribe(
    ga,
    Action1{ error -> print ("error $error") },
    Action0{ print ("completed") })

pick one

Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
vigilancer
  • 1,456
  • 14
  • 15
  • Nope, doesn't work. if it's the case, why my last snippet works then? – pt2121 Jan 24 '16 at 02:08
  • because in last example they all Actions. give me a sec i'll try – vigilancer Jan 24 '16 at 02:16
  • please provide `view.adapter` signature at least. is it really Action1? if it is in my example it should be `(view.adapter as GroupRecyclerViewAdapter).call(it)`, sorry – vigilancer Jan 24 '16 at 02:26
  • Sure. added it. it's Action1 – pt2121 Jan 24 '16 at 02:30
  • in `(view.adapter as GroupRecyclerViewAdapter).call(it)` take a note on `it` part – vigilancer Jan 24 '16 at 02:32
  • what error are you getting after applying my comment? – vigilancer Jan 24 '16 at 02:34
  • `call` per se returns Unit, but `{ (view.adapter as GroupRecyclerViewAdapter).call(it) }` is a lambda – vigilancer Jan 24 '16 at 02:37
  • `isn't compiled` says nothing – vigilancer Jan 24 '16 at 02:38
  • But my `GroupRecyclerViewAdapter` works fine. I'm sorry but the thing is I'm trying to pass some value in `call` (`onNext`). I don't think your edit really answers my question. – pt2121 Jan 24 '16 at 02:52
  • because your question makes no sense. you are not specifying type of lambda, but type of arguments you passing to `.subscribe()`. Since you are confused with lambda syntax I'm correcting you that you cannot pass Action *and* lamba as arguments, you must choose one. – vigilancer Jan 24 '16 at 02:59
  • 2
    Hey guys, did it work or didn't? And where the rule of not using SAM with lambdas has come from? Never heard of that. – voddan Jan 24 '16 at 06:28
  • @voddan not aware if there is an explicit rule for that. but provided code in snippets works. and mixing Actions with lambdas gives syntax error. – vigilancer Jan 24 '16 at 13:51
  • @EntryLevelDev based on the conversation, this is a bug of the compiler. Please fill an issue at https://youtrack.jetbrains.com/issues/KT – voddan Jan 24 '16 at 14:49
  • @voddan I am not sure I understand this enough to file the issue. I still don't quite understand how Kotlin compiler infer type in this case. i'll do some research and might file an issue later. – pt2121 Jan 24 '16 at 14:56
  • @EntryLevelDev information in your question is more than enough for a bug ticket. Note: it is better for an issue to be filed by the one who found the problem because developers may need some additional info about your project, environment, etc. – voddan Jan 24 '16 at 19:15
  • @EntryLevelDev please provide link to created issue, I'll vote it up. experiencing same behaviour. or if you are don't mind I can create one. – vigilancer Jan 25 '16 at 01:05
  • @AndreyElizarov actually, please go ahead creating the issue if you'd like. – pt2121 Jan 25 '16 at 01:13
  • @AndreyElizarov do you mind elaborate more why extending adapter with Action is poor design choice? I'm following https://github.com/JakeWharton/u2020 and I think it's a pretty good idea. – pt2121 Jan 25 '16 at 01:16
  • @voddan just to be clear, bug here is that one cannot mix SAMs with lambdas in arguments of function which expects only SAMS? – vigilancer Jan 25 '16 at 01:20
  • @EntryLevelDev could you point out specific files where did you get idea from? (@AndreyElizarov - me, forgot to change nick) – vigilancer Jan 25 '16 at 01:24
  • @vigilancer https://github.com/JakeWharton/u2020/blob/90610dd9d12a2c7b9885aae4261339ed0d9a1a5f/src/main/java/com/jakewharton/u2020/ui/trending/TrendingAdapter.java I think making the Adapter as a "sink" and letting it auto update a view when data changes is pretty neat. that's the point of using Rx, right? – pt2121 Jan 25 '16 at 01:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101543/discussion-between-entryleveldev-and-vigilancer). – pt2121 Jan 25 '16 at 01:32
2

You have two versions of the subscribe method to choose from:

  • The first (the real one) has the signature subscribe(Action1<ArrayList<Group>>, Action1<Throwable>, Action0).
  • The second version is generated by the Kotlin compiler and has the signature subscribe((ArrayList<Group>>) -> Unit, (Throwable) -> Unit, () -> Unit)

In your code, however, you pass the following parameter types:

subscribe(
    view.adapter as GroupRecyclerViewAdapter, // Action1<Throwable>
    { println(it.message) },  // (Throwable) -> Unit
    { println("completed") } // () -> Unit
)

As you can see, these parameter types satisfy none of the available signatures. The other answer gives you some solutions to your problem. In addition, you can make GroupRecyclerViewAdapter implement the functional type Function1<ArrayList<Group>, Unit> (they're interfaces, too) instead of Action1<ArrayList<Group>>.

Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148