#2177 Synthetic fields for const mixins

SlimerDude Fri 2 Aug 2013

It's been mentioned before ( Topic 1546, Topic 1921 ) and I find I keep coming back to it... being able to define (synthetic) fields for const mixins:

const mixin Serv { 
  abstract const Str dude
}

const class MyServ : Serv { 
  override const Str dude {
    get { "stuff" }
    set { .. do stuff .. }
  }
}

As no state is being held, and the compiler has already calculated the field is synthetic, it should really be allowed.

I could have get() and set() methods, but they're ugly and look disjointed. What I really want to have is:

serv := MyServ()
serv.dude = "sweet"
var := serv.dude

Interestingly, const mixins are allowed @Operators, so I can already give more complicated map and addition behaviour to my const classes!

If synthetic fields are too tricky, I could suggest extending @Operators for basic get n set methods, but that's quite nasty and I don't think anyone wants that!

EDIT: Ah - ignore my rant above, I just found Ticket 2110.

brian Fri 2 Aug 2013

If its const you don't need the setter, so you can just make a method:

const mixin serv { 
  abstract Str dude()
}

const class servImpl : serv { 
  override const Str dude := ""
}

SlimerDude Fri 2 Aug 2013

Fat finger syndrome - I posted the comment mid-flow... I've just found Ticket 2110 anyway, so err, ignore!

SlimerDude Fri 2 Aug 2013

Stop the press! You can!

It's counter intuitive, but the trick is to NOT declare the field as const:

const mixin a {
  abstract Str dude
}

const class bb : a {
  override Str dude {
    get { "dredd" }
    set {  echo(it) }
  }
}

class Dude {
  static Void main(Str[] args) {
    bb().dude = "judge" // --> judge
    echo(bb().dude)     // --> dredd
  }
}

I'm happy it works, but err Brian, is this behaviour expected?

SlimerDude Fri 2 Aug 2013

Readonly const fields still aren't possible but it does give rise to this interesting edge case Err:

const mixin Serv {
  abstract Str dude
}

const class MyServ : Serv {
  override Str dude {
    get { "dredd" }
    private set { echo(it) }  // a private setter
  }
}

class Dude {
  static Void main(Str[] args) {
    serv := (Serv) MyServ()
    serv.dude = "judge" // compiles okay against the mixin
  }
}

gives an Err at runtime:

sys::Err: java.lang.IllegalAccessError: fan.blah.MyServ.dude(Ljava/lang/String;)V
  blah::Dude.main (Dude.fan:XX)
  java.lang.reflect.Method.invoke (Method.java:597)
  fan.sys.Method.invoke (Method.java:559)
  fan.sys.Method$MethodFunc.callList (Method.java:198)
  fan.sys.Method.callList (Method.java:138)
  fanx.tools.Fan.callMain (Fan.java:173)
  fanx.tools.Fan.executeType (Fan.java:140)
  fanx.tools.Fan.execute (Fan.java:41)
  fanx.tools.Fan.run (Fan.java:298)
  fanx.tools.Fan.main (Fan.java:336)

brian Tue 6 Aug 2013

Yeah there should probably be a compiler error there, sort of an interesting edge case. But I'm still not sure why you are trying to make it a field in the mixin versus a method like a suggested. By definition if its const, then the mixin never needs a setter.

SlimerDude Tue 6 Aug 2013

Simple - I have a const class with a synthetic getter / setter (where the field value is calculated / held elsewhere) and I wish to expose it through a mixin.

See BedSheet's HttpResponse.statusCode for an example. (Yeah, I was quick to jump on this! I was quite excited by it!)

brian Tue 6 Aug 2013

Promoted to ticket #2177 and assigned to brian

Ok, that makes sense. Probably won't fix it quickly, but definitely worth tracking

Login or Signup to reply.