Tôi nghĩ bạn có thể hưởng lợi từ việc sử dụng số Box của Lift, trong đó có Full
(ví dụ: Some
), Empty
(tức là None
) và Failure
(một số Empty
với lý do tại sao nó trống và có thể bị xích). David Pollak có một số good blog post giới thiệu nó. Nói tóm lại, bạn có thể làm điều gì đó như thế này (không kiểm tra):
def validate1: Box[String]
def validate2: Box[String]
def validate3: Box[String]
val validation = for (
validation1 <- validate1 ?~ "error message 1"
validation2 <- validate2 ?~ "error message 2"
validation3 <- validate3 ?~ "error message 3"
) yield "overall success message"
Đây không phải là bất kỳ ngắn hơn ví dụ ban đầu nhưng nó, theo ý kiến của tôi, một chút logic hơn, với kết quả của một xác nhận thành công trong một số Full
và xác thực không thành công trong Failure
.
Tuy nhiên, chúng tôi có thể thu nhỏ hơn. Đầu tiên phải kể chức năng xác nhận của chúng tôi trở Box[String]
, họ có thể trở lại Failure
là chính mình và chúng tôi không cần phải chuyển đổi Empty
-Failure
mình:
val validation = for (
validation1 <- validate1
validation2 <- validate2
validation3 <- validate3
) yield "overall success message"
Nhưng, Box
cũng có một phương pháp or
trả về cùng Box
nếu nó là Full
hoặc khác Box
nếu không. Điều này sẽ cung cấp cho chúng tôi:
val xác nhận = validate1 hoặc validate2 hoặc validate3
Tuy nhiên, dòng đó dừng lại ở người đầu tiên xác nhận thành công, không phải là thất bại đầu tiên. Nó có thể làm cho tinh thần để thực hiện một phương pháp mà làm những gì bạn muốn (có lẽ gọi là unless
?) Mặc dù tôi không thể nói rằng nó thực sự sẽ hữu ích hơn nhiều so với cách tiếp cận hiểu.
Tuy nhiên, đây là một thư viện nhỏ yếu đuối nào đó:
scala> class Unless[T](a: Box[T]) {
| def unless(b: Box[T]) = {
| if (a.isEmpty) { a }
| else b
| }
| }
defined class Unless
scala> implicit def b2U[T](b: Box[T]): Unless[T] = new Unless(b)
b2U: [T](b: net.liftweb.common.Box[T])Unless[T]
scala> val a = Full("yes")
a: net.liftweb.common.Full[java.lang.String] = Full(yes)
scala> val b = Failure("no")
b: net.liftweb.common.Failure = Failure(no,Empty,Empty)
scala> val c = Full("yes2")
c: net.liftweb.common.Full[java.lang.String] = Full(yes2)
scala> a unless b
res1: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless b unless c
res2: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless c unless b
res3: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless c
res4: net.liftweb.common.Box[java.lang.String] = Full(yes2)
Đây là một hack nhanh chóng dựa trên sự hiểu biết hạn chế của tôi về hệ thống kiểu Scala, như bạn có thể thấy trong các lỗi sau:
scala> b unless a
<console>:13: error: type mismatch;
found : net.liftweb.common.Full[java.lang.String]
required: net.liftweb.common.Box[T]
b unless a
^
Tuy nhiên, điều đó là đủ để giúp bạn đi đúng hướng.
Tất nhiên, Lift ScalaDocs có thêm thông tin về Box.
Dòng cuối cùng có thể được đơn giản hóa một chút: '(validate1 ++ validate2 ++ validate3) .head' – pr1001
Tôi không nghĩ rằng bạn muốn thả các cuộc gọi '.iterator' - sau đó bạn sẽ luôn gọi tất cả các phương thức xác thực thay vì chỉ các phương thức gọi cho đến khi một trong số chúng trả về lỗi. – Steve
Ahh, tôi thấy, rất thông minh. – pr1001