首先是背景 - 我正在编写一些代码来解码从套接字接收到的消息。套接字的性质意味着这些作为ByteStrings接收的消息可能是完整的、截断的或与其他消息连接的。消息本身被分成一个公共头,其中包含后面的可变数据的长度。
我的计划是拥有读取消息部分的函数,例如第一次读取可以读取变量数据的长度,第二次读取变量数据本身。
当调用这些方法之一时,我希望它返回下一个操作,这可能是读取序列中的下一个逻辑操作,或者如果由于尚未接收到所需的所有数据而无法执行特定读取,则该操作可能是其本身。
在从套接字接收到的数据是完美帧的情况下,读取操作将在readLength和之间交替readData。但是,当从套接字以多个块读取数据时,读取操作可能遵循readLength,readData和readData模式。
希望这是有道理的。
我想要做的是这样的事情(由于循环引用而无法编译):
type ReadFunction = (ByteBuffer) => ReadFunction
Run Code Online (Sandbox Code Playgroud)
这样我就可以声明如下内容:
def readLength(buffer: ByteBuffer): ReadFunction = {
if (buffer.limit - buffer.position > 4) {
return readData(buffer.getInt)
}
else {
return readLength
}
}
def readData(length: Int)(buffer: ByteBuffer): ReadFunction = {
if (buffer.limit - buffer.position > length) {
val data: Array[Byte](size)
buffer.get(data)
//process data
readLength
}
else {
readData(length)
}
}
Run Code Online (Sandbox Code Playgroud)
现在我知道我可以(并且实际上已经)通过将读取操作定义为扩展共同特征并返回每个特征的类来解决这个问题,但这似乎不像 Scala。
所以我的问题是 - 你如何定义一个可以返回自身的函数?
你不能在type声明中使用循环引用,但你可以像这样在classortrait声明中使用它:
implicit class ReadFunction(f: Int => ReadFunction) extends (Int => ReadFunction) {
def apply(i: Int) = f(i)
}
lazy val read: ReadFunction = { i: Int => println(i); read }
scala> read(1)(2)(3)
1
2
3
res0: ReadFunction = <function1>
Run Code Online (Sandbox Code Playgroud)