Thread
#compose
    kioba

    kioba

    3 years ago
    is there a way to diverge a layout with specific receivers? An example is like Scaffold in Flutter

    https://cdn-images-1.medium.com/max/1600/1*jZdYRvtKllXu0h0FiGG9Vw.png

    . where the AppBar, Body, and BottomNavBar are specified receivers for a Widget and Scaffold provides behaviour for them.
    Manuel Vivo

    Manuel Vivo

    3 years ago
    You can do something like
    @Composable
    fun Scaffold(appBar: @Composable() () -> Unit, @Children body: @Composable() () -> Unit) {
        FlexColumn {
            inflexible {
                appBar()
            }
            expanded(flex = 1.0f) {
                Surface(color = +themeColor{ surface }) {
                    children()
                }
            }
        }
    }
    Andrey Kulikov

    Andrey Kulikov

    3 years ago
    Yeah, we are going to have something similar in our Scaffold
    kioba

    kioba

    3 years ago
    Thanks for the full example! so the general idea for building compose api is to wrap effects into a lambda to enforce lazy evaluation and passing effects around? feels like at the end everything will be wrapped in a lambda 🤔
    r

    Ryan Mentley

    3 years ago
    feels like at the end everything will be wrapped in a lambda
    Quite a lot of stuff ends up wrapped in lambdas - see, for example, the animation system's usage of lambdas. It ends up being rather nice once you're used to it.
    kioba

    kioba

    3 years ago
    yeah, I am completely agree with you @Ryan Mentley lambdas are nice. It would be better if we would not have to do these wrappings but they would be considered part of the Compose.
    instead of
    Unit
    a compose function could return a @Compose () -> Unit or something that wraps it like
    class Widget(val effect: @Compose () -> Unit)
    l

    Leland Richardson [G]

    3 years ago
    can you write an example of what you mean? I’m not sure I understand
    kioba

    kioba

    3 years ago
    all I am saying is no point of eager execution if everyone wraps them in a lambda to make them lazy. instead of
    fun Text(str: String): Unit
    ->
    fun Text(str: String): Compose
    1) That would proved a return type for everyone, 2) we can keep the compiler plugin because all that matter is the execution of the most outer function. 3) lazy evaluation
    what #arrow does with
    Fx
    and
    IO
    is the same what #compose tries to achieve with
    setContent
    and
    @Compose () -> Unit
    gildor

    gildor

    3 years ago
    And how would you use this Text function which returns Compose instance? Should you add it explicitly to some render context?
    kioba

    kioba

    3 years ago
    val text = Text("myLibraryGeneratedText")
    // …
    setContent {
      Scaffold {
        appbar = Appbar(),
        child = text
      }
    }
    gildor

    gildor

    3 years ago
    So explicitly pass every child to some property for nesting?
    Row(children = listOf(Padding (child = Text("blah")), Padding(child = Text("hlab"))
    Supper messy comparing to current syntax, one may do not like returning Unit, but completely screw up ergonomics because of this doesn't look as good idea for me I would prefer some other solution for scoped components
    kioba

    kioba

    3 years ago
    Without formatting everything can be super messy. Current Syntax is a mixture of your example (just look at scaffold ) and kotlin dsl. your example just described flutter with functions but we could improve it with Kotlin specific Syntax. The reason why return type is better choice is because you can create the components outside of Compose, It is pure by the definition because wraps the effect. I dont think we have problems with the compiler plugin that is great to have and as I mentioned i agree eith the benefits. All what we wish to use is a pure api
    l

    Leland Richardson [G]

    3 years ago
    I just want to clarify that the team did not take these decisions lightly. None of these arguments are new to us - we spent months hashing out a lot of these questions ~1 year ago or so. A lot of us had the exact same reactions, and a lot of different solutions were evaluated. It’s also worth pointing out that your example above can be emulated by just wrapping in a lambda (a “Thunk” of sorts):
    val text = @Composable { Text("myLibraryGeneratedText") }
    // …
    setContent {
      Scaffold(
        appbar = { Appbar() },
        child = text
      )
    }
    Not the same thing, and I understand what you’re trying to get at, but this is the way we went and we believe it has a lot of benefits.
    gildor

    gildor

    3 years ago
    also good thing about lambda that it lazy by default
    kioba

    kioba

    3 years ago
    yeah that is the idea now to use lambdas, actually the function first approach is quite interesting and exciting to see