Context Receivers Are Coming to Kotlin!

Sdílet
Vložit
  • čas přidán 13. 04. 2022
  • Kotlin 1.6.20 comes with a new toy: Context Receivers. You can use them to elegantly constrain functions (and more!) to a specific context from which they can be called. Sebastian ( / sebi_io ) helps you figure out what exactly that means: Get a refresher on “receivers” in Kotlin, set yourself up to use the context receivers prototype in your own project, and get all the details about how context receivers work and how they can be used.
    #ContextReceivers #Kotlin #Programming #Development
  • Věda a technologie

Komentáře • 102

  • @PhilippLackner
    @PhilippLackner Před 2 lety +9

    I didn't know I need this

  • @BrianOxleyTexan
    @BrianOxleyTexan Před 2 lety +9

    This is one of the best explanations of a complex feature I've run into. Presentation is clear, gives markers to listener to wait for an explanation of a later thing, shows off clear examples in the left hand code sample. Fantastic!

  • @GakisStylianos
    @GakisStylianos Před 2 lety +40

    Great work Seb. This was quite a long one, must've been hard to get it all right, but I believe you've done a great job!

  • @renascienza.bazarclub
    @renascienza.bazarclub Před 2 lety +29

    The good: can cleanup a lot of code. Imagine what this can do with Android, where we need to inform the Context object everywhere...
    The bad: you can have a function that depends of something external to itself to compile and maybe even work properly (if you have for instance two objects on scope that satisfies the constraint, what is the right one?).
    This can make the code less clear and more cryptic to less experienced Kotlin programmers, or if the function definition is inside a library that is poorly documented. And everything that is tricky to understand or have abuse potential, can be a source of bugs or productivity loss.
    This need to be used wisely.

    • @pablisco
      @pablisco Před 2 lety +2

      > you can have a function that depends of something external to itself to compile
      Isn't that the same if you have unbound parameters?

    • @ChrisB_Crisps
      @ChrisB_Crisps Před 2 lety

      How is "the bad" different from the same function receiving a new parameter? It seems that the compiler will show a compilation error if the function is call without the context (similar to a compiler error when calling a function but missing an argument). This doesn't seem to come from ideas that come from a modern or devops mindset.

    • @renascienza.bazarclub
      @renascienza.bazarclub Před 2 lety

      @@ChrisB_Crisps First things first: change your attitude. Basic respect is the first thing to talk with everyone on internet. If you can't, we are done here.
      Well, this is different from a function receiving a new parameter because in that case, this is *explicit*. You go to the function declaration and everything is there. Nothing is declared somewhere else, nothing is implicit or invisible at first sight.
      Things like multiple context inferences, operator overload, external functions need to be used with care because isn't easy to see at glance. We can use it, but there is a need to be careful.
      Finally, to *professional development* time is money and quality of code matter. We don't actually write code only to machines, but to humans understand. If a programmer is impairing the team, you fire him, not the team.

    • @ChrisB_Crisps
      @ChrisB_Crisps Před 2 lety

      @@renascienza.bazarclub Sorry for talking to you without with bad attitude and for not being respectful which is a basic of interactions.
      I am not sure what are you referring to professional development, quality has to be taken into account but I think that code working and in production can bring more revenue and competitive advantage than a good sonarqube quality score. If a programmer is impairing the team it could be that it simply needs to be coached, mentored or their leadership qualities and reasessed, firing can also cost money. Everyone is a leader, and in almost any cases it's possible to amplify their strengths by finding the right objectives for the right skill.
      I see that you edited your comment.

  • @zhou7yuan
    @zhou7yuan Před 2 lety +20

    receivers in Kotlin
    extension function [2:38]
    receiver effects [3:11]
    lambda in Receivers [4:20]
    `with` function[5:40]
    nesting `with` calls[6:17]
    context: motivation [7:10]
    (logger example) [7:42]
    (what signature expressed is different) [10:40]
    - ✔can be called wherever a logger is present
    - ❌call me on a logger
    like extension function: context receiver as anonymous parameter [12:09]
    multiple context receiver [12:49]
    issue: naming conflict [14:11]
    - labeled `this` statement [15:12]
    define interface for context[16:19]
    calling convention: cannot call like attributes like extension function [19:04]
    context on class [20:33]
    context useful if you don't control receiver [23:05]
    - operator overloading `+` with context
    usecases [27:21]
    transaction api [27:29]
    DSL [27:58]
    Android: measurements (dp) [28:20]
    cascade from parent object: when instanciating object [29:08]

  • @khaled.noordin
    @khaled.noordin Před 2 lety +8

    Thanks seb for delivering content. I ❤ kotlin.

  • @wusibeaumontmahoney1278
    @wusibeaumontmahoney1278 Před 2 lety +4

    You are an excellent developer advocate for kotlin, keep up the great work.

    • @Kotlin
      @Kotlin  Před 2 lety +2

      True! Sebastian is great!

  • @prateekkocher8540
    @prateekkocher8540 Před 2 lety +7

    Love watching and learning abt new toys in Kotlin thanks to your fun yet informative videos ❤️

    • @Kotlin
      @Kotlin  Před 2 lety +2

      We are glad it helped!

  • @DerTroglodyt
    @DerTroglodyt Před 2 lety +11

    Exceptional well explained. Thanks a lot.

  • @gekylafas
    @gekylafas Před 2 lety +1

    The EUR + USD example was quite enlightening, kudos!

  • @TheMisterGege1
    @TheMisterGege1 Před 2 lety +1

    Thanks for the great introduction to context receivers. Really looking forward to using them in production one day. Great stuff! And thanks to the Kotlin team, they’re doing an amazing job!

  • @matthieulucas9059
    @matthieulucas9059 Před 2 lety +5

    A lifesaver for DSLs!

  • @hojjatmashal4823
    @hojjatmashal4823 Před rokem

    The most intriguing part to me is how it could replace a great part of a DI framework to decouple our code from a third party DI framework!

  • @omkumar0900
    @omkumar0900 Před 2 lety +10

    Line 15 at 5:30, return type of lambda should be String
    fun printTransformedGreeting(transform: String.() -> String)
    Otherwise it will only print "Unit" instead of sarcastic greeting like "hEllO wORld!".

    • @sebastianaigner9125
      @sebastianaigner9125 Před 2 lety +9

      Oof! 😅 You're of course right - you can even see the inlay hint that says the type of `transformed` is Unit. Thanks for pointing that out!

    • @LostMekkaSoft
      @LostMekkaSoft Před 2 lety

      @@sebastianaigner9125 similarly, the json dsl also unintentionally calls put(this, Unit) on line 10 ^^

  • @sheenfabile9460
    @sheenfabile9460 Před rokem

    I cant believe this video lenght is 30+ mins. It feels like 5 mins when you get what he is saying. Thanks Sebbbbbbb!

  • @rodneymkay
    @rodneymkay Před 2 lety +5

    Love the thumbnail xD Bet that was fun to make xD

  • @alexgorodecky1661
    @alexgorodecky1661 Před 6 měsíci

    Implicits in Kotlin! Congrats! The beginning of the end!

  • @xetra1155
    @xetra1155 Před 2 lety +3

    Extremely good explaination!

  • @CodyCasterline
    @CodyCasterline Před 2 lety +40

    This looks cool!
    But … why do I have to make a LoggerContext type to give Logger a name "logger". If you're introducing this new syntax, couldn't you just specify context(logger: Logger) and save everyone that boilerplate? (Kotlin is usually so good at saving me from writing boilerplate!). 😊

    • @thebigboi5357
      @thebigboi5357 Před 2 lety +3

      exactly my thoughts! Having named contexts seems to be the obvious solution, since it is concise and follows existing Kotlin syntax

    • @radosawjuszczyk638
      @radosawjuszczyk638 Před 2 lety +1

      I was about to put the same comment!

    • @radosawjuszczyk638
      @radosawjuszczyk638 Před 2 lety +4

      but that would look like we can put `context(logger1: Logger, logger2: Logger)` which would create ambiguity in nested `with`s

    • @CodyCasterline
      @CodyCasterline Před 2 lety +1

      @@radosawjuszczyk638 So just have the compiler check for and disallow that case.

    • @GakisStylianos
      @GakisStylianos Před 2 lety +1

      In the KEEP they mention such considerations. Thing is, that would be a backwards compatible change, so it may happen.

  • @cisimon7
    @cisimon7 Před 2 lety +1

    Well explained, thanks Seb. I think I have a couple of ideas on other ways to apply this. Experimentation time, may have to wait for compose to be upgraded to use Kotlin 1.6.20

  • @mihun4ik
    @mihun4ik Před 2 lety +1

    Nice one. Thank you for the good guide!
    I guess context receivers is a great feature that could influence DI frameworks.
    Also, developers will need to learn how NOT to use context receivers.
    It is a thing with elegant implementation (thanks to KEEP team) that I was waiting for a long time.

  • @islamfaridmadbouly
    @islamfaridmadbouly Před 2 lety +1

    Great Explanation. Thank you!

  • @qbalsdon
    @qbalsdon Před 2 lety

    Thanks for this! I see this as really useful when you need a dependency for ONE method in a class and don't want to inject a new object just for that one method, or don't want to store references in that class. This come with great power, and we all know what comes with great power... great electric bills

  • @OlegGolubev_yolo
    @OlegGolubev_yolo Před 2 lety

    Got this in mind for 3 years, glad it coming! :P

  • @damercy
    @damercy Před 2 lety +2

    loved it! ❤️

  • @user-no9yr1ze1d
    @user-no9yr1ze1d Před 2 lety +1

    Nice one. Thanks for video

  • @mohanaggarwal4058
    @mohanaggarwal4058 Před 2 lety +2

    Thanks a lot sir for this tutorial 😊😊👍

  • @skytech2501
    @skytech2501 Před 2 lety +1

    Kotlin introduces Coroutines to solve "callback hell" and introduces with(), let(), apply() for "callback hell" !!

  • @larsartmann
    @larsartmann Před 2 lety +1

    Very good video!

  • @matthewgiallourakis7645

    Can't wait for this feature to be added to the JS target! This is going to make writing Kotlin DSLs for javascript libraries so much nicer 🙏

  • @holloszaboakos
    @holloszaboakos Před 2 lety +1

    Some suggestion for the feature: There should be a "with function" with vararg parameters so in case of multiple context we don't have to embed that many times. It would look like with(logger, notification){ ... }. Also in the context function we should be capable to name the contexts like: context(Logger as logger, Notification as notification) or context(logger : Logger, notification : Notification). This would render these boxing interfaces unnecessary. Why isn't this an annotation by the way? Also if there is two interfaces in context(...) and one class implements both, an instance of that class should be enough.

  • @kee1o
    @kee1o Před rokem

    great explanation

  • @MagnumRocha87
    @MagnumRocha87 Před 2 lety +1

    wow, this would unblocking a lot of ideas, and clean a lot of code as well 😆
    let's go Kotlin 💪

  • @alexanderataman7836
    @alexanderataman7836 Před rokem

    Great explained! Thank You! Context replaces the use cases of dependency injection libraries?

  • @TheMisterGege1
    @TheMisterGege1 Před 2 lety +3

    This is great for functional programming. We can write suspend functions that execute side effects within the provided context. No need to wrap these funs in classes anymore and goobye invoke operator.

  • @jameswhitehead74
    @jameswhitehead74 Před 2 lety +2

    I'm not quite sold on this yet. I'm really struggling to come up with a "real world" use-case for this feature where I wouldn't create a class and use constructor dependency injection instead. Interested to see how this evolves with the community response.

  • @skotch_izolentovich
    @skotch_izolentovich Před 2 lety +1

    Woooooow, this is amaing!

  • @thanosfisherman
    @thanosfisherman Před měsícem +1

    Huge spaghetti enabler

  • @AlbertBikeev
    @AlbertBikeev Před rokem

    That's freaking great! Given that you can have generic parameters passed to Context receivers it's practically Typeclasses! Can't wait for it's stabilisation and adoption by library authors!

  • @tomislavhoman3035
    @tomislavhoman3035 Před rokem

    Hmm, seems like it could help making dependency injection to functions when doing functional programming a bit cleaner

  • @dmytrooleinichenko9865
    @dmytrooleinichenko9865 Před rokem +1

    It is looks like analog of scala implicit/given feature

  • @similartoself4750
    @similartoself4750 Před 2 lety +5

    Looks promising for DI and DSLs. I think usage outside of those two will most likely lead to horrible code though.

  • @ScottBecker
    @ScottBecker Před 2 lety +3

    Nice! Is there a way to flatten nested with statements into a single with block?

    • @markvedder1121
      @markvedder1121 Před 2 lety

      No. But as he says at 13:56 there might be in the future.

  • @a.accioly
    @a.accioly Před 2 lety +1

    I like where this is going, we definitively need implicit parameters, but... I'm partial to Scala 3 way of doing things. Instead of context() adding a separate argument list + with() changing the scope of "this", Scala 3 added 2 keywords: "given" declares an implicit instance and the keyword "using" is used when implicit parameters are expected (both can be named or anonymous). Of course that Scala being Scala does way more than context receivers, but I l think that their way is a little bit cleaner. As it is, it feels like Kotlin is reusing "with" for something that it really shouldn't be used for.

  • @renecadenas3610
    @renecadenas3610 Před 2 lety +1

    It sounds like a kind of Scala feature called "Implicit parameters". But in this case, with too boilerplate. 🤔

  • @kawthooleidevelopers
    @kawthooleidevelopers Před 11 měsíci

    Is there any comprehensive Kotlin Ktor tutorial that cover advanced topics and best practices? I can only time basic api and basic authentication

  • @user-jz9dm9xr2n
    @user-jz9dm9xr2n Před 2 lety

    Spring framework to every house)

  • @J1oTTa
    @J1oTTa Před 2 lety +1

    kotlin is love S2

  • @AlanDarkworld
    @AlanDarkworld Před 2 lety

    First of all: very nice and instructive video! I generally like the idea of context receivers, but I can already tell that people will sprinkle them around everywhere for no good reason. What bugs me a little is that we have yet another soft keyword (context) that could have been an annotation. Also, why is it that we don't have to write "::class" after the class name when declaring the context type? Did someone figure out after all that the class name alone might be enough to refer to the class, without needing the rather ugly ::class construct? ;)

  • @daveg1159
    @daveg1159 Před 2 lety +5

    with(logger, notificationSender) {}

  • @shumymikaball
    @shumymikaball Před 2 lety

    I would love to see this as a native DI for Kotlin. But needs to improve in some parts.

  • @AndreyDerkach8
    @AndreyDerkach8 Před 2 lety

    why is it available only for JVM? Any plans to move it to JS ?

  • @quidryan
    @quidryan Před 2 lety

    Is that a laptop on top of the gray box on top of the bookcase? It's stressing me out 😬.

  • @yektadev
    @yektadev Před 2 lety

    This looks so clean! I'd love to see it being added to the language. It only can make things confusing when it's used outside of what it's meant to be used for, but that's also true for any other feature and I wouldn't consider it a downside.

  • @user-cm4ce5fh4q
    @user-cm4ce5fh4q Před 8 měsíci

    good

  • @nymexe
    @nymexe Před 10 měsíci

    Hmm. After enabling the context receivers feature decompiler is not working. The decompiler is throwing this exception: java.lang.UnsupportedOperationException: Unsupported receiver value: ExampleScope: Ctx { class ContextAppliedClass }

  • @hun2579
    @hun2579 Před 8 měsíci

    Is it kind of DI for function?

  • @LA-fb9bf
    @LA-fb9bf Před 2 lety +18

    Proposal: context(Loggercontext l, Notificationcontext c) and then access it with l. or c.

    • @notkamui9749
      @notkamui9749 Před 2 lety +4

      this !
      and also, add parameters to the `with`function, so that we can give all the contexts needed, instead of nesting `with` calls

    • @pawewodarczyk1546
      @pawewodarczyk1546 Před 2 lety +7

      Almost, because in Kotlin parameter labels should be on the left side :)
      context(logger: Logger, notificationSender: NotificationSender)

    • @GakisStylianos
      @GakisStylianos Před 2 lety +1

      You can read the KEEP about this topic

  • @tenminutetokyo2643
    @tenminutetokyo2643 Před 2 lety

    Ah, IKEA.

  • @alxjones
    @alxjones Před 2 lety

    This just seems like implicits with extra steps. Why not just implement implicits? What benefit do context receivers have that make them work the extra boilerplate?

  • @ryansgot
    @ryansgot Před 2 lety +1

    The presenter did a good job presenting the topic. However, this feature looks like an attempt to make Kotlin both less readable and less efficient. As a dev manager and tech lead, I can only imagine what atrocities my team will create with this feature. The dependency injection use case makes sense, and the plus infix operator is pretty cool. However, I wonder whether the convenience context receivers provides is worth the cost of the confusion that will result.

    • @johnf419
      @johnf419 Před 2 lety

      Context receivers are what “with” should have been
      I never understood why there was a “with” and “run” where “with” doesn’t return Unit
      In my Android code I use “with(binding)” as a single expression function for view methods but just adding “context(binding)” would be nicer and less confusing to devs that don’t know why the complier is saying return type does match expression
      However, I haven’t finish the presentation but it doesn’t it will work with overridden functions like lifcycle methods

  • @cularu1
    @cularu1 Před rokem

    with() should receive multiple parameters.

  • @Yazon2006
    @Yazon2006 Před 2 lety

    Can't enable it for android project.

  • @user-jw1tb2ec9w
    @user-jw1tb2ec9w Před rokem

    How to solve the error?
    `The feature "context receivers" is experimental and should be enabled explicitly`

  • @udhayarajan_m
    @udhayarajan_m Před 2 lety

    Sorry android Developers we need to escape context too like the one we used with object as `object` and now context as `context`

  • @senk0n
    @senk0n Před 2 lety

    why dont just: with(firstContext, secondContext) { ... 🤔

  • @nickreid4650
    @nickreid4650 Před 2 lety +3

    I fundamentally disagree with the idea of adding even more anonymous variables.

  • @vadim-zuev
    @vadim-zuev Před 2 lety +1

    So "context" is gonna be a keyword and cannot be used as a field name anymore? God help us Android devs...

  • @RhexGomez
    @RhexGomez Před 2 lety

    I appreciate the effort for building such feature but after seeing the amount of work just to do the store(String, Logger, NotificationSender) it's too much.

  • @johnokpo4068
    @johnokpo4068 Před 2 lety

    Please 🙏 I have trying to get my app to come up when my phone boots completely but I haven't been able to achieve this, please do you know of any way or material that will help please I will be gland to check it up. Thanks

  • @kamertonaudiophileplayer847

    Swift.

  • @buszi_
    @buszi_ Před 2 lety

    My feedback at this point:
    1. this "context" keyword could be used as a keyword for a function parameter, I think it would be far nicer in the code and we could still use the names of those objects in the code of this function
    2. context receivers would be optional, so you could still just pass this context object as a function parameter, this would not force us to use function that uses context receivers within "with" blocks when it is not necessary
    3. I don't really like the idea of wrapping everything into interfaces (the problem in the part 2 of this video), why wouldn't we just use named context receivers, so like "context(name: Type)" and then we don't have resolution errors within the function code, I know that it would not let us to call the object as a receiver (so we would need to call "name.foo()" instead of just "foo()") but I would prefer it this way instead of forcing us to wrap everything in additional interfaces

  • @CrapE_DM
    @CrapE_DM Před 2 lety

    I think partial function application is better. I've been against this since I first heard about it. It SEEMS simple and elegant, but it's not, really.

  • @khanra17
    @khanra17 Před rokem

    Why making kotlin ugly ?

  • @cryzz0n
    @cryzz0n Před 2 lety

    Thanks for the great introduction to context receivers. Really looking forward to using them in production one day. Great stuff! And thanks to the Kotlin team, they’re doing an amazing job!