Using const for "data classes", I'm repeating this code to update the data.
const class Person
{
Int id
Str name
new make(|This| f)
{
f(this)
// put default value if absent
}
new makeCopy(Person that, |This| f)
{
this.id = that.id
this.name = that.name
f(this)
}
This copy(|This| f)
{
makeCopy(this, f)
}
}
// Usage
p1 := Person { id = 3; name = "foo" }
p2 := p.copy { name = "bar" }
Do you use something similar? Something better? How do you do it?
SlimerDudeWed 23 Nov 2016
Hi Fraya,
Another good question!
Fantom only allows the one it-block in a ctor parameter list so in the past I've used a field map and reflection to do something like this:
const class Person {
const Int id
const Str name
new make(|This| f) { f(this) }
Person clone([Field:Obj?]? newVals := null) {
fieldVals := Field:Obj?[:]
this.typeof.fields.each {
fieldVals[it] = it.get(this)
}
if (newVals != null)
fieldVals.setAll(newVals)
planFunc := Field.makeSetFunc(fieldVals)
return Person(planFunc)
}
}
And use it like this:
p1 := Person { // create
it.id = 3
it.name = "foo"
}
p2 := p1.clone // clone p1
p3 := p2.clone([ // clone p2 & set new name
Person#name : "Bob"
])
You can't pass in a normal func to set the fields as you run into const issues.
brianWed 23 Nov 2016
I personally like a constructor that takes an original instance to copy from and an it-block to tweak individual fields:
class Foo
{
new make(Foo? orig := null, |This|? f := null)
{
if (orig != null)
{
this.a = orig.a
this.b = orig.b
}
if (f != null) f(this)
}
const Str a := "xxx"
const Str b := "yyy"
}
x := Foo(null) { it.a = "1" }
y := Foo(x) { it.a = "2" }
frayaWed 23 Nov 2016
@SlimerDude
Thank you for your response, your solution can be a mixin returning This and changing the function last line to
fraya Wed 23 Nov 2016
Using const for "data classes", I'm repeating this code to update the data.
const class Person { Int id Str name new make(|This| f) { f(this) // put default value if absent } new makeCopy(Person that, |This| f) { this.id = that.id this.name = that.name f(this) } This copy(|This| f) { makeCopy(this, f) } } // Usage p1 := Person { id = 3; name = "foo" } p2 := p.copy { name = "bar" }Do you use something similar? Something better? How do you do it?
SlimerDude Wed 23 Nov 2016
Hi Fraya,
Another good question!
Fantom only allows the one
it-blockin a ctor parameter list so in the past I've used a field map and reflection to do something like this:const class Person { const Int id const Str name new make(|This| f) { f(this) } Person clone([Field:Obj?]? newVals := null) { fieldVals := Field:Obj?[:] this.typeof.fields.each { fieldVals[it] = it.get(this) } if (newVals != null) fieldVals.setAll(newVals) planFunc := Field.makeSetFunc(fieldVals) return Person(planFunc) } }And use it like this:
p1 := Person { // create it.id = 3 it.name = "foo" } p2 := p1.clone // clone p1 p3 := p2.clone([ // clone p2 & set new name Person#name : "Bob" ])You can't pass in a normal func to set the fields as you run into
constissues.brian Wed 23 Nov 2016
I personally like a constructor that takes an original instance to copy from and an it-block to tweak individual fields:
class Foo { new make(Foo? orig := null, |This|? f := null) { if (orig != null) { this.a = orig.a this.b = orig.b } if (f != null) f(this) } const Str a := "xxx" const Str b := "yyy" } x := Foo(null) { it.a = "1" } y := Foo(x) { it.a = "2" }fraya Wed 23 Nov 2016
@SlimerDude
Thank you for your response, your solution can be a mixin returning
Thisand changing the function last line tomakeFunc := this.typeof.method("make") return makeFunc.call(planFunc)? Can I haz a Cloneable?? :)
@andy thank you, i'll test it