From 7c5ea26ed924fa42d3e477ddb1ee109e0a2d54ae Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Tue, 28 Jan 2014 21:46:02 +0100 Subject: [PATCH] Complete exercises TODO: verify Markdown formatting. --- exercises/E08.md | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/exercises/E08.md b/exercises/E08.md index 3f3382d..b525747 100644 --- a/exercises/E08.md +++ b/exercises/E08.md @@ -1,35 +1,54 @@ -Because of the delay, partial solutions will be +Because of the delay, partial solutions are more welcome than usual. +Please try to solve at least two-three exercises, and focus on the theory part. - -- Consider a macro running on an expression with nested subexpressions: +- Consider a macro named `aMacro` running on an expression with nested subexpressions: val intermediateExpr = if (cond) { list map f } else { list map g } aMacro(intermediateExpr map h) We said that aMacro can't know statically the what intermediateExpr is going to contain. +Sketch a scenario which exemplifies the problem. + +- Assume again that `aMacro` is a macro and consider the snippet below, divided in two fragments marked (1) and (2). Will `aMacro` receive different arguments in examples (1) and (2)? + +```scala + //(1) + aMacro(1) + //(2) + aMacro({ + val v = 1 + v + }) +``` + + If there is a difference between the arguments in those scenarios: + - can you describe scenarios where the difference is or is not interesting, and motivate why? + - For scenarios where the difference is not interesting, does the difference introduce potential for bugs? - Choose an example of boilerplate in the course lecture notes and try describing how macros could be used to automate the generation of such boilerplate. -- Macros can also be used: +- Macros can also be used in the implementation of DSLs. For instance: - for integrating external DSLs - - for language virtualization - - for - Give an example of a possible usage scenario. + - for implementing alternative semantics of existing code (language virtualization) + - to perform static analyses, even on code which does not get executed. + Give an example of a possible usage scenario among those categories, and/or point out additional categories with appropriate examples. -- Inside trace_impl, we have two different proposalsfor the body: +- Inside trace_impl in the code from the lecture (`14-macros/macros/01macros.scala`), we have two different proposals for the body: +```scala def trace(x: Any): Unit = macro trace_impl def trace_impl(c: Context)(x: c.Expr[Any]): c.Expr[Unit] = { import c.universe._ //Base version (1): //c.Expr(q"""println("The value of %s is %s" format (${show(x)}, $x))""") - + // //Question: what's wrong if we write instead (2): //c.Expr(q"""println(${"The value of %s is %s" format (show(x), x)})""") } +``` Please analyze and describe the difference between the two pieces of code, in terms of the different execution times we have discussed during the lecture. @@ -46,7 +65,7 @@ Coding exercises: try writing a macro - fun(f: Term => Term): HOASFun + def fun(f: Term => Term): HOASFun = macro ... -that, when invoked as fun(strangeName => body...), returns -HOASFun(strangeName => body..., "strangeName") by capturing the argument to the macro. +that, when invoked as `fun(strangeName => body...)`, expands to +`HOASFun(strangeName => body..., "strangeName")` by capturing the name (`"strangeName"`) of the parameter (`strangeName`) of the argument (`strangeName => body`) for the macro invocation.