まだ十分な選択肢がないことは明らかなので、もう 1 つの方法はScalaUtils の試行メソッドを使用することです。ScalaUtils は、依存関係として追加することを気にしない、非常に小さな集中ライブラリです。Attempt メソッド (org.scalautils パッケージ オブジェクトにあります) は、toEither を呼び出すことができる Or 型を提供します。最初は、依存関係を追加する必要がないように Try を使用してこれを行うことを提案するつもりでしたが、toEither メソッドがないようで、驚きました。Or を使用すると、次のようになります。
scala> import org.scalautils._
import org.scalautils._
scala> def foo(i: Int, s: String): String = { require(i >= 0); s * i }
foo: (i: Int, s: String)String
scala> def bar(b: Boolean, i: Int, s: String): Int = { require(i >= 0); if (b) s.length else i }
bar: (b: Boolean, i: Int, s: String)Int
scala> def foo2(i: Int, s: String) = attempt(foo(i, s)).toEither
foo2: (i: Int, s: String)Either[Throwable,String]
scala> def bar2(b: Boolean, i: Int, s: String) = attempt(bar(b, i, s)).toEither
bar2: (b: Boolean, i: Int, s: String)Either[Throwable,Int]
scala> foo2(2, "ho")
res10: Either[Throwable,String] = Right(hoho)
scala> foo2(-2, "ho")
res11: Either[Throwable,String] = Left(java.lang.IllegalArgumentException: requirement failed)
scala> bar2(true, 3, "ho")
res12: Either[Throwable,Int] = Right(2)
scala> bar2(false, 3, "ho")
res13: Either[Throwable,Int] = Right(3)
scala> bar2(false, -3, "ho")
res14: Either[Throwable,Int] = Left(java.lang.IllegalArgumentException: requirement failed)
申し訳ありませんが、最初はあなたが 1 つの方法を望んでいたことを見逃していました。noziarが提案したように、おそらくオーバーロードするだけです:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def safely[A, B, C](f: (A, B) => C): (A, B) => Either[Throwable, C] = (a: A, b: B) => attempt(f(a, b)).toEither
def safely[A, B, C, D](f: (A, B, C) => D): (A, B, C) => Either[Throwable, D] = (a: A, b: B, c: C) => attempt(f(a, b, c)).toEither
// Exiting paste mode, now interpreting.
safely: [A, B, C](f: (A, B) => C)(A, B) => Either[Throwable,C] <and> [A, B, C, D](f: (A, B, C) => D)(A, B, C) => Either[Throwable,D]
safely: [A, B, C](f: (A, B) => C)(A, B) => Either[Throwable,C] <and> [A, B, C, D](f: (A, B, C) => D)(A, B, C) => Either[Throwable,D]
scala> val foo3 = safely { foo _ }
foo3: (Int, String) => Either[Throwable,String] = <function2>
scala> val bar3 = safely { bar _ }
bar3: (Boolean, Int, String) => Either[Throwable,Int] = <function3>
scala> foo3(2, "ho")
res5: Either[Throwable,String] = Right(hoho)
scala> foo3(-2, "ho")
res6: Either[Throwable,String] = Left(java.lang.IllegalArgumentException: requirement failed)
scala> bar3(true, 3, "ho")
res7: Either[Throwable,Int] = Right(2)
scala> bar3(false, 3, "ho")
res8: Either[Throwable,Int] = Right(3)
scala> bar3(false, -3, "ho")
res9: Either[Throwable,Int] = Left(java.lang.IllegalArgumentException: requirement failed)
過負荷 (および形状のない) を回避したい場合は、他の代替手段はmagnet patternです。これで 1 つの安全な方法にたどり着くと思いますが、オーバーロードの方が簡単だと思います。