Bạn nên chắc chắn xem xét Quasiquotes.
Quasiquotes được sử dụng để làm hai việc: để xây dựng cây cối, và để phù hợp với mô hình cây. Chúng cho phép bạn thể hiện cây mà bạn muốn làm việc với mã Scala tương đương. Bạn để cho thư viện quasiquote đối phó với cách mã Scala ánh xạ tới một biểu đồ Tree, và đó là một điều tốt!
Bạn có thể chơi xung quanh với họ trong REPL, mặc dù kết quả có thể hơi khác nhau trong vũ trụ vĩ mô:
scala> import scala.reflect.runtime.universe._
scala> showRaw(cq"p => p.name.is(Required(), HasLength(255))")
res0: String = CaseDef(
Bind(
TermName("p"),
Ident(termNames.WILDCARD)),
EmptyTree,
Apply(
Select(
Select(
Ident(TermName("p")),
TermName("name")),
TermName("is")),
List(
Apply(
Ident(TermName("Required")),
List()),
Apply(
Ident(TermName("HasLength")),
List(Literal(Constant(255)))))))
Một điều khác bạn có thể làm với Quasiquotes là để thực sự sử dụng chúng để phù hợp với mô hình.
Bây giờ, bạn phải cẩn thận, vì mẫu đó CHỈ phù hợp nếu người dùng đặt tên biến mẫu p
.
scala> val fromTree = cq"x => x.name.is(Required(), HasLength(255))"
scala> val cq"p => p.name.is($x, $y)" = fromTree
scala.MatchError: case (x @ _) => x.name.is(Required(), HasLength(255)) (of class scala.reflect.internal.Trees$CaseDef)
... 33 elided
Thay vào đó, bạn sẽ muốn có một chút chung chung hơn:
scala> val cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" = fromTree
p1: reflect.runtime.universe.TermName = x
p2: reflect.runtime.universe.TermName = x
x: reflect.runtime.universe.Tree = Required()
y: reflect.runtime.universe.Tree = HasLength(255)
scala> p1 == p2
res2: Boolean = true
Và, tất nhiên, nếu bạn đã làm điều này như là một phần của một mô hình phù hợp, bạn có thể làm:
case cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" if p1 == p2 =>
???
Hãy nhớ rằng Macro là lỗ sâu, sâu. Nếu bạn chỉ mới bắt đầu, hãy dành nhiều thời gian để nhận mã macro của bạn chính xác. Sau đó, hy vọng sẽ dành rất nhiều thời gian đối phó với các trường hợp cạnh.
Bạn có chắc chắn bạn cần macro ở đây không? Bạn có thể giải thích phương thức 'is' của bạn đến từ đâu không? –
Có, tôi khá chắc chắn tôi muốn macro, phương thức "is" lấy ValidationRules và macro tìm tất cả các lần xuất hiện để tạo đối tượng chứa "tên" của thuộc tính đang được thử nghiệm cộng với giá trị và tất cả các quy tắc để chạy nó. Không thực sự tìm cách tranh luận nếu cách tiếp cận của tôi là cách tốt nhất ... tìm kiếm trợ giúp với trường hợp sử dụng cụ thể để làm các trường hợp phù hợp trong macro để tìm tất cả ValidateRules trong biểu thức. – user2270883