scala: function recursively returns a function object, how to overcome illegal cyclic reference?
i have a class with a method that returns a function object. the requirements are that the method is arity 0 and its return type is an Option of a Function0 - whose return type is the original return type. for example:
class MyClass {
def f(): Option[Function[A]] = Some(g _)
def g(): Option[Function[A]] = Some(h _)
... goes on and on, eventually returns Some(z _) ...
def z(): Option[Function[A]] = None
}
Due to the recursion, the issue is that the type A is defined as:
type A = Option[Function开发者_运维知识库0[A]]
but since cyclic references are not allowed, it produces the error:
illegal cyclic reference involving type A
i obviously want to avoid defining a different return type for each of the methods, but having a unified return type doesn't seem possible due to the cycle. is there any way to do this? thanks!
This is not supported by Scala type definitions. See How to define a cyclic type definition?
You can accomplish this with a class instead of a type, although you would have to define your own Option-like class. An example is below (with monadic methods omitted). Also, see this mailing list discussion: http://www.scala-lang.org/node/2541
sealed trait OptionalFunction extends (() => OptionalFunction) {
def get: (() => OptionalFunction)
}
case class SomeFunction(fn: () => OptionalFunction) extends OptionalFunction {
def apply() = fn()
def get = fn
}
case object NoFunction extends OptionalFunction {
def apply() = this
def get = throw new NoSuchElementException
}
class MyClass {
type A = OptionalFunction
def f(): A = SomeFunction(g _)
def g(): A = SomeFunction(h _)
def h(): A = SomeFunction(() => { println("At the end!"); i })
def i(): A = NoFunction
}
scala> new MyClass().f()()()()
At the end!
res0: OptionalFunction[Unit] = <function0>
I'm not sure if this is what you're looking for, but many of these edge-cases can be worked around with explicitly using objects:
abstract class F extends Function0[F]
val p = new F {
def apply() = { println("hi"); this }
}
>> defined class F
>> p: $anon forSome { type $anon <: F{def apply(): $anon} } =
p()
>> hi
>> res2: $anon =
p()()
>> hi
>> hi
>> res3: $anon =
Happy coding.
精彩评论