Sometimes it is useful to be able to explore the parent AST in a macro. Examples include guiding type inference, building tree-like DSLs, etc (see below). Unfortunately, the current macro API makes it extremely awkward (also see below). Here I propose a way to separate such functionality in a well-defined (safe, optimized) new type of macros and leverage existing Scala features (traits + implicits) to take care of the rest.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val rx1 = Var(1) | |
val rx2 = Var(2) | |
val rx3 = Rx { rx1() + rx2() } | |
// ... | |
val style = TextSize.large + padding(all = 16 dp) | |
def rxText(rx: Rx[Int]) = rx.map(_.toString).map(text) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* "a123b45c" → ["a", 123, "b", 45, "c"] */ | |
function nat(x) { | |
// digit-parts | |
var d = x.split(/[^0-9]+/); // ["", "123", "45, ""] | |
// alpha-parts | |
var a = x.split(/[0-9]+/); // ["a", "b", "c"] | |
// helpers | |
function nonEmpty(x) { return x != "" } | |
function toInt(x) { return x - 0 } | |
// the one that does not start with a "" goes first |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// F[A] :: F[B] :: ... :: M :: F[N] :: O :: ... :: HNil -> F[A :: B :: ... :: M :: N :: O :: ... :: HNil] | |
object applicativeFolder extends Poly2 { | |
// (F[A], F[B]) -> F[A :: B] | |
implicit def caseApp[A, B <: HList, F[_]](implicit app: Applicative[F]) = | |
at[F[A], F[B]] { (a, b) ⇒ | |
app.apply[A, A :: B](app.map[B, A ⇒ A :: B](b, x ⇒ y ⇒ y :: x), a) | |
} | |
// (A, F[B]) -> F[A :: B] (uses Applicative.pure) | |
implicit def casePure[A, B <: HList, F[_]](implicit app: Applicative[F], pure: A <:!< F[_]) = |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.higherKinds | |
import play.api.libs.functional._ | |
import shapeless._ | |
import shapeless.ops.hlist.RightFolder | |
import play.api.data.mapping.{ From, Reader, Rule } | |
import play.api.libs.json.{Json, JsValue} | |
import play.api.data.mapping.json.Rules._ | |
object applicativeFolder2 extends Poly2 { | |
// Rule[I, X] :: Rule[I, L] -> Rule[I, X :: L] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Future { | |
// perform something in background | |
val url = ... | |
val data = fetch(url) | |
process(data) | |
} mapUi { data ⇒ | |
// this will happen on the UI thread | |
display(data) | |
} onFailureUi { | |
// handle failure on the UI thread |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use with Options: | |
var maybeTweak: Option[Tweak[TextView]] = Some(text("Hi")) | |
myTextView ~> maybeTweak // this will set the text | |
maybeTweak = None | |
myTextView ~> maybeTweak // this will be ignored | |
// use with Futures: | |
val showInASecond = future { | |
Thread.sleep(1000) | |
show |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def largeText(t: String)(implicit ctx: Context) = text(t) + TextSize.large |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var userId = slot[EditText] | |
l[VerticalLinearLayout]( | |
w[TextView] ~> text("ID"), | |
w[EditText] ~> wire(userId), | |
w[Button] ~> text("Sign in") ~> On.click(signin(userId.get.getText)) | |
) ~> padding(all = 20 dp) |