https://kotlinlang.org logo
k

kioba

06/14/2019, 11:18 AM
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.
m

Manuel Vivo

06/14/2019, 11:22 AM
You can do something like
Copy code
@Composable
fun Scaffold(appBar: @Composable() () -> Unit, @Children body: @Composable() () -> Unit) {
    FlexColumn {
        inflexible {
            appBar()
        }
        expanded(flex = 1.0f) {
            Surface(color = +themeColor{ surface }) {
                children()
            }
        }
    }
}
👍 2
a

Andrey Kulikov

06/14/2019, 11:43 AM
Yeah, we are going to have something similar in our Scaffold
k

kioba

06/14/2019, 11:45 AM
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

06/14/2019, 1:39 PM
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.
k

kioba

06/14/2019, 4:57 PM
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]

06/14/2019, 5:39 PM
can you write an example of what you mean? I’m not sure I understand
1
k

kioba

06/15/2019, 7:09 AM
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
g

gildor

06/15/2019, 12:27 PM
And how would you use this Text function which returns Compose instance? Should you add it explicitly to some render context?
k

kioba

06/15/2019, 5:56 PM
Copy code
val text = Text("myLibraryGeneratedText")
// …
setContent {
  Scaffold {
    appbar = Appbar(),
    child = text
  }
}
g

gildor

06/16/2019, 2:06 AM
So explicitly pass every child to some property for nesting?
Copy code
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
k

kioba

06/16/2019, 11:29 AM
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]

06/16/2019, 4:13 PM
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):
Copy code
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.
👍 3
g

gildor

06/17/2019, 2:52 AM
also good thing about lambda that it lazy by default
k

kioba

06/17/2019, 8:08 AM
yeah that is the idea now to use lambdas, actually the function first approach is quite interesting and exciting to see
5 Views