Skip to content

Commit ea737b4

Browse files
committed
WIP - fix scala#5941: implement lens macros
1 parent 78259a1 commit ea737b4

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
abstract class Lens[S, T] {
2+
def get(s: S): T
3+
def set(t: T, s: S) :S
4+
}
5+
6+
import scala.quoted._
7+
import scala.tasty._
8+
9+
object Lens {
10+
def apply[S, T](_get: S => T)(_set: T => S => S): Lens[S, T] = new Lens {
11+
def get(s: S): T = _get(s)
12+
def set(t: T, s: S): S = _set(t)(s)
13+
}
14+
15+
/** case class Address(streetNumber: Int, streetName: String)
16+
*
17+
* Lens.gen[Address, Int](_.streetNumber) ~~>
18+
*
19+
* Lens[Address, Int](_.streetNumber)(n => a => a.copy(streetNumber = n))
20+
*/
21+
inline def gen[S, T](get: S => T): Lens[S, T] = ~impl('(get))
22+
23+
def impl[S: Type, T: Type](getter: Expr[S => T])(implicit refl: Reflection): Expr[Lens[S, T]] = {
24+
import refl._
25+
import util._
26+
import quoted.Toolbox.Default._
27+
28+
cond.unseal.underlyingArgument match {
29+
case Term.Block(
30+
DefDef(_, Nil, (param :: Nil) :: Nil, _, Some(Term.Select(o, field))) :: Nil,
31+
Lambda(meth, _)
32+
) =>
33+
'{
34+
val setter = (s: S) => (t: T) => {
35+
???
36+
// t.copy(field)
37+
}
38+
apply[~S, ~T](~getter)(setter)
39+
}
40+
}
41+
}
42+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
case class Address(streetNumber: Int, streetName: String)
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
val len = Lens.gen[Address, Int](_.streetNumber)
6+
val address = Address(10, "High Street")
7+
assert(len.get(address) == 10)
8+
val addr2 = len.set(5, address)
9+
assert(len.get(addr2) == 5)
10+
}
11+
}

0 commit comments

Comments
 (0)