Context Receivers Are Coming to Kotlin!

Поділитися
Вставка
  • Опубліковано 13 кві 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
  • Наука та технологія

КОМЕНТАРІ • 102

  • @PhilippLackner
    @PhilippLackner 2 роки тому +11

    I didn't know I need this

  • @BrianOxleyTexan
    @BrianOxleyTexan 2 роки тому +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!

  • @zhou7yuan
    @zhou7yuan 2 роки тому +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]

  • @GakisStylianos
    @GakisStylianos 2 роки тому +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 2 роки тому +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 2 роки тому +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 2 роки тому

      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 2 роки тому

      @@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 2 роки тому

      @@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.

  • @Talaria.School
    @Talaria.School 2 роки тому +8

    Thanks seb for delivering content. I ❤ kotlin.

  • @wusibeaumontmahoney1278
    @wusibeaumontmahoney1278 2 роки тому +4

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

    • @Kotlin
      @Kotlin  2 роки тому +2

      True! Sebastian is great!

  • @prateekkocher8540
    @prateekkocher8540 2 роки тому +7

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

    • @Kotlin
      @Kotlin  2 роки тому +2

      We are glad it helped!

  • @gekylafas
    @gekylafas 2 роки тому +1

    The EUR + USD example was quite enlightening, kudos!

  • @DerTroglodyt
    @DerTroglodyt 2 роки тому +11

    Exceptional well explained. Thanks a lot.

  • @matthieulucas9059
    @matthieulucas9059 2 роки тому +5

    A lifesaver for DSLs!

  • @hojjatmashal4823
    @hojjatmashal4823 Рік тому

    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!

  • @TheMisterGege1
    @TheMisterGege1 2 роки тому +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!

  • @omkumar0900
    @omkumar0900 2 роки тому +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 2 роки тому +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 2 роки тому

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

  • @aniruddhasen8801
    @aniruddhasen8801 Місяць тому

    I was with you in the first half . . . but when you started adding `LoggerContext`, `NotificationContext`, adding more objects to the `main()` function, and then extracting the logging call to a separate context received function . . . I started to think, _". . . Honestly, at this point, I don't mind adding the logger and notification sender as parameters to my function."_
    If the point of this is to simplify code, then you've definitely missed the runway.
    *Edit:* Though, I'm still wrapping my head around 'em, the transaction & JSON examples helped clarify & justify the use of context receivers. More exploration, investigation, deeper inspection, consideration, and contemplation is definitely needed (from my end, that is).

  • @sheenfabile9460
    @sheenfabile9460 Рік тому

    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 2 роки тому +5

    Love the thumbnail xD Bet that was fun to make xD

  • @CodyCasterline
    @CodyCasterline 2 роки тому +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 2 роки тому +3

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

    • @radosawjuszczyk638
      @radosawjuszczyk638 2 роки тому +1

      I was about to put the same comment!

    • @radosawjuszczyk638
      @radosawjuszczyk638 2 роки тому +4

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

    • @CodyCasterline
      @CodyCasterline 2 роки тому +1

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

    • @GakisStylianos
      @GakisStylianos 2 роки тому +1

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

  • @skytech2501
    @skytech2501 2 роки тому +1

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

  • @qbalsdon
    @qbalsdon 2 роки тому

    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

  • @mihun4ik
    @mihun4ik 2 роки тому +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.

  • @MagnumRocha87
    @MagnumRocha87 2 роки тому +1

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

  • @cisimon7
    @cisimon7 2 роки тому +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

  • @matthewgiallourakis7645
    @matthewgiallourakis7645 2 роки тому

    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 🙏

  • @xetra1155
    @xetra1155 2 роки тому +3

    Extremely good explaination!

  • @holloszaboakos
    @holloszaboakos 2 роки тому +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.

  • @AlbertBikeev
    @AlbertBikeev 2 роки тому

    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!

  • @OlegGolubev_yolo
    @OlegGolubev_yolo 2 роки тому

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

  • @TheMisterGege1
    @TheMisterGege1 2 роки тому +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.

  • @LA-fb9bf
    @LA-fb9bf 2 роки тому +18

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

    • @notkamui9749
      @notkamui9749 2 роки тому +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 2 роки тому +7

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

    • @GakisStylianos
      @GakisStylianos 2 роки тому +1

      You can read the KEEP about this topic

  • @mohanaggarwal4058
    @mohanaggarwal4058 2 роки тому +2

    Thanks a lot sir for this tutorial 😊😊👍

  • @jameswhitehead74
    @jameswhitehead74 2 роки тому +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.

  • @islamfaridmadbouly
    @islamfaridmadbouly 2 роки тому +1

    Great Explanation. Thank you!

  • @daveg1159
    @daveg1159 2 роки тому +5

    with(logger, notificationSender) {}

  • @damercy
    @damercy 2 роки тому +2

    loved it! ❤️

  • @tomislavhoman3035
    @tomislavhoman3035 Рік тому

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

  • @user-no9yr1ze1d
    @user-no9yr1ze1d 2 роки тому +1

    Nice one. Thanks for video

  • @yektadev
    @yektadev 2 роки тому

    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.

  • @a.accioly
    @a.accioly 2 роки тому +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.

  • @dmytrooleinichenko9865
    @dmytrooleinichenko9865 Рік тому +1

    It is looks like analog of scala implicit/given feature

  • @similartoself4750
    @similartoself4750 2 роки тому +5

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

  • @renecadenas3610
    @renecadenas3610 2 роки тому +1

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

  • @J1oTTa
    @J1oTTa 2 роки тому +1

    kotlin is love S2

  • @user-jz9dm9xr2n
    @user-jz9dm9xr2n 2 роки тому

    Spring framework to every house)

  • @larsartmann
    @larsartmann 2 роки тому +1

    Very good video!

  • @alexanderataman7836
    @alexanderataman7836 Рік тому

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

  • @kee1o
    @kee1o Рік тому

    great explanation

  • @skotch_izolentovich
    @skotch_izolentovich 2 роки тому +1

    Woooooow, this is amaing!

  • @alexgorodecky1661
    @alexgorodecky1661 7 місяців тому

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

  • @ScottBecker
    @ScottBecker 2 роки тому +3

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

    • @markvedder1121
      @markvedder1121 2 роки тому

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

  • @kawthooleidevelopers
    @kawthooleidevelopers Рік тому

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

  • @nymexe
    @nymexe Рік тому

    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 }

  • @shumymikaball
    @shumymikaball 2 роки тому

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

  • @cularu1
    @cularu1 2 роки тому

    with() should receive multiple parameters.

  • @ryansgot
    @ryansgot 2 роки тому +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 2 роки тому

      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

  • @tenminutetokyo2643
    @tenminutetokyo2643 2 роки тому

    Ah, IKEA.

  • @AlanDarkworld
    @AlanDarkworld 2 роки тому

    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? ;)

  • @user-jw1tb2ec9w
    @user-jw1tb2ec9w 2 роки тому

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

  • @udhayarajan_m
    @udhayarajan_m 2 роки тому

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

  • @alxjones
    @alxjones 2 роки тому

    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?

  • @user-cm4ce5fh4q
    @user-cm4ce5fh4q 10 місяців тому

    good

  • @quidryan
    @quidryan 2 роки тому

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

  • @senk0n
    @senk0n 2 роки тому

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

  • @AndreyDerkach8
    @AndreyDerkach8 2 роки тому

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

  • @thanosfisherman
    @thanosfisherman 3 місяці тому +1

    Huge spaghetti enabler

  • @Yazon2006
    @Yazon2006 2 роки тому

    Can't enable it for android project.

  • @nickreid4650
    @nickreid4650 2 роки тому +3

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

  • @johnokpo4068
    @johnokpo4068 2 роки тому

    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

  • @vadim-zuev
    @vadim-zuev 2 роки тому +1

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

  • @RhexGomez
    @RhexGomez 2 роки тому

    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.

  • @kamertonaudiophileplayer847
    @kamertonaudiophileplayer847 2 роки тому +1

    Swift.

  • @buszi_
    @buszi_ 2 роки тому

    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 2 роки тому

    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 Рік тому

    Why making kotlin ugly ?

  • @cryzz0n
    @cryzz0n 2 роки тому

    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!