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
// deep search inside myLayout | |
myLayout ~~> { | |
// make all buttons have medium-sized text | |
case b: Button ⇒ b ~> TextSize.medium | |
// find layouts consisting of just ImageView and TextView | |
case Layout(m: ImageView, t: TextView) ⇒ | |
t ~> text("I’m next to an image") | |
// hide everything else | |
case otherStuff ⇒ otherStuff ~> hide | |
} |
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
[info] [running phase parser on 9 compilation units] | |
[info] [running phase macroparadise on 9 compilation units] | |
[info] [running phase namer on 9 compilation units] | |
[info] [running phase packageobjects on 9 compilation units] | |
[info] [running phase typer on 9 compilation units] | |
[warn] issue error: type mismatch; | |
[warn] found : c.WeakTypeTag[X&0] | |
[warn] (which expands to) c.universe.WeakTypeTag[X&0] | |
[warn] required: c.universe.WeakTypeTag[needs.this.Need[_$1] forSome { type _$1 }] | |
[warn] issue error: type mismatch; |
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
new SVerticalLayout { | |
STextView("ID") | |
val userId = SEditText() | |
SButton("Sign in", signin(userId.text)) | |
}.padding(20 dip) |
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) |
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
// 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
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
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
// 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[_]) = |