elizarov
06/05/2019, 3:41 PMfun foo() = logged { transactional { ... } } // (1)
Padding(color=my) { OtherWrapper { Component() } } // (2)
It would be preferable to be able to write:
fun foo() = logged <compose> transactional { ... } // (1)
Padding(color=my) <compose> OtherWrapper <compose> Component() // (2)
The trick is what <compose>
sequence of characters is. It is extremely hard to find a syntactic form that is readable and understandable, looks nicely, and is not ambiguous with all the current and potential future extensions of Kotlin language. Ideas are welcome, use a thread please 🧵romainguy
06/05/2019, 3:43 PMkarelpeeters
06/05/2019, 3:44 PM.
work? function.x
never means anything right now does it?miha-x64
06/05/2019, 3:44 PMx
elizarov
06/05/2019, 3:45 PM=>
but it stylistically conflict with the rest of Kotlin and is not really obvious to the novice reader (logged => transactional
WTF?)karelpeeters
06/05/2019, 3:45 PMfunction
could be an ordinary class with an invoke
operator.Fudge
06/05/2019, 3:45 PMlogged and transactional
miha-x64
06/05/2019, 3:45 PMfun foo() by logged { transactional(::someFunc) }
Leland Richardson [G]
06/05/2019, 3:46 PM>>=
|>
Fudge
06/05/2019, 3:49 PMextends
is better than :
Leland Richardson [G]
06/05/2019, 3:50 PMelizarov
06/05/2019, 3:51 PMEric Martori
06/05/2019, 3:53 PMusing>
?
It is the only unambiguous thing I can think that is abvious while readingmiha-x64
06/05/2019, 3:54 PM>
? it's already ambiguous in the existing language 🙂elizarov
06/05/2019, 3:56 PM|>
the most, but the problem is that in JS it does completely different thing. It subsumes Kotlin’s scoping function let
and Kotlin’s extensions in general:
5 |> increment // JS
5.increment() // Kt (1)
5.let(::increment) // Kt (2)
&
, but using it for composition forever bars us from adding it as a bit-wise operator.for
. But even though it reads and parses, it is in conflict with its other meaning.Fudge
06/05/2019, 4:12 PMmiha-x64
06/05/2019, 4:13 PMfunc <smth> expr
instead of func { expr }
Ruckus
06/05/2019, 4:32 PM\
?Fudge
06/05/2019, 4:33 PMdivision
or or
, so I don't think it's a very good candidateelizarov
06/05/2019, 4:35 PMthen
to write Padding(color=my) then Component()
. But now it can be parsed as one-argument call to Padding
, application of infix then
with Component
or a two-argument call to Padding
with a second argument being lambda encapsulating Compose()
. It is not just syntactically ambiguous, you’ll have to do call resolution twice (for one- and two- argument Padding
) to see which one was meant here — this is something that should not be done.Fudge
06/05/2019, 4:39 PM&
for this then, and
for the bitwise operation is good enoughromainguy
06/05/2019, 4:59 PMFudge
06/05/2019, 5:01 PMa
) if It's too longbloder
06/05/2019, 5:02 PM|>
and >>=
ideas for that and I see what we want here like an opposite solution of Js / Elixir pipe operator ( () -> T
instead of (T) -> Unit
), but it still have the same principle of |>
from JS and Elixir then I don't see problems, in the end we have the same operator that compose things.romainguy
06/05/2019, 5:03 PMRuckus
06/05/2019, 5:05 PMthemishkun
06/05/2019, 5:13 PM<|
bloder
06/05/2019, 5:14 PMthemishkun
06/05/2019, 5:17 PMelizarov
06/05/2019, 5:19 PMthemishkun
06/05/2019, 5:25 PMmiha-x64
06/05/2019, 5:26 PMfunc <operator> expr
desugars to func { expr }
, it makes function boxing (anonymous class generation) even more implicit.Ruckus
06/05/2019, 5:36 PMfun foo(op: () -> Unit): () -> Unit
fun bar(op: () -> Unit)
fun bar(): Unit
fun baz(): Unit
foo <...> bar <...> baz
// Is that equal to
foo { bar { baz() } }
// or
foo { bar() } { baz() }
Or am I just confusing myself?Fudge
06/05/2019, 5:36 PMelizarov
06/05/2019, 5:43 PM{ .... }.transactional().logged()
Ruckus
06/05/2019, 5:53 PMelizarov
06/05/2019, 5:57 PMpadding
or logged
start to use too much precious screen space and even more dear mental parsing capacity. My personal favorite is reverse pipe <|
. It shows the direction of “embedding” and resembled an opening brace, but it is going to be tough for novices due to its utter unfamiliarity.Padding(color=my).OtherWrapper().Component()
Is it a readable shortcut to writing it with curly braces?bloder
06/05/2019, 6:18 PMfoo().bar().5
?Fudge
06/05/2019, 6:19 PM5
?bloder
06/05/2019, 6:19 PMFudge
06/05/2019, 6:20 PMbloder
06/05/2019, 6:21 PMFudge
06/05/2019, 6:22 PMPadding(color=my).around().Column {
Text("Hello")
}
infix
...
Padding(color=my) around Column {
Text("Hello")
}
elizarov
06/05/2019, 6:23 PMaround
. Dot is enough in compose context.Fudge
06/05/2019, 6:23 PMPadding(color=my).Column {
Text("Hello")
}
?elizarov
06/05/2019, 6:24 PMPadding(color=my) {
Column {
Text("Hello")
}
}
I’m not sure it helps, though, but obviously SwiftUI team thought they’d need to save space and nesting for simple and common wrappers like “padding”, etcRuckus
06/05/2019, 7:21 PMmiha-x64
06/05/2019, 7:32 PMRuckus
06/05/2019, 7:35 PMRobert Menke
06/05/2019, 9:08 PMinfix fun andThen
into the stdlib? I’m not opposed to an operator syntax, but too many operators can obviously make code confusing.
fun pascalCase() = snakeCase andThen upperCase
//left to right
infix fun <A, B, C> ((A) -> B).andThen(right : (B) -> C) : (A) -> C = {
arg -> right(invoke(arg))
}
//right to left
infix fun <A, B, C> ((B) -> C).compose(right : (A) -> B) : (A) -> C = {
arg -> invoke(right(arg))
}
elizarov
06/05/2019, 9:36 PMandThen
are expressions whose type is a functional type like (A) -> B
. Neigher Padding(color=my)
nor Component()
expressions in our discussion have such a type.Robert Menke
06/05/2019, 9:38 PMelizarov
06/05/2019, 9:42 PMfun foo() = (logged + transactional) { ... }
Implementation sketch here: https://pl.kotl.in/NDME-I0LXLeland Richardson [G]
06/06/2019, 9:07 AMlouiscad
06/06/2019, 9:13 AMLeland Richardson [G]
06/06/2019, 9:13 AM