Scala,强制数组/集合参数的长度
Posted
技术标签:
【中文标题】Scala,强制数组/集合参数的长度【英文标题】:Scala, enforce length of Array/Collection parameter 【发布时间】:2021-11-09 23:12:39 【问题描述】:假设我有一个类定义为
case class MyClass(myArray: Array[Int])
我只想允许 myArray 参数具有特定长度的实例,比如 3。
-
我可以在类型/编译级别强制执行
myArray.size == 3
吗?
其他系列会有所不同吗? (比如说,一个不可变的列表)
我发现的唯一方法是在运行时通过智能构造函数检查 myArray 的大小并失败 - 例如使用 require
。
【问题讨论】:
看看:github.com/milessabin/shapeless/blob/main/core/src/main/scala/… and github.com/travisbrown/sized and github.com/fthomas/refined 【参考方案1】:我可以在类型/编译级别强制 myArray.size == 3 吗?
是的,Scala 可以represent numbers at type-level。例如,使用 shapeless 中的Sized
import shapeless._
import syntax.sized._
import nat._
case class MyClass(myArray: Sized[Array[Int], _3])
MyClass(Sized[Array](1,2,3)) // ok
MyClass(Sized[Array](1,2,3,4)) // compile-time error
Array(1,2,3,4).sized(3).map(MyClass) // None
以下是在 Scala 3 中使用 scala.compiletime.ops
设施的方法
import scala.compiletime.ops.int.S
enum MyArray[Size, +A]:
case Nil extends MyArray[0, Nothing]
case Cons[N <: Int, B](head: B, tail: MyArray[N, B]) extends MyArray[S[N], B]
import MyArray._
val xs: MyArray[3, Int] = Cons(1, Cons(2, Cons(3, Nil)))
val ys: MyArray[4, Int] = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))
case class MyClass(myArray: MyArray[3, Int])
MyClass(xs) // ok
MyClass(ys) // compile-time error
【讨论】:
【参考方案2】:你可以将 require 用于你想要的一切:)
case class MyClass(myArray: Array[Int])
require(myArray.size == 3, "Only arrays with 3 items are allowed!")
如果你传递的数组不符合要求,它会抛出一个IllegalArgumentException
。
【讨论】:
感谢您的回答,这正是我所说的“智能构造函数”。我会更新我的问题以明确表示?以上是关于Scala,强制数组/集合参数的长度的主要内容,如果未能解决你的问题,请参考以下文章