- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
A way around cyclic reference restrictions to achieve default value effects?
Fri, 2010-01-08, 00:33
Hi all,
The following code describes some immutable types:
case class AsnBmpString extends AsnCharacterString {
}
case class AsnBoolean(value: Boolean) {
}
object AsnBoolean extends AsnBoolean(false)
class AsnCharacterString extends AsnType {
}
abstract class AsnChoice extends AsnType {
}
abstract class AsnEnumeration extends AsnType {
def toString: String
}
case class AsnGeneralString extends AsnCharacterString {
}
case class AsnGraphicString extends AsnCharacterString {
}
case class AsnIa5String extends AsnCharacterString {
}
case class AsnInteger(value: Long) extends AsnType {
}
object AsnInteger extends AsnInteger(0) {
}
case class AsnIso646String extends AsnCharacterString {
}
sealed case class AsnNull {
}
object AsnNull extends AsnNull
case class AsnNumericString extends AsnCharacterString {
}
case class AsnPrintableString(value: String) extends AsnCharacterString {
}
object AsnPrintableString extends AsnPrintableString("") {
}
case class AsnReal(value: Double) extends AsnType {
}
object AsnReal extends AsnReal(0.0) {
}
class AsnSequence extends AsnType {
}
class AsnSet extends AsnType {
}
case class AsnT61String extends AsnCharacterString {
}
case class AsnTeletexString extends AsnCharacterString {
}
trait AsnType {
}
case class AsnUniversalString extends AsnCharacterString {
}
case class AsnUtf8String extends AsnCharacterString {
}
case class AsnVideotexString extends AsnCharacterString {
}
case class AsnVisibleString extends AsnCharacterString {
}
case class MySequence(
field0: Option[AsnInteger],
field1: AsnReal,
field2: AsnPrintableString,
field3: MyChoice
) extends AsnSequence {
def field0(f: (Option[AsnInteger] => Option[AsnInteger])): MySequence = copy(field0 = f(field0))
def field1(f: (AsnReal => AsnReal)): MySequence = copy(field1 = f(field1))
def field2(f: (AsnPrintableString => AsnPrintableString)): MySequence = copy(field2 = f(field2))
def field3(f: (MyChoice => MyChoice)): MySequence = copy(field3 = f(field3))
}
object MySequence extends MySequence(
Some(AsnInteger),
AsnReal,
AsnPrintableString,
MyChoice.default
) {
}
abstract class MyChoice extends AsnChoice {
def _choice: Int
def choice0: Option[AsnNull] = None
def choice1: Option[AsnInteger] = None
def choice2: Option[AsnReal] = None
def choice0(f: (MyChoice => AsnNull)): MyChoice =
MyChoice.Choice0(f(this))
def choice1(f: (MyChoice => AsnInteger)): MyChoice =
MyChoice.Choice1(f(this))
def choice2(f: (MyChoice => AsnReal)): MyChoice =
MyChoice.Choice2(f(this))
}
object MyChoice {
object default extends Choice0(AsnNull)
case class Choice0(_element: AsnNull) extends MyChoice {
def _choice: Int = 0
override def choice0: Option[AsnNull] = Some(_element)
}
case class Choice1(_element: AsnInteger) extends MyChoice {
def _choice: Int = 1
override def choice1: Option[AsnInteger] = Some(_element)
}
case class Choice2(_element: AsnReal) extends MyChoice {
def _choice: Int = 2
override def choice2: Option[AsnReal] = Some(_element)
}
}
case class MyEnum(_value: Int) extends AsnEnumeration {
}
object MyEnum extends MyEnum(0) {
def value0: MyEnum = MyEnum(0)
def value1: MyEnum = MyEnum(1)
def value2: MyEnum = MyEnum(2)
def value3: MyEnum = MyEnum(3)
}
It also lets me transform the immutable values easily:
// Create a sequence, initialising all fields.
val mySequence = MySequence(
Some(AsnInteger(1)),
AsnReal(1.0),
AsnPrintableString("Hello world"),
MyChoice.Choice1(AsnInteger(2)))
// Create copy of sequence field0 and field1 initialised to different values
val mySequence2 =
( mySequence
.field0{
case Some(AsnInteger(x)) => Some(AsnInteger(x + 2))
case None => None
}
.field1{_ => AsnReal(3.0)}
)
println(mySequence2)
println(mySequence2.field3._choice)
println(mySequence.field3{_.choice2{_ => AsnReal(9.9)}})
println(AsnNull)
println(MySequence)
println(MyChoice)
// Using the MySequence constructor can be tedious because you need
// always supply values for all fields. An easier way to construct
// the sequence is supported: MySequence is itself a value with
// fields initialised to default values, so the alternative way to
// construct objects is:
val moo =
( MySequence
.field0{_ => Some(AsnInteger(12))}
.field1{_ => AsnReal(123.0)}
)
println(moo)
println(moo.field3.choice2{_ => AsnReal(1.23)}._choice)
println(MyEnum.value1)
However, for the choice type the need to write MyChoice.default instead of just MyChoice annoys me a lot and I am disallowed from fixing it by writing:
object MyChoice extends MyChoice.Choice0 {
The error is:
illegal cyclic reference involving object MyChoice TestGeneratedCode.scala /asn1runtimetest/src/test/asn1/genruntime line 50 Scala Problem
Any other way I can do this?
Cheers,
-John
The following code describes some immutable types:
case class AsnBmpString extends AsnCharacterString {
}
case class AsnBoolean(value: Boolean) {
}
object AsnBoolean extends AsnBoolean(false)
class AsnCharacterString extends AsnType {
}
abstract class AsnChoice extends AsnType {
}
abstract class AsnEnumeration extends AsnType {
def toString: String
}
case class AsnGeneralString extends AsnCharacterString {
}
case class AsnGraphicString extends AsnCharacterString {
}
case class AsnIa5String extends AsnCharacterString {
}
case class AsnInteger(value: Long) extends AsnType {
}
object AsnInteger extends AsnInteger(0) {
}
case class AsnIso646String extends AsnCharacterString {
}
sealed case class AsnNull {
}
object AsnNull extends AsnNull
case class AsnNumericString extends AsnCharacterString {
}
case class AsnPrintableString(value: String) extends AsnCharacterString {
}
object AsnPrintableString extends AsnPrintableString("") {
}
case class AsnReal(value: Double) extends AsnType {
}
object AsnReal extends AsnReal(0.0) {
}
class AsnSequence extends AsnType {
}
class AsnSet extends AsnType {
}
case class AsnT61String extends AsnCharacterString {
}
case class AsnTeletexString extends AsnCharacterString {
}
trait AsnType {
}
case class AsnUniversalString extends AsnCharacterString {
}
case class AsnUtf8String extends AsnCharacterString {
}
case class AsnVideotexString extends AsnCharacterString {
}
case class AsnVisibleString extends AsnCharacterString {
}
case class MySequence(
field0: Option[AsnInteger],
field1: AsnReal,
field2: AsnPrintableString,
field3: MyChoice
) extends AsnSequence {
def field0(f: (Option[AsnInteger] => Option[AsnInteger])): MySequence = copy(field0 = f(field0))
def field1(f: (AsnReal => AsnReal)): MySequence = copy(field1 = f(field1))
def field2(f: (AsnPrintableString => AsnPrintableString)): MySequence = copy(field2 = f(field2))
def field3(f: (MyChoice => MyChoice)): MySequence = copy(field3 = f(field3))
}
object MySequence extends MySequence(
Some(AsnInteger),
AsnReal,
AsnPrintableString,
MyChoice.default
) {
}
abstract class MyChoice extends AsnChoice {
def _choice: Int
def choice0: Option[AsnNull] = None
def choice1: Option[AsnInteger] = None
def choice2: Option[AsnReal] = None
def choice0(f: (MyChoice => AsnNull)): MyChoice =
MyChoice.Choice0(f(this))
def choice1(f: (MyChoice => AsnInteger)): MyChoice =
MyChoice.Choice1(f(this))
def choice2(f: (MyChoice => AsnReal)): MyChoice =
MyChoice.Choice2(f(this))
}
object MyChoice {
object default extends Choice0(AsnNull)
case class Choice0(_element: AsnNull) extends MyChoice {
def _choice: Int = 0
override def choice0: Option[AsnNull] = Some(_element)
}
case class Choice1(_element: AsnInteger) extends MyChoice {
def _choice: Int = 1
override def choice1: Option[AsnInteger] = Some(_element)
}
case class Choice2(_element: AsnReal) extends MyChoice {
def _choice: Int = 2
override def choice2: Option[AsnReal] = Some(_element)
}
}
case class MyEnum(_value: Int) extends AsnEnumeration {
}
object MyEnum extends MyEnum(0) {
def value0: MyEnum = MyEnum(0)
def value1: MyEnum = MyEnum(1)
def value2: MyEnum = MyEnum(2)
def value3: MyEnum = MyEnum(3)
}
It also lets me transform the immutable values easily:
// Create a sequence, initialising all fields.
val mySequence = MySequence(
Some(AsnInteger(1)),
AsnReal(1.0),
AsnPrintableString("Hello world"),
MyChoice.Choice1(AsnInteger(2)))
// Create copy of sequence field0 and field1 initialised to different values
val mySequence2 =
( mySequence
.field0{
case Some(AsnInteger(x)) => Some(AsnInteger(x + 2))
case None => None
}
.field1{_ => AsnReal(3.0)}
)
println(mySequence2)
println(mySequence2.field3._choice)
println(mySequence.field3{_.choice2{_ => AsnReal(9.9)}})
println(AsnNull)
println(MySequence)
println(MyChoice)
// Using the MySequence constructor can be tedious because you need
// always supply values for all fields. An easier way to construct
// the sequence is supported: MySequence is itself a value with
// fields initialised to default values, so the alternative way to
// construct objects is:
val moo =
( MySequence
.field0{_ => Some(AsnInteger(12))}
.field1{_ => AsnReal(123.0)}
)
println(moo)
println(moo.field3.choice2{_ => AsnReal(1.23)}._choice)
println(MyEnum.value1)
However, for the choice type the need to write MyChoice.default instead of just MyChoice annoys me a lot and I am disallowed from fixing it by writing:
object MyChoice extends MyChoice.Choice0 {
The error is:
illegal cyclic reference involving object MyChoice TestGeneratedCode.scala /asn1runtimetest/src/test/asn1/genruntime line 50 Scala Problem
Any other way I can do this?
Cheers,
-John